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

Now gets artwork from filesystem!

This commit is contained in:
Daniel Barber 2019-03-16 19:53:37 -04:00
parent 17ed1cdecc
commit 0306f9e9b5
Signed by: danbarber
GPG Key ID: 931D8112E0103DD8
6 changed files with 64 additions and 30 deletions

View File

@ -18,8 +18,12 @@ extension MPDClient {
queueCommand(command: .playAlbum, userData: ["album": album]) queueCommand(command: .playAlbum, userData: ["album": album])
} }
func getAlbumURI(for album: Album) { func getAlbumURI(for album: Album, callback: @escaping (String?) -> Void) {
queueCommand(command: .getAlbumURI, userData: ["album": album]) queueCommand(
command: .getAlbumURI,
priority: .low,
userData: ["album": album, "callback": callback]
)
} }
func sendPlayAlbum(_ album: Album) { func sendPlayAlbum(_ album: Album) {
@ -65,30 +69,31 @@ extension MPDClient {
self.delegate?.didLoadAlbums(mpdClient: self, albums: albums) self.delegate?.didLoadAlbums(mpdClient: self, albums: albums)
} }
func albumURI(for album: Album) -> String? { func albumURI(for album: Album, callback: (String?) -> Void) {
var songURI: String? var songURI: String?
guard isConnected else { return nil } guard isConnected else { return }
print("Getting URI")
mpd_search_db_songs(self.connection, true) mpd_search_db_songs(self.connection, true)
mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM, album.title) mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM, album.title)
mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM_ARTIST, album.artist) mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_ALBUM_ARTIST, album.artist)
mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_TRACK, "1") mpd_search_add_tag_constraint(self.connection, MPD_OPERATOR_DEFAULT, MPD_TAG_TRACK, "1")
mpd_search_commit(self.connection) mpd_search_commit(self.connection)
print("Performed search")
while let mpdSong = mpd_recv_song(self.connection) { while let mpdSong = mpd_recv_song(self.connection) {
let song = Song(mpdSong) let song = Song(mpdSong)
print(song)
if songURI == nil { if songURI == nil {
songURI = song.uriString songURI = song.uriString
} }
} }
print("Got URI")
return songURI callback(
songURI?
.split(separator: "/")
.dropLast()
.joined(separator: "/")
)
} }
} }

View File

@ -38,8 +38,10 @@ extension MPDClient {
guard let album = userData["album"] as? Album else { return } guard let album = userData["album"] as? Album else { return }
sendPlayAlbum(album) sendPlayAlbum(album)
case .getAlbumURI: case .getAlbumURI:
guard let album = userData["album"] as? Album else { return } guard let album = userData["album"] as? Album,
_ = getAlbumURI(for: album) let callback = userData["callback"] as? (String?) -> Void
else { return }
albumURI(for: album, callback: callback)
} }
} }
} }

View File

@ -18,17 +18,13 @@ extension MPDClient {
} }
func idle() { func idle() {
let idleOperation = BlockOperation { if !self.isIdle && self.commandsQueued == 0 {
if !self.isIdle && self.commandsQueued == 0 { mpd_send_idle(self.connection)
mpd_send_idle(self.connection) self.isIdle = true
self.isIdle = true
let result = mpd_recv_idle(self.connection, true) let result = mpd_recv_idle(self.connection, true)
self.handleIdleResult(result) self.handleIdleResult(result)
}
} }
idleOperation.queuePriority = .veryLow
commandQueue.addOperation(idleOperation)
} }
func handleIdleResult(_ result: mpd_idle) { func handleIdleResult(_ result: mpd_idle) {

View File

@ -40,13 +40,15 @@ class MPDClient {
guard isConnected else { return } guard isConnected else { return }
noIdle() noIdle()
let commandOperation = BlockOperation() { [unowned self] in let commandOperation = BlockOperation() { [unowned self] in
self.commandsQueued -= 1 self.commandsQueued -= 1
self.sendCommand(command: command, userData: userData) self.sendCommand(command: command, userData: userData)
self.idle()
} }
commandOperation.queuePriority = priority commandOperation.queuePriority = priority
commandsQueued += 1 commandsQueued += 1
commandQueue.addOperation(commandOperation) commandQueue.addOperation(commandOperation)
idle()
} }
} }

View File

@ -58,6 +58,10 @@ struct Preferences {
return mpdLibraryDir ?? mpdLibraryDirDefault return mpdLibraryDir ?? mpdLibraryDirDefault
} }
var expandedMpdLibraryDir: String {
return NSString(string: mpdLibraryDirOrDefault).expandingTildeInPath
}
func addObserver(_ observer: NSObject, forKeyPath keyPath: String) { func addObserver(_ observer: NSObject, forKeyPath keyPath: String) {
preferences.addObserver(observer, forKeyPath: keyPath, options: .new, context: nil) preferences.addObserver(observer, forKeyPath: keyPath, options: .new, context: nil)
} }

View File

@ -13,18 +13,16 @@ import PMKFoundation
class AlbumArtService: NSObject { class AlbumArtService: NSObject {
static var shared = AlbumArtService() static var shared = AlbumArtService()
var preferences = Preferences()
var session = URLSession(configuration: .default) var session = URLSession(configuration: .default)
let cacheQueue = DispatchQueue(label: "albumArtCacheQueue", attributes: .concurrent) let cacheQueue = DispatchQueue(label: "albumArtCacheQueue", attributes: .concurrent)
let filesystemQueue = DispatchQueue(label: "albumArtFilesystemQueue", attributes: .concurrent)
func fetchAlbumArt(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) { func fetchAlbumArt(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) {
cacheQueue.async { [unowned self] in cacheQueue.async { [unowned self] in
//print("Trying cache") //print("Trying cache")
if !self.getCachedArtwork(for: album, callback: callback) { if !self.getCachedArtwork(for: album, callback: callback) {
// self.filesystemQueue.async { self.getArtworkFromFilesystem(for: album, callback: callback)
// _ = self.getArtworkFromFilesystem(for: album, callback: callback)
// }
// if !self.getArtworkFromFilesystem(for: album, callback: callback) { // if !self.getArtworkFromFilesystem(for: album, callback: callback) {
// // self.getRemoteArtwork(for: album, callback: callback) // // self.getRemoteArtwork(for: album, callback: callback)
// } // }
@ -53,11 +51,38 @@ class AlbumArtService: NSObject {
} }
} }
func getArtworkFromFilesystem(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) -> Bool { func getArtworkFromFilesystem(
print("No cache trying filesystem") for album: AlbumItem,
let uri = AppDelegate.mpdClient.getAlbumURI(for: album.album) callback: @escaping (_ image: NSImage) -> Void
print(uri) ) {
return false let coverArtFilenames = [
"folder.jpg",
"cover.jpg",
"\(album.artist) - \(album.title).jpg"
]
AppDelegate.mpdClient.getAlbumURI(
for: album.album,
callback: { (_ albumURI: String?) in
guard let albumURI = albumURI
else { return }
let musicDir = self.preferences.expandedMpdLibraryDir
let fullAlbumURI = "\(musicDir)/\(albumURI)"
for coverArtFilename in coverArtFilenames {
let coverArtURI = "\(fullAlbumURI)/\(coverArtFilename)"
if FileManager.default.fileExists(atPath: coverArtURI),
let data = FileManager.default.contents(atPath: coverArtURI),
let image = NSImage(data: data) {
self.cacheArtwork(for: album, data: data)
callback(image)
break
}
}
}
)
} }
func cacheArtwork(for album: AlbumItem, data: Data) { func cacheArtwork(for album: AlbumItem, data: Data) {