mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Dragged songs now have album art
This commit is contained in:
parent
dbf454f509
commit
feccf9b7df
@ -60,7 +60,7 @@ class AlbumViewItem: NSCollectionViewItem {
|
|||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song,
|
songUri: song.uriString,
|
||||||
cacheKey: album.hash
|
cacheKey: album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -136,7 +136,7 @@ class AlbumDetailView: NSViewController {
|
|||||||
|
|
||||||
func getBigCoverArt(song: Song, album: Album) {
|
func getBigCoverArt(song: Song, album: Album) {
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song.mpdSong,
|
songUri: song.mpdSong.uriString,
|
||||||
cacheKey: album.hash
|
cacheKey: album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -154,13 +154,14 @@ class AlbumDetailView: NSViewController {
|
|||||||
|
|
||||||
func cacheSmallCover(song: Song, album: Album) {
|
func cacheSmallCover(song: Song, album: Album) {
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song.mpdSong,
|
songUri: song.mpdSong.uriString,
|
||||||
cacheKey: album.hash
|
cacheKey: album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
_ = KingfisherManager.shared.retrieveImage(
|
_ = KingfisherManager.shared.retrieveImage(
|
||||||
with: .provider(provider),
|
with: .provider(provider),
|
||||||
options: [
|
options: [
|
||||||
|
.memoryCacheExpiration(.never),
|
||||||
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
|
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
|
||||||
.scaleFactor(2),
|
.scaleFactor(2),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -49,7 +49,9 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
|
|||||||
draggedSong: DraggedSong(
|
draggedSong: DraggedSong(
|
||||||
type: .albumSongItem(song.mpdSong.uriString),
|
type: .albumSongItem(song.mpdSong.uriString),
|
||||||
title: song.title,
|
title: song.title,
|
||||||
artist: song.artist
|
artist: song.artist,
|
||||||
|
album: song.album.title,
|
||||||
|
uri: song.mpdSong.uriString
|
||||||
),
|
),
|
||||||
ofType: .songPasteboardType
|
ofType: .songPasteboardType
|
||||||
)
|
)
|
||||||
@ -68,9 +70,11 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
|
|||||||
) { draggingItem, index, stop in
|
) { draggingItem, index, stop in
|
||||||
guard let item = draggingItem.item as? NSPasteboardItem,
|
guard let item = draggingItem.item as? NSPasteboardItem,
|
||||||
let draggedSong = item.draggedSong(forType: .songPasteboardType),
|
let draggedSong = item.draggedSong(forType: .songPasteboardType),
|
||||||
case let (title?, artist?) = (
|
case let (title, artist, album, uri) = (
|
||||||
draggedSong.title,
|
draggedSong.title,
|
||||||
draggedSong.artist
|
draggedSong.artist,
|
||||||
|
draggedSong.album,
|
||||||
|
draggedSong.uri
|
||||||
)
|
)
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
@ -78,7 +82,9 @@ class AlbumTracksDataSource: NSObject, NSTableViewDataSource {
|
|||||||
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
|
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
|
||||||
let draggedSongView = DraggedSongView(
|
let draggedSongView = DraggedSongView(
|
||||||
title: title,
|
title: title,
|
||||||
artist: artist
|
artist: artist,
|
||||||
|
album: album,
|
||||||
|
uri: uri
|
||||||
)
|
)
|
||||||
|
|
||||||
component.contents = draggedSongView.view.image()
|
component.contents = draggedSongView.view.image()
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class CurrentCoverArtView: NSImageView {
|
|||||||
|
|
||||||
func setSongImage(_ song: Song) {
|
func setSongImage(_ song: Song) {
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song.mpdSong,
|
songUri: song.mpdSong.uriString,
|
||||||
cacheKey: song.album.hash
|
cacheKey: song.album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,9 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
draggedSong: DraggedSong(
|
draggedSong: DraggedSong(
|
||||||
type: .queueItem(queueItem.queuePos),
|
type: .queueItem(queueItem.queuePos),
|
||||||
title: queueItem.song.title,
|
title: queueItem.song.title,
|
||||||
artist: queueItem.song.artist
|
artist: queueItem.song.artist,
|
||||||
|
album: queueItem.song.album.title,
|
||||||
|
uri: queueItem.song.mpdSong.uriString
|
||||||
),
|
),
|
||||||
ofType: .songPasteboardType
|
ofType: .songPasteboardType
|
||||||
)
|
)
|
||||||
@ -127,9 +129,11 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
guard let item = draggingItem.item as? NSPasteboardItem,
|
guard let item = draggingItem.item as? NSPasteboardItem,
|
||||||
let data = item.data(forType: .songPasteboardType),
|
let data = item.data(forType: .songPasteboardType),
|
||||||
let draggedSong = try? PropertyListDecoder().decode(DraggedSong.self, from: data),
|
let draggedSong = try? PropertyListDecoder().decode(DraggedSong.self, from: data),
|
||||||
case let (title?, artist?) = (
|
case let (title, artist, album, uri) = (
|
||||||
draggedSong.title,
|
draggedSong.title,
|
||||||
draggedSong.artist
|
draggedSong.artist,
|
||||||
|
draggedSong.album,
|
||||||
|
draggedSong.uri
|
||||||
)
|
)
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
@ -137,7 +141,9 @@ class QueueDataSource: NSObject, NSOutlineViewDataSource {
|
|||||||
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
|
let component = NSDraggingImageComponent(key: NSDraggingItem.ImageComponentKey.icon)
|
||||||
let draggedSongView = DraggedSongView(
|
let draggedSongView = DraggedSongView(
|
||||||
title: title,
|
title: title,
|
||||||
artist: artist
|
artist: artist,
|
||||||
|
album: album,
|
||||||
|
uri: uri
|
||||||
)
|
)
|
||||||
|
|
||||||
let view = draggedSongView.view
|
let view = draggedSongView.view
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class QueueSongCoverView: NSTableCellView {
|
|||||||
isPlaying = queueItem.isPlaying
|
isPlaying = queueItem.isPlaying
|
||||||
|
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song.mpdSong,
|
songUri: song.mpdSong.uriString,
|
||||||
cacheKey: song.album.hash
|
cacheKey: song.album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -16,11 +16,14 @@ class DraggedSongView: NSViewController {
|
|||||||
|
|
||||||
private let songTitle: String
|
private let songTitle: String
|
||||||
private let songArtist: String
|
private let songArtist: String
|
||||||
private var songCoverImage: NSImage?
|
private let songAlbum: String
|
||||||
|
private let songUri: String
|
||||||
|
|
||||||
init(title: String, artist: String) {
|
init(title: String, artist: String, album: String, uri: String) {
|
||||||
songTitle = title
|
songTitle = title
|
||||||
songArtist = artist
|
songArtist = artist
|
||||||
|
songAlbum = album
|
||||||
|
songUri = uri
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
}
|
}
|
||||||
@ -57,25 +60,20 @@ class DraggedSongView: NSViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setCoverArt() {
|
func setCoverArt() {
|
||||||
let mpdAlbum = MPDClient.MPDAlbum(
|
let mpdAlbum = MPDClient.MPDAlbum(title: songAlbum, artist: songArtist)
|
||||||
title: titleLabel.stringValue,
|
|
||||||
artist: artistLabel.stringValue
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
|
songUri: songUri,
|
||||||
|
cacheKey: Album(mpdAlbum: mpdAlbum).hash
|
||||||
)
|
)
|
||||||
|
|
||||||
KingfisherManager.shared.cache.retrieveImage(
|
coverImage.kf.setImage(
|
||||||
forKey: Album(mpdAlbum: mpdAlbum).hash,
|
with: .provider(provider),
|
||||||
|
placeholder: NSImage.defaultCoverArt,
|
||||||
options: [
|
options: [
|
||||||
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
|
.processor(DownsamplingImageProcessor(size: .queueSongCoverSize)),
|
||||||
.scaleFactor(2),
|
.scaleFactor(2),
|
||||||
],
|
]
|
||||||
callbackQueue: .untouch
|
)
|
||||||
) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let cacheResult):
|
|
||||||
self.coverImage.image = cacheResult.image
|
|
||||||
case .failure(_):
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,17 +10,17 @@ import Foundation
|
|||||||
import Kingfisher
|
import Kingfisher
|
||||||
|
|
||||||
public struct MPDAlbumArtImageDataProvider: ImageDataProvider {
|
public struct MPDAlbumArtImageDataProvider: ImageDataProvider {
|
||||||
let song: MPDClient.MPDSong
|
let songUri: String
|
||||||
|
|
||||||
init(song: MPDClient.MPDSong, cacheKey: String? = nil) {
|
init(songUri: String, cacheKey: String? = nil) {
|
||||||
self.song = song
|
self.songUri = songUri
|
||||||
self.cacheKey = cacheKey ?? song.uriString
|
self.cacheKey = cacheKey ?? songUri
|
||||||
}
|
}
|
||||||
|
|
||||||
public var cacheKey: String
|
public var cacheKey: String
|
||||||
|
|
||||||
public func data(handler: @escaping (Result<Data, Error>) -> Void) {
|
public func data(handler: @escaping (Result<Data, Error>) -> Void) {
|
||||||
App.mpdClient.fetchAlbumArt(song: song) { imageData in
|
App.mpdClient.fetchAlbumArt(songUri: songUri) { imageData in
|
||||||
guard let imageData = imageData
|
guard let imageData = imageData
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
@ -29,6 +29,6 @@ public struct MPDAlbumArtImageDataProvider: ImageDataProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var contentURL: String? {
|
public var contentURL: String? {
|
||||||
return song.uriString
|
return songUri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class UserNotificationsController {
|
|||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
let provider = MPDAlbumArtImageDataProvider(
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
song: song.mpdSong,
|
songUri: song.mpdSong.uriString,
|
||||||
cacheKey: song.album.hash
|
cacheKey: song.album.hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -122,11 +122,11 @@ extension MPDClient {
|
|||||||
|
|
||||||
// Song commands
|
// Song commands
|
||||||
case .fetchAlbumArt:
|
case .fetchAlbumArt:
|
||||||
guard let song = userData["song"] as? MPDSong,
|
guard let songUri = userData["songUri"] as? String,
|
||||||
let callback = userData["callback"] as? (Data?) -> Void
|
let callback = userData["callback"] as? (Data?) -> Void
|
||||||
else { return }
|
else { return }
|
||||||
|
|
||||||
sendFetchAlbumArt(for: song, callback: callback)
|
sendFetchAlbumArt(forUri: songUri, callback: callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,10 @@ import Foundation
|
|||||||
import mpdclient
|
import mpdclient
|
||||||
|
|
||||||
extension MPDClient {
|
extension MPDClient {
|
||||||
func fetchAlbumArt(song: MPDSong, callback: @escaping (Data?) -> Void) {
|
func fetchAlbumArt(songUri: String, callback: @escaping (Data?) -> Void) {
|
||||||
enqueueCommand(
|
enqueueCommand(
|
||||||
command: .fetchAlbumArt,
|
command: .fetchAlbumArt,
|
||||||
userData: ["song": song, "callback": callback]
|
userData: ["songUri": songUri, "callback": callback]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,14 +33,14 @@ extension MPDClient {
|
|||||||
return songs
|
return songs
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendFetchAlbumArt(for song: MPDSong, callback: @escaping (Data?) -> Void) -> Void {
|
func sendFetchAlbumArt(forUri songUri: String, callback: @escaping (Data?) -> Void) -> Void {
|
||||||
var imageData: Data?
|
var imageData: Data?
|
||||||
var currentOffset: Int32 = 0
|
var currentOffset: Int32 = 0
|
||||||
|
|
||||||
var size: Int?
|
var size: Int?
|
||||||
|
|
||||||
while size == nil || currentOffset < size! {
|
while size == nil || currentOffset < size! {
|
||||||
mpd_send_albumart(self.connection, song.uri, String(currentOffset))
|
mpd_send_albumart(self.connection, songUri, String(currentOffset))
|
||||||
|
|
||||||
guard let sizePair = mpd_recv_pair(self.connection) else {
|
guard let sizePair = mpd_recv_pair(self.connection) else {
|
||||||
mpd_connection_clear_error(self.connection)
|
mpd_connection_clear_error(self.connection)
|
||||||
|
|||||||
@ -53,11 +53,6 @@ extension MPDClient {
|
|||||||
return getTag(.date)
|
return getTag(.date)
|
||||||
}
|
}
|
||||||
|
|
||||||
var path: String {
|
|
||||||
return NSString(string: uriString)
|
|
||||||
.deletingLastPathComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
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 "" }
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
struct DraggedSong: Codable {
|
struct DraggedSong: Codable {
|
||||||
var type: DraggedSongType
|
var type: DraggedSongType
|
||||||
var title: String?
|
var title: String
|
||||||
var artist: String?
|
var artist: String
|
||||||
|
var album: String
|
||||||
|
var uri: String
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user