1
1
mirror of https://github.com/danbee/persephone synced 2025-03-04 08:39:11 +00:00

WIP: Get album metadata when fetching albums

This commit is contained in:
Daniel Barber 2019-11-04 19:23:01 -05:00
parent 4af3e7aead
commit 42d274058f
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
17 changed files with 56 additions and 74 deletions

View File

@ -74,7 +74,6 @@
E489E39D22B9CF0000CA8CBD /* NSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E39C22B9CF0000CA8CBD /* NSView.swift */; }; E489E39D22B9CF0000CA8CBD /* NSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E39C22B9CF0000CA8CBD /* NSView.swift */; };
E489E3A422B9D31800CA8CBD /* DraggedSongView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */; }; E489E3A422B9D31800CA8CBD /* DraggedSongView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */; };
E489E3A522B9D31800CA8CBD /* DraggedSongView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */; }; 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 */; }; E4928E0B2218D62A001D4BEA /* CGColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4928E0A2218D62A001D4BEA /* CGColor.swift */; };
E49A5482233E580800EED353 /* PromiseKit in Frameworks */ = {isa = PBXBuildFile; productRef = E49A5481233E580800EED353 /* PromiseKit */; }; E49A5482233E580800EED353 /* PromiseKit in Frameworks */ = {isa = PBXBuildFile; productRef = E49A5481233E580800EED353 /* PromiseKit */; };
E49A5485233E5ADC00EED353 /* Differ in Frameworks */ = {isa = PBXBuildFile; productRef = E49A5484233E5ADC00EED353 /* Differ */; }; 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 = "<group>"; }; E489E39C22B9CF0000CA8CBD /* NSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSView.swift; sourceTree = "<group>"; };
E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggedSongView.swift; sourceTree = "<group>"; }; E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggedSongView.swift; sourceTree = "<group>"; };
E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DraggedSongView.xib; sourceTree = "<group>"; }; E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = DraggedSongView.xib; sourceTree = "<group>"; };
E48E92D6235113DF00A5E1BB /* Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metadata.swift; sourceTree = "<group>"; };
E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = "<group>"; }; E4928E0A2218D62A001D4BEA /* CGColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGColor.swift; sourceTree = "<group>"; };
E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = "<group>"; }; E4A3A6A022A457B600EA2C40 /* AlbumDetailSongListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumDetailSongListView.swift; sourceTree = "<group>"; };
E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = "<group>"; }; E4A642D922090CBE00067D21 /* MPDStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDStatus.swift; sourceTree = "<group>"; };
@ -736,7 +734,6 @@
E419E2862249B96600216A8C /* Song.swift */, E419E2862249B96600216A8C /* Song.swift */,
E47E2FDC2220A6D100F747E6 /* Time.swift */, E47E2FDC2220A6D100F747E6 /* Time.swift */,
E4B11B72226A6C770075461B /* TrackTimer.swift */, E4B11B72226A6C770075461B /* TrackTimer.swift */,
E48E92D6235113DF00A5E1BB /* Metadata.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -950,7 +947,6 @@
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */, E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */,
E41E5310223EF6CE00173814 /* CoverArtService+Remote.swift in Sources */, E41E5310223EF6CE00173814 /* CoverArtService+Remote.swift in Sources */,
E442CCCD2347E73C00004E0C /* Artist.swift in Sources */, E442CCCD2347E73C00004E0C /* Artist.swift in Sources */,
E48E92D7235113DF00A5E1BB /* Metadata.swift in Sources */,
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */, E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */,
E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */, E42410B62241B956005ED6DF /* MPDClient+Database.swift in Sources */,
E4235640228623D2001216D6 /* QueueSongTitleView.swift in Sources */, E4235640228623D2001216D6 /* QueueSongTitleView.swift in Sources */,

View File

@ -25,28 +25,18 @@ class AlbumDataSource: NSObject, NSCollectionViewDataSource {
switch albums[indexPath.item].coverArt { switch albums[indexPath.item].coverArt {
case .notLoaded: case .notLoaded:
App.mpdClient.getAlbumFirstSong(for: albums[indexPath.item].mpdAlbum) { mpdSong in let album = albums[indexPath.item]
guard let mpdSong = mpdSong else { return } guard let path = album.mpdAlbum.path else { break }
DispatchQueue.main.async { CoverArtService(path: path, album: album)
App.store.dispatch( .fetchCoverArt()
UpdateAlbumMetaData( .done { image in
metadata: Metadata(date: mpdSong.date), DispatchQueue.main.async {
albumIndex: indexPath.item 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: default:
break break
} }

View File

@ -49,7 +49,7 @@ class AlbumDetailView: NSViewController {
getAlbumSongs(for: album) getAlbumSongs(for: album)
let date = album.metadata?.date ?? "" let date = album.mpdAlbum.date ?? ""
albumTitle.stringValue = album.title albumTitle.stringValue = album.title
albumMetadata.stringValue = "\(album.artist) · \(date)" albumMetadata.stringValue = "\(album.artist) · \(date)"
@ -132,12 +132,12 @@ class AlbumDetailView: NSViewController {
self.dataSource.albumSongs[1].song self.dataSource.albumSongs[1].song
else { return } else { return }
self.getBigCoverArt(song: song) self.getBigCoverArt(song: song, album: album)
} }
} }
func getBigCoverArt(song: Song) { func getBigCoverArt(song: Song, album: Album) {
let coverArtService = CoverArtService(song: song) let coverArtService = CoverArtService(path: song.mpdSong.path, album: album)
coverArtService.fetchBigCoverArt() coverArtService.fetchBigCoverArt()
.done(on: DispatchQueue.main) { [weak self] image in .done(on: DispatchQueue.main) { [weak self] image in

View File

@ -22,7 +22,7 @@ class UserNotificationsController {
status.state == .playing status.state == .playing
else { return } else { return }
let coverArtService = CoverArtService(song: currentSong) let coverArtService = CoverArtService(path: currentSong.mpdSong.path, album: currentSong.album)
coverArtService.fetchBigCoverArt() coverArtService.fetchBigCoverArt()
.done() { .done() {

View File

@ -161,7 +161,8 @@ class WindowController: NSWindowController {
} }
@IBAction func handleSearchQuery(_ sender: NSSearchField) { @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)
} }
} }

View File

@ -11,7 +11,11 @@ import mpdclient
extension MPDClient { extension MPDClient {
func fetchAllAlbums() { func fetchAllAlbums() {
enqueueCommand(command: .fetchAllAlbums) enqueueCommand(command: .fetchAlbums, userData: ["filter": ""])
}
func fetchAlbums(filter: String) {
enqueueCommand(command: .fetchAlbums, userData: ["filter": filter])
} }
func playAlbum(_ album: MPDAlbum) { func playAlbum(_ album: MPDAlbum) {
@ -49,7 +53,7 @@ extension MPDClient {
} }
} }
func allAlbums(filter: String) { func albums(filter: String) {
var albums: [MPDAlbum] = [] var albums: [MPDAlbum] = []
mpd_search_db_songs(self.connection, false) mpd_search_db_songs(self.connection, false)
@ -66,7 +70,12 @@ extension MPDClient {
while let song = mpd_recv_song(self.connection) { while let song = mpd_recv_song(self.connection) {
let mpdSong = MPDSong(song) 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) { if (mpdAlbum != albums.last) {
albums.append(mpdAlbum) albums.append(mpdAlbum)
} }

View File

@ -92,8 +92,9 @@ extension MPDClient {
allArtists() allArtists()
// Album commands // Album commands
case .fetchAllAlbums: case .fetchAlbums:
allAlbums(filter: "") guard let filter = userData["filter"] as? String else { return }
albums(filter: filter)
case .playAlbum: case .playAlbum:
guard let album = userData["album"] as? MPDAlbum else { return } guard let album = userData["album"] as? MPDAlbum else { return }
sendPlayAlbum(album) sendPlayAlbum(album)

View File

@ -12,5 +12,7 @@ extension MPDClient {
struct MPDAlbum: Equatable { struct MPDAlbum: Equatable {
let title: String let title: String
let artist: String let artist: String
var date: String?
var path: String?
} }
} }

View File

@ -41,7 +41,7 @@ extension MPDClient {
case fetchAllArtists case fetchAllArtists
// Album commands // Album commands
case fetchAllAlbums case fetchAlbums
case playAlbum case playAlbum
case getAlbumFirstSong case getAlbumFirstSong
case getAlbumSongs case getAlbumSongs

View File

@ -36,7 +36,9 @@ extension MPDClient {
var album: MPDAlbum { var album: MPDAlbum {
return MPDAlbum( return MPDAlbum(
title: getTag(.album), title: getTag(.album),
artist: artist artist: artist,
date: date,
path: path
) )
} }
@ -52,6 +54,13 @@ extension MPDClient {
return getTag(.date) return getTag(.date)
} }
var path: String {
return uriString
.split(separator: "/")
.dropLast()
.joined(separator: "/")
}
func getTag(_ tagType: MPDTag) -> String { func getTag(_ tagType: MPDTag) -> String {
guard let tag = mpd_song_get_tag(song, tagType.mpdTag(), 0) guard let tag = mpd_song_get_tag(song, tagType.mpdTag(), 0)
else { return "" } else { return "" }

View File

@ -12,7 +12,6 @@ import CryptoSwift
struct Album { struct Album {
var mpdAlbum: MPDClient.MPDAlbum var mpdAlbum: MPDClient.MPDAlbum
var coverArt: Loading<NSImage?> = .notLoaded var coverArt: Loading<NSImage?> = .notLoaded
var metadata: Metadata?
init(mpdAlbum: MPDClient.MPDAlbum) { init(mpdAlbum: MPDClient.MPDAlbum) {
self.mpdAlbum = mpdAlbum self.mpdAlbum = mpdAlbum
@ -26,6 +25,11 @@ struct Album {
return mpdAlbum.artist return mpdAlbum.artist
} }
var date: String {
guard let date = mpdAlbum.date else { return "" }
return date
}
var hash: String { var hash: String {
return "\(title) - \(artist)".sha1() return "\(title) - \(artist)".sha1()
} }

View File

@ -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?
}

View File

@ -10,7 +10,7 @@ import AppKit
import PromiseKit import PromiseKit
class CoverArtService { class CoverArtService {
let song: Song let path: String
let album: Album let album: Album
let cachedArtworkSize = 180 let cachedArtworkSize = 180
@ -21,9 +21,9 @@ class CoverArtService {
var session = URLSession(configuration: .default) var session = URLSession(configuration: .default)
let coverArtQueue = DispatchQueue(label: "coverArtQueue", qos: .utility) let coverArtQueue = DispatchQueue(label: "coverArtQueue", qos: .utility)
init(song: Song) { init(path: String, album: Album) {
self.song = song self.path = path
self.album = song.album self.album = album
} }
func fetchBigCoverArt() -> Promise<NSImage?> { func fetchBigCoverArt() -> Promise<NSImage?> {

View File

@ -40,7 +40,7 @@ extension CoverArtService {
if self.fileSystemArtworkFilePath() == nil { if self.fileSystemArtworkFilePath() == nil {
FileManager.default.createFile( FileManager.default.createFile(
atPath: "\(self.musicDir)/\(self.songPath)/\(artworkFileName)", atPath: "\(self.musicDir)/\(self.path)/\(artworkFileName)",
contents: data, contents: data,
attributes: nil attributes: nil
) )
@ -52,21 +52,12 @@ extension CoverArtService {
return self.coverArtFilenames return self.coverArtFilenames
.lazy .lazy
.map { "\(musicDir)/\(self.songPath)/\($0)" } .map { "\(musicDir)/\(self.path)/\($0)" }
.first { .first {
FileManager.default.fileExists(atPath: $0) FileManager.default.fileExists(atPath: $0)
} }
} }
var songPath: String {
return song
.mpdSong
.uriString
.split(separator: "/")
.dropLast()
.joined(separator: "/")
}
func tryImage(_ filePath: String) -> NSImage? { func tryImage(_ filePath: String) -> NSImage? {
guard let data = FileManager.default.contents(atPath: filePath), guard let data = FileManager.default.contents(atPath: filePath),
let image = NSImage(data: data) let image = NSImage(data: data)

View File

@ -16,11 +16,6 @@ struct UpdateCoverArtAction: Action {
var albumIndex: Int var albumIndex: Int
} }
struct UpdateAlbumMetaData: Action {
var metadata: Metadata
var albumIndex: Int
}
struct UpdateAlbumListAction: Action { struct UpdateAlbumListAction: Action {
var albums: [MPDClient.MPDAlbum] var albums: [MPDClient.MPDAlbum]
} }

View File

@ -18,9 +18,6 @@ func albumListReducer(action: Action, state: AlbumListState?) -> AlbumListState
case let action as UpdateCoverArtAction: case let action as UpdateCoverArtAction:
state.albums[action.albumIndex].coverArt = .loaded(action.coverArt) state.albums[action.albumIndex].coverArt = .loaded(action.coverArt)
case let action as UpdateAlbumMetaData:
state.albums[action.albumIndex].metadata = action.metadata
case is ResetAlbumListCoverArtAction: case is ResetAlbumListCoverArtAction:
state.albums = state.albums.map { state.albums = state.albums.map {
var album = $0 var album = $0

View File

@ -40,7 +40,7 @@ func playerReducer(action: Action, state: PlayerState?) -> PlayerState {
state.currentSong = action.currentSong state.currentSong = action.currentSong
if let currentSong = state.currentSong { if let currentSong = state.currentSong {
let coverArtService = CoverArtService(song: currentSong) let coverArtService = CoverArtService(path: currentSong.mpdSong.path, album: currentSong.album)
coverArtService.fetchBigCoverArt() coverArtService.fetchBigCoverArt()
.done() { image in .done() { image in