From 42d274058ffdc386082edfd45f723aa53c0162da Mon Sep 17 00:00:00 2001 From: Daniel Barber Date: Mon, 4 Nov 2019 19:23:01 -0500 Subject: [PATCH] WIP: Get album metadata when fetching albums --- Persephone.xcodeproj/project.pbxproj | 4 --- .../Album Browser/AlbumDataSource.swift | 28 ++++++------------- .../Album Detail/AlbumDetailView.swift | 8 +++--- .../Shared/UserNotificationsController.swift | 2 +- .../Components/Window/WindowController.swift | 3 +- .../Extensions/MPDClient+Album.swift | 15 ++++++++-- .../Extensions/MPDClient+Command.swift | 5 ++-- Persephone/MPDClient/Models/MPDAlbum.swift | 2 ++ Persephone/MPDClient/Models/MPDCommand.swift | 2 +- Persephone/MPDClient/Models/MPDSong.swift | 11 +++++++- Persephone/Models/Album.swift | 6 +++- Persephone/Models/Metadata.swift | 13 --------- Persephone/Services/CoverArtService.swift | 8 +++--- .../CoverArtService+Filesystem.swift | 13 ++------- .../State/Actions/AlbumListActions.swift | 5 ---- .../State/Reducers/AlbumListReducer.swift | 3 -- Persephone/State/Reducers/PlayerReducer.swift | 2 +- 17 files changed, 56 insertions(+), 74 deletions(-) delete mode 100644 Persephone/Models/Metadata.swift diff --git a/Persephone.xcodeproj/project.pbxproj b/Persephone.xcodeproj/project.pbxproj index e77941a..300c183 100644 --- a/Persephone.xcodeproj/project.pbxproj +++ b/Persephone.xcodeproj/project.pbxproj @@ -74,7 +74,6 @@ E489E39D22B9CF0000CA8CBD /* NSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E39C22B9CF0000CA8CBD /* NSView.swift */; }; E489E3A422B9D31800CA8CBD /* DraggedSongView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */; }; E489E3A522B9D31800CA8CBD /* DraggedSongView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */; }; - E48E92D7235113DF00A5E1BB /* Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = E48E92D6235113DF00A5E1BB /* Metadata.swift */; }; E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4928E0A2218D62A001D4BEA /* CGColor.swift */; }; E49A5482233E580800EED353 /* PromiseKit in Frameworks */ = {isa = PBXBuildFile; productRef = E49A5481233E580800EED353 /* PromiseKit */; }; E49A5485233E5ADC00EED353 /* Differ in Frameworks */ = {isa = PBXBuildFile; productRef = E49A5484233E5ADC00EED353 /* Differ */; }; @@ -279,7 +278,6 @@ E489E39C22B9CF0000CA8CBD /* NSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSView.swift; sourceTree = ""; }; E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggedSongView.swift; sourceTree = ""; }; E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DraggedSongView.xib; sourceTree = ""; }; - E48E92D6235113DF00A5E1BB /* Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metadata.swift; sourceTree = ""; }; E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = ""; }; E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = ""; }; E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = ""; }; @@ -736,7 +734,6 @@ E419E2862249B96600216A8C /* Song.swift */, E47E2FDC2220A6D100F747E6 /* Time.swift */, E4B11B72226A6C770075461B /* TrackTimer.swift */, - E48E92D6235113DF00A5E1BB /* Metadata.swift */, ); path = Models; sourceTree = ""; @@ -950,7 +947,6 @@ E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */, E41E5310223EF6CE00173814 /* CoverArtService+Remote.swift in Sources */, E442CCCD2347E73C00004E0C /* Artist.swift in Sources */, - E48E92D7235113DF00A5E1BB /* Metadata.swift in Sources */, E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */, E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */, E4235640228623D2001216D6 /* QueueSongTitleView.swift in Sources */, diff --git a/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift b/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift index be21924..50d4b12 100644 --- a/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift +++ b/Persephone/Components/Browser/Album Browser/AlbumDataSource.swift @@ -25,28 +25,18 @@ class AlbumDataSource: NSObject, NSCollectionViewDataSource { switch albums[indexPath.item].coverArt { case .notLoaded: - App.mpdClient.getAlbumFirstSong(for: albums[indexPath.item].mpdAlbum) { mpdSong in - guard let mpdSong = mpdSong else { return } + let album = albums[indexPath.item] + guard let path = album.mpdAlbum.path else { break } - DispatchQueue.main.async { - App.store.dispatch( - UpdateAlbumMetaData( - metadata: Metadata(date: mpdSong.date), - albumIndex: indexPath.item + CoverArtService(path: path, album: album) + .fetchCoverArt() + .done { image in + DispatchQueue.main.async { + App.store.dispatch( + UpdateCoverArtAction(coverArt: image, albumIndex: indexPath.item) ) - ) - } - - CoverArtService(song: Song(mpdSong: mpdSong)) - .fetchCoverArt() - .done { image in - DispatchQueue.main.async { - App.store.dispatch( - UpdateCoverArtAction(coverArt: image, albumIndex: indexPath.item) - ) - } } - } + } default: break } diff --git a/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift b/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift index 8b99cf2..0940d93 100644 --- a/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift +++ b/Persephone/Components/Browser/Album Detail/AlbumDetailView.swift @@ -49,7 +49,7 @@ class AlbumDetailView: NSViewController { getAlbumSongs(for: album) - let date = album.metadata?.date ?? "" + let date = album.mpdAlbum.date ?? "" albumTitle.stringValue = album.title albumMetadata.stringValue = "\(album.artist) · \(date)" @@ -132,12 +132,12 @@ class AlbumDetailView: NSViewController { self.dataSource.albumSongs[1].song else { return } - self.getBigCoverArt(song: song) + self.getBigCoverArt(song: song, album: album) } } - func getBigCoverArt(song: Song) { - let coverArtService = CoverArtService(song: song) + func getBigCoverArt(song: Song, album: Album) { + let coverArtService = CoverArtService(path: song.mpdSong.path, album: album) coverArtService.fetchBigCoverArt() .done(on: DispatchQueue.main) { [weak self] image in diff --git a/Persephone/Components/Shared/UserNotificationsController.swift b/Persephone/Components/Shared/UserNotificationsController.swift index 486fe2d..6825e41 100644 --- a/Persephone/Components/Shared/UserNotificationsController.swift +++ b/Persephone/Components/Shared/UserNotificationsController.swift @@ -22,7 +22,7 @@ class UserNotificationsController { status.state == .playing else { return } - let coverArtService = CoverArtService(song: currentSong) + let coverArtService = CoverArtService(path: currentSong.mpdSong.path, album: currentSong.album) coverArtService.fetchBigCoverArt() .done() { diff --git a/Persephone/Components/Window/WindowController.swift b/Persephone/Components/Window/WindowController.swift index 38c745b..7847e32 100644 --- a/Persephone/Components/Window/WindowController.swift +++ b/Persephone/Components/Window/WindowController.swift @@ -161,7 +161,8 @@ class WindowController: NSWindowController { } @IBAction func handleSearchQuery(_ sender: NSSearchField) { - App.store.dispatch(SetSearchQuery(searchQuery: sender.stringValue)) + //App.store.dispatch(SetSearchQuery(searchQuery: sender.stringValue)) + App.mpdClient.fetchAlbums(filter: sender.stringValue) } } diff --git a/Persephone/MPDClient/Extensions/MPDClient+Album.swift b/Persephone/MPDClient/Extensions/MPDClient+Album.swift index b1c17ae..d27de3c 100644 --- a/Persephone/MPDClient/Extensions/MPDClient+Album.swift +++ b/Persephone/MPDClient/Extensions/MPDClient+Album.swift @@ -11,7 +11,11 @@ import mpdclient extension MPDClient { func fetchAllAlbums() { - enqueueCommand(command: .fetchAllAlbums) + enqueueCommand(command: .fetchAlbums, userData: ["filter": ""]) + } + + func fetchAlbums(filter: String) { + enqueueCommand(command: .fetchAlbums, userData: ["filter": filter]) } func playAlbum(_ album: MPDAlbum) { @@ -49,7 +53,7 @@ extension MPDClient { } } - func allAlbums(filter: String) { + func albums(filter: String) { var albums: [MPDAlbum] = [] mpd_search_db_songs(self.connection, false) @@ -66,7 +70,12 @@ extension MPDClient { while let song = mpd_recv_song(self.connection) { let mpdSong = MPDSong(song) - let mpdAlbum = MPDAlbum(title: mpdSong.album.title, artist: mpdSong.artist) + let mpdAlbum = MPDAlbum( + title: mpdSong.album.title, + artist: mpdSong.artist, + date: mpdSong.date, + path: mpdSong.path + ) if (mpdAlbum != albums.last) { albums.append(mpdAlbum) } diff --git a/Persephone/MPDClient/Extensions/MPDClient+Command.swift b/Persephone/MPDClient/Extensions/MPDClient+Command.swift index 4af41da..049d443 100644 --- a/Persephone/MPDClient/Extensions/MPDClient+Command.swift +++ b/Persephone/MPDClient/Extensions/MPDClient+Command.swift @@ -92,8 +92,9 @@ extension MPDClient { allArtists() // Album commands - case .fetchAllAlbums: - allAlbums(filter: "") + case .fetchAlbums: + guard let filter = userData["filter"] as? String else { return } + albums(filter: filter) case .playAlbum: guard let album = userData["album"] as? MPDAlbum else { return } sendPlayAlbum(album) diff --git a/Persephone/MPDClient/Models/MPDAlbum.swift b/Persephone/MPDClient/Models/MPDAlbum.swift index 9b9bb94..e73ec8d 100644 --- a/Persephone/MPDClient/Models/MPDAlbum.swift +++ b/Persephone/MPDClient/Models/MPDAlbum.swift @@ -12,5 +12,7 @@ extension MPDClient { struct MPDAlbum: Equatable { let title: String let artist: String + var date: String? + var path: String? } } diff --git a/Persephone/MPDClient/Models/MPDCommand.swift b/Persephone/MPDClient/Models/MPDCommand.swift index 1d43119..f3dee72 100644 --- a/Persephone/MPDClient/Models/MPDCommand.swift +++ b/Persephone/MPDClient/Models/MPDCommand.swift @@ -41,7 +41,7 @@ extension MPDClient { case fetchAllArtists // Album commands - case fetchAllAlbums + case fetchAlbums case playAlbum case getAlbumFirstSong case getAlbumSongs diff --git a/Persephone/MPDClient/Models/MPDSong.swift b/Persephone/MPDClient/Models/MPDSong.swift index df4cba3..7b4c4f8 100644 --- a/Persephone/MPDClient/Models/MPDSong.swift +++ b/Persephone/MPDClient/Models/MPDSong.swift @@ -36,7 +36,9 @@ extension MPDClient { var album: MPDAlbum { return MPDAlbum( title: getTag(.album), - artist: artist + artist: artist, + date: date, + path: path ) } @@ -52,6 +54,13 @@ extension MPDClient { return getTag(.date) } + var path: String { + return uriString + .split(separator: "/") + .dropLast() + .joined(separator: "/") + } + func getTag(_ tagType: MPDTag) -> String { guard let tag = mpd_song_get_tag(song, tagType.mpdTag(), 0) else { return "" } diff --git a/Persephone/Models/Album.swift b/Persephone/Models/Album.swift index ca67bf2..9967802 100644 --- a/Persephone/Models/Album.swift +++ b/Persephone/Models/Album.swift @@ -12,7 +12,6 @@ import CryptoSwift struct Album { var mpdAlbum: MPDClient.MPDAlbum var coverArt: Loading = .notLoaded - var metadata: Metadata? init(mpdAlbum: MPDClient.MPDAlbum) { self.mpdAlbum = mpdAlbum @@ -26,6 +25,11 @@ struct Album { return mpdAlbum.artist } + var date: String { + guard let date = mpdAlbum.date else { return "" } + return date + } + var hash: String { return "\(title) - \(artist)".sha1() } diff --git a/Persephone/Models/Metadata.swift b/Persephone/Models/Metadata.swift deleted file mode 100644 index 8474e7e..0000000 --- a/Persephone/Models/Metadata.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// Metadata.swift -// Persephone -// -// Created by Daniel Barber on 2019/10/11. -// Copyright © 2019 Dan Barber. All rights reserved. -// - -import Foundation - -struct Metadata { - var date: String? -} diff --git a/Persephone/Services/CoverArtService.swift b/Persephone/Services/CoverArtService.swift index 5782c7d..d8f2d28 100644 --- a/Persephone/Services/CoverArtService.swift +++ b/Persephone/Services/CoverArtService.swift @@ -10,7 +10,7 @@ import AppKit import PromiseKit class CoverArtService { - let song: Song + let path: String let album: Album let cachedArtworkSize = 180 @@ -21,9 +21,9 @@ class CoverArtService { var session = URLSession(configuration: .default) let coverArtQueue = DispatchQueue(label: "coverArtQueue", qos: .utility) - init(song: Song) { - self.song = song - self.album = song.album + init(path: String, album: Album) { + self.path = path + self.album = album } func fetchBigCoverArt() -> Promise { diff --git a/Persephone/Services/Extensions/CoverArtService+Filesystem.swift b/Persephone/Services/Extensions/CoverArtService+Filesystem.swift index 36f794b..98a45fd 100644 --- a/Persephone/Services/Extensions/CoverArtService+Filesystem.swift +++ b/Persephone/Services/Extensions/CoverArtService+Filesystem.swift @@ -40,7 +40,7 @@ extension CoverArtService { if self.fileSystemArtworkFilePath() == nil { FileManager.default.createFile( - atPath: "\(self.musicDir)/\(self.songPath)/\(artworkFileName)", + atPath: "\(self.musicDir)/\(self.path)/\(artworkFileName)", contents: data, attributes: nil ) @@ -52,21 +52,12 @@ extension CoverArtService { return self.coverArtFilenames .lazy - .map { "\(musicDir)/\(self.songPath)/\($0)" } + .map { "\(musicDir)/\(self.path)/\($0)" } .first { FileManager.default.fileExists(atPath: $0) } } - var songPath: String { - return song - .mpdSong - .uriString - .split(separator: "/") - .dropLast() - .joined(separator: "/") - } - func tryImage(_ filePath: String) -> NSImage? { guard let data = FileManager.default.contents(atPath: filePath), let image = NSImage(data: data) diff --git a/Persephone/State/Actions/AlbumListActions.swift b/Persephone/State/Actions/AlbumListActions.swift index 1457335..bab922c 100644 --- a/Persephone/State/Actions/AlbumListActions.swift +++ b/Persephone/State/Actions/AlbumListActions.swift @@ -16,11 +16,6 @@ struct UpdateCoverArtAction: Action { var albumIndex: Int } -struct UpdateAlbumMetaData: Action { - var metadata: Metadata - var albumIndex: Int -} - struct UpdateAlbumListAction: Action { var albums: [MPDClient.MPDAlbum] } diff --git a/Persephone/State/Reducers/AlbumListReducer.swift b/Persephone/State/Reducers/AlbumListReducer.swift index ea5603d..f97a7ff 100644 --- a/Persephone/State/Reducers/AlbumListReducer.swift +++ b/Persephone/State/Reducers/AlbumListReducer.swift @@ -18,9 +18,6 @@ func albumListReducer(action: Action, state: AlbumListState?) -> AlbumListState case let action as UpdateCoverArtAction: state.albums[action.albumIndex].coverArt = .loaded(action.coverArt) - case let action as UpdateAlbumMetaData: - state.albums[action.albumIndex].metadata = action.metadata - case is ResetAlbumListCoverArtAction: state.albums = state.albums.map { var album = $0 diff --git a/Persephone/State/Reducers/PlayerReducer.swift b/Persephone/State/Reducers/PlayerReducer.swift index 04938de..62bab20 100644 --- a/Persephone/State/Reducers/PlayerReducer.swift +++ b/Persephone/State/Reducers/PlayerReducer.swift @@ -40,7 +40,7 @@ func playerReducer(action: Action, state: PlayerState?) -> PlayerState { state.currentSong = action.currentSong if let currentSong = state.currentSong { - let coverArtService = CoverArtService(song: currentSong) + let coverArtService = CoverArtService(path: currentSong.mpdSong.path, album: currentSong.album) coverArtService.fetchBigCoverArt() .done() { image in