mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Refactor art service
This commit is contained in:
parent
e8b58b7686
commit
9123a25bc7
@ -30,6 +30,9 @@
|
|||||||
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5306223C019100173814 /* MPDClient+Status.swift */; };
|
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5306223C019100173814 /* MPDClient+Status.swift */; };
|
||||||
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5308223C020400173814 /* MPDClient+Command.swift */; };
|
E41E5309223C020400173814 /* MPDClient+Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5308223C020400173814 /* MPDClient+Command.swift */; };
|
||||||
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530A223C033700173814 /* MPDClient+Album.swift */; };
|
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530A223C033700173814 /* MPDClient+Album.swift */; };
|
||||||
|
E41E530E223EF4CF00173814 /* AlbumArtService+Caching.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530D223EF4CF00173814 /* AlbumArtService+Caching.swift */; };
|
||||||
|
E41E5310223EF6CE00173814 /* AlbumArtService+Remote.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E530F223EF6CE00173814 /* AlbumArtService+Remote.swift */; };
|
||||||
|
E41E5312223EF74A00173814 /* AlbumArtService+Filesystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41E5311223EF74A00173814 /* AlbumArtService+Filesystem.swift */; };
|
||||||
E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */; };
|
E41EA46C221636AF0068EF46 /* GeneralPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */; };
|
||||||
E421ACA3221F73C4008B2449 /* MediaKeyTap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */; };
|
E421ACA3221F73C4008B2449 /* MediaKeyTap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */; };
|
||||||
E421ACA4221F73C4008B2449 /* MediaKeyTap.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
E421ACA4221F73C4008B2449 /* MediaKeyTap.framework in Embed Libraries */ = {isa = PBXBuildFile; fileRef = E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
@ -186,6 +189,9 @@
|
|||||||
E41E5306223C019100173814 /* MPDClient+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Status.swift"; sourceTree = "<group>"; };
|
E41E5306223C019100173814 /* MPDClient+Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Status.swift"; sourceTree = "<group>"; };
|
||||||
E41E5308223C020400173814 /* MPDClient+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Command.swift"; sourceTree = "<group>"; };
|
E41E5308223C020400173814 /* MPDClient+Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Command.swift"; sourceTree = "<group>"; };
|
||||||
E41E530A223C033700173814 /* MPDClient+Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Album.swift"; sourceTree = "<group>"; };
|
E41E530A223C033700173814 /* MPDClient+Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MPDClient+Album.swift"; sourceTree = "<group>"; };
|
||||||
|
E41E530D223EF4CF00173814 /* AlbumArtService+Caching.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlbumArtService+Caching.swift"; sourceTree = "<group>"; };
|
||||||
|
E41E530F223EF6CE00173814 /* AlbumArtService+Remote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlbumArtService+Remote.swift"; sourceTree = "<group>"; };
|
||||||
|
E41E5311223EF74A00173814 /* AlbumArtService+Filesystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlbumArtService+Filesystem.swift"; sourceTree = "<group>"; };
|
||||||
E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPrefsViewController.swift; sourceTree = "<group>"; };
|
E41EA46B221636AF0068EF46 /* GeneralPrefsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralPrefsViewController.swift; sourceTree = "<group>"; };
|
||||||
E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaKeyTap.framework; path = Carthage/Build/Mac/MediaKeyTap.framework; sourceTree = "<group>"; };
|
E421ACA1221F73B8008B2449 /* MediaKeyTap.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaKeyTap.framework; path = Carthage/Build/Mac/MediaKeyTap.framework; sourceTree = "<group>"; };
|
||||||
E42A8F3922176D6400A13ED9 /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = "<group>"; };
|
E42A8F3922176D6400A13ED9 /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = "<group>"; };
|
||||||
@ -433,6 +439,16 @@
|
|||||||
path = mpd;
|
path = mpd;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E41E530C223EF4BA00173814 /* Extensions */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E41E530D223EF4CF00173814 /* AlbumArtService+Caching.swift */,
|
||||||
|
E41E530F223EF6CE00173814 /* AlbumArtService+Remote.swift */,
|
||||||
|
E41E5311223EF74A00173814 /* AlbumArtService+Filesystem.swift */,
|
||||||
|
);
|
||||||
|
path = Extensions;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E450AD8922262B420091BED3 /* Operations */ = {
|
E450AD8922262B420091BED3 /* Operations */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -482,6 +498,7 @@
|
|||||||
E4A83BF2222207BE0098FED6 /* Services */ = {
|
E4A83BF2222207BE0098FED6 /* Services */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
E41E530C223EF4BA00173814 /* Extensions */,
|
||||||
E4A83BF3222207D50098FED6 /* AlbumArtService.swift */,
|
E4A83BF3222207D50098FED6 /* AlbumArtService.swift */,
|
||||||
);
|
);
|
||||||
path = Services;
|
path = Services;
|
||||||
@ -727,6 +744,7 @@
|
|||||||
E4F6B460221E119B00ACF42A /* QueueDataSource.swift in Sources */,
|
E4F6B460221E119B00ACF42A /* QueueDataSource.swift in Sources */,
|
||||||
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */,
|
E4C8B53C22342005009A20F3 /* PreferencesWindowController.swift in Sources */,
|
||||||
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */,
|
E41E5307223C019100173814 /* MPDClient+Status.swift in Sources */,
|
||||||
|
E41E5310223EF6CE00173814 /* AlbumArtService+Remote.swift in Sources */,
|
||||||
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */,
|
E41E530B223C033700173814 /* MPDClient+Album.swift in Sources */,
|
||||||
E4A642DA22090CBE00067D21 /* Status.swift in Sources */,
|
E4A642DA22090CBE00067D21 /* Status.swift in Sources */,
|
||||||
E47E2FD72220720300F747E6 /* AlbumItemView.swift in Sources */,
|
E47E2FD72220720300F747E6 /* AlbumItemView.swift in Sources */,
|
||||||
@ -755,7 +773,9 @@
|
|||||||
E4A83BF4222207D50098FED6 /* AlbumArtService.swift in Sources */,
|
E4A83BF4222207D50098FED6 /* AlbumArtService.swift in Sources */,
|
||||||
E47E2FD5222071FD00F747E6 /* AlbumViewItem.swift in Sources */,
|
E47E2FD5222071FD00F747E6 /* AlbumViewItem.swift in Sources */,
|
||||||
E408D3BE220E03EE0006D9BE /* RawRepresentable.swift in Sources */,
|
E408D3BE220E03EE0006D9BE /* RawRepresentable.swift in Sources */,
|
||||||
|
E41E530E223EF4CF00173814 /* AlbumArtService+Caching.swift in Sources */,
|
||||||
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
|
E4E8CC922204F4B80024217A /* QueueViewController.swift in Sources */,
|
||||||
|
E41E5312223EF74A00173814 /* AlbumArtService+Filesystem.swift in Sources */,
|
||||||
E41E5301223BF99300173814 /* MPDClient+Queue.swift in Sources */,
|
E41E5301223BF99300173814 /* MPDClient+Queue.swift in Sources */,
|
||||||
E4EB237B220F7CF1008C70C0 /* Album.swift in Sources */,
|
E4EB237B220F7CF1008C70C0 /* Album.swift in Sources */,
|
||||||
E450AD9D2229B9050091BED3 /* String.swift in Sources */,
|
E450AD9D2229B9050091BED3 /* String.swift in Sources */,
|
||||||
|
|||||||
@ -7,11 +7,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import SwiftyJSON
|
|
||||||
import PromiseKit
|
|
||||||
import PMKFoundation
|
|
||||||
|
|
||||||
class AlbumArtService: NSObject {
|
class AlbumArtService: NSObject {
|
||||||
|
let cachedArtworkSize = 180
|
||||||
|
let cachedArtworkQuality: CGFloat = 0.5
|
||||||
|
|
||||||
static var shared = AlbumArtService()
|
static var shared = AlbumArtService()
|
||||||
var preferences = Preferences()
|
var preferences = Preferences()
|
||||||
|
|
||||||
@ -20,132 +20,8 @@ class AlbumArtService: NSObject {
|
|||||||
|
|
||||||
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")
|
|
||||||
if !self.getCachedArtwork(for: album, callback: callback) {
|
if !self.getCachedArtwork(for: album, callback: callback) {
|
||||||
self.getArtworkFromFilesystem(for: album, callback: callback)
|
self.getArtworkFromFilesystem(for: album, callback: callback)
|
||||||
// if !self.getArtworkFromFilesystem(for: album, callback: callback) {
|
|
||||||
// // self.getRemoteArtwork(for: album, callback: callback)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCachedArtwork(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) -> Bool {
|
|
||||||
guard let bundleIdentifier = Bundle.main.bundleIdentifier,
|
|
||||||
let cacheDir = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
|
||||||
.appendingPathComponent(bundleIdentifier)
|
|
||||||
else { return false }
|
|
||||||
|
|
||||||
let cacheFilePath = cacheDir.appendingPathComponent(album.hash).path
|
|
||||||
|
|
||||||
if FileManager.default.fileExists(atPath: cacheFilePath) {
|
|
||||||
guard let data = FileManager.default.contents(atPath: cacheFilePath),
|
|
||||||
let image = NSImage(data: data)
|
|
||||||
else { return true }
|
|
||||||
|
|
||||||
callback(image)
|
|
||||||
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getArtworkFromFilesystem(
|
|
||||||
for album: AlbumItem,
|
|
||||||
callback: @escaping (_ image: NSImage) -> Void
|
|
||||||
) {
|
|
||||||
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) {
|
|
||||||
|
|
||||||
let imageThumb = image.toFitBox(
|
|
||||||
size: NSSize(width: 180, height: 180)
|
|
||||||
)
|
|
||||||
self.cacheArtwork(
|
|
||||||
for: album,
|
|
||||||
data: imageThumb.jpegData(compressionQuality: 0.5)
|
|
||||||
)
|
|
||||||
callback(imageThumb)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func cacheArtwork(for album: AlbumItem, data: Data?) {
|
|
||||||
guard let bundleIdentifier = Bundle.main.bundleIdentifier,
|
|
||||||
let cacheDir = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
|
||||||
.appendingPathComponent(bundleIdentifier)
|
|
||||||
else { return }
|
|
||||||
|
|
||||||
let cacheFilePath = cacheDir.appendingPathComponent(album.hash).path
|
|
||||||
|
|
||||||
FileManager.default.createFile(atPath: cacheFilePath, contents: data, attributes: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRemoteArtwork(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) {
|
|
||||||
let albumArtWorkItem = DispatchWorkItem() {
|
|
||||||
self.getArtworkFromMusicBrainz(for: album, callback: callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
AlbumArtQueue.shared.addToQueue(workItem: albumArtWorkItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getArtworkFromMusicBrainz(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) {
|
|
||||||
guard var urlComponents = URLComponents(string: "https://musicbrainz.org/ws/2/release/")
|
|
||||||
else { return }
|
|
||||||
|
|
||||||
urlComponents.query = "query=artist:\(album.artist) AND release:\(album.title) AND country:US&limit=1&fmt=json"
|
|
||||||
|
|
||||||
guard let searchURL = urlComponents.url
|
|
||||||
else { return }
|
|
||||||
|
|
||||||
URLSession.shared.dataTask(.promise, with: searchURL).validate()
|
|
||||||
.compactMap {
|
|
||||||
JSON($0.data)
|
|
||||||
}.compactMap {
|
|
||||||
$0["releases"][0]["id"].string
|
|
||||||
}.compactMap {
|
|
||||||
URLComponents(string: "https://coverartarchive.org/release/\($0)/front-500")
|
|
||||||
}.then { (urlComponents: URLComponents?) -> Promise<(data: Data, response: URLResponse)> in
|
|
||||||
let url = urlComponents!.url
|
|
||||||
return URLSession.shared.dataTask(.promise, with: url!).validate()
|
|
||||||
}.compactMap {
|
|
||||||
self.cacheArtwork(for: album, data: $0.data)
|
|
||||||
return NSImage(data: $0.data)
|
|
||||||
}.done {
|
|
||||||
callback($0)
|
|
||||||
}.catch {
|
|
||||||
if let httpError = $0 as? PMKHTTPError {
|
|
||||||
switch httpError {
|
|
||||||
case let .badStatusCode(statusCode, _, _):
|
|
||||||
switch statusCode {
|
|
||||||
case 404:
|
|
||||||
self.cacheArtwork(for: album, data: Data())
|
|
||||||
default:
|
|
||||||
self.getRemoteArtwork(for: album, callback: callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
Persephone/Services/Extensions/AlbumArtService+Caching.swift
Normal file
43
Persephone/Services/Extensions/AlbumArtService+Caching.swift
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// AlbumArtService+Caching.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/3/17.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
extension AlbumArtService {
|
||||||
|
func getCachedArtwork(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) -> Bool {
|
||||||
|
guard let bundleIdentifier = Bundle.main.bundleIdentifier,
|
||||||
|
let cacheDir = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
||||||
|
.appendingPathComponent(bundleIdentifier)
|
||||||
|
else { return false }
|
||||||
|
|
||||||
|
let cacheFilePath = cacheDir.appendingPathComponent(album.hash).path
|
||||||
|
|
||||||
|
if FileManager.default.fileExists(atPath: cacheFilePath) {
|
||||||
|
guard let data = FileManager.default.contents(atPath: cacheFilePath),
|
||||||
|
let image = NSImage(data: data)
|
||||||
|
else { return true }
|
||||||
|
|
||||||
|
callback(image)
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cacheArtwork(for album: AlbumItem, data: Data?) {
|
||||||
|
guard let bundleIdentifier = Bundle.main.bundleIdentifier,
|
||||||
|
let cacheDir = try? FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
|
||||||
|
.appendingPathComponent(bundleIdentifier)
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
let cacheFilePath = cacheDir.appendingPathComponent(album.hash).path
|
||||||
|
|
||||||
|
FileManager.default.createFile(atPath: cacheFilePath, contents: data, attributes: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// AlbumArtService+Filesystem.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/3/17.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
extension AlbumArtService {
|
||||||
|
func getArtworkFromFilesystem(
|
||||||
|
for album: AlbumItem,
|
||||||
|
callback: @escaping (_ image: NSImage) -> Void
|
||||||
|
) {
|
||||||
|
let coverArtFilenames = [
|
||||||
|
"folder.jpg",
|
||||||
|
"cover.jpg",
|
||||||
|
"\(album.artist) - \(album.title).jpg"
|
||||||
|
]
|
||||||
|
|
||||||
|
let 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 let image = self.tryImage(coverArtURI) {
|
||||||
|
self.cacheArtwork(
|
||||||
|
for: album,
|
||||||
|
data: image.jpegData(compressionQuality: self.cachedArtworkQuality)
|
||||||
|
)
|
||||||
|
callback(image)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppDelegate.mpdClient.getAlbumURI(
|
||||||
|
for: album.album,
|
||||||
|
callback: callback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryImage(_ filePath: String) -> NSImage? {
|
||||||
|
if FileManager.default.fileExists(atPath: filePath),
|
||||||
|
let data = FileManager.default.contents(atPath: filePath),
|
||||||
|
let image = NSImage(data: data) {
|
||||||
|
|
||||||
|
let imageThumb = image.toFitBox(
|
||||||
|
size: NSSize(width: self.cachedArtworkSize, height: self.cachedArtworkSize)
|
||||||
|
)
|
||||||
|
|
||||||
|
return imageThumb
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Persephone/Services/Extensions/AlbumArtService+Remote.swift
Normal file
61
Persephone/Services/Extensions/AlbumArtService+Remote.swift
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// AlbumArtService+Remote.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Daniel Barber on 2019/3/17.
|
||||||
|
// Copyright © 2019 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
import SwiftyJSON
|
||||||
|
import PromiseKit
|
||||||
|
import PMKFoundation
|
||||||
|
|
||||||
|
extension AlbumArtService {
|
||||||
|
func getRemoteArtwork(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) {
|
||||||
|
let albumArtWorkItem = DispatchWorkItem() {
|
||||||
|
self.getArtworkFromMusicBrainz(for: album, callback: callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
AlbumArtQueue.shared.addToQueue(workItem: albumArtWorkItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getArtworkFromMusicBrainz(for album: AlbumItem, callback: @escaping (_ image: NSImage) -> Void) {
|
||||||
|
guard var urlComponents = URLComponents(string: "https://musicbrainz.org/ws/2/release/")
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
urlComponents.query = "query=artist:\(album.artist) AND release:\(album.title) AND country:US&limit=1&fmt=json"
|
||||||
|
|
||||||
|
guard let searchURL = urlComponents.url
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
URLSession.shared.dataTask(.promise, with: searchURL).validate()
|
||||||
|
.compactMap {
|
||||||
|
JSON($0.data)
|
||||||
|
}.compactMap {
|
||||||
|
$0["releases"][0]["id"].string
|
||||||
|
}.compactMap {
|
||||||
|
URLComponents(string: "https://coverartarchive.org/release/\($0)/front-500")
|
||||||
|
}.then { (urlComponents: URLComponents?) -> Promise<(data: Data, response: URLResponse)> in
|
||||||
|
let url = urlComponents!.url
|
||||||
|
return URLSession.shared.dataTask(.promise, with: url!).validate()
|
||||||
|
}.compactMap {
|
||||||
|
self.cacheArtwork(for: album, data: $0.data)
|
||||||
|
return NSImage(data: $0.data)
|
||||||
|
}.done {
|
||||||
|
callback($0)
|
||||||
|
}.catch {
|
||||||
|
if let httpError = $0 as? PMKHTTPError {
|
||||||
|
switch httpError {
|
||||||
|
case let .badStatusCode(statusCode, _, _):
|
||||||
|
switch statusCode {
|
||||||
|
case 404:
|
||||||
|
self.cacheArtwork(for: album, data: Data())
|
||||||
|
default:
|
||||||
|
self.getRemoteArtwork(for: album, callback: callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user