mirror of
https://github.com/danbee/persephone
synced 2025-03-04 08:39:11 +00:00
Use MPNowPlayingInfoCenter to player info
This means that the notications bar media player will show track & artist title, as well as artwork for the album. It also means that Play/Pause/Next/Previous work without needing accessibility access
This commit is contained in:
parent
3b330f1c78
commit
a0f1942ba8
@ -12,6 +12,8 @@ struct App {
|
|||||||
static let store = Store<AppState>(reducer: appReducer, state: nil)
|
static let store = Store<AppState>(reducer: appReducer, state: nil)
|
||||||
static let trackTimer = TrackTimer()
|
static let trackTimer = TrackTimer()
|
||||||
static let userNotificationsController = UserNotificationsController()
|
static let userNotificationsController = UserNotificationsController()
|
||||||
|
static let mediaInfoController = MediaInfoController()
|
||||||
|
static let playerStateInfoController = PlayerStateInfoController()
|
||||||
static let mpdServerDelegate = MPDServerDelegate()
|
static let mpdServerDelegate = MPDServerDelegate()
|
||||||
static let mpdServerController = MPDServerController(delegate: mpdServerDelegate)
|
static let mpdServerController = MPDServerController(delegate: mpdServerDelegate)
|
||||||
static var mpdClient: MPDClient!
|
static var mpdClient: MPDClient!
|
||||||
|
|||||||
@ -40,6 +40,8 @@ class AppDelegate: NSObject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = App.userNotificationsController
|
_ = App.userNotificationsController
|
||||||
|
_ = App.mediaInfoController
|
||||||
|
_ = App.playerStateInfoController
|
||||||
|
|
||||||
_ = App.mpdServerController
|
_ = App.mpdServerController
|
||||||
}
|
}
|
||||||
|
|||||||
76
Mac/Components/Shared/MediaInfoController.swift
Normal file
76
Mac/Components/Shared/MediaInfoController.swift
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// MediaInfoController.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Alan Harper on 18/11/20.
|
||||||
|
// Copyright © 2020 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ReSwift
|
||||||
|
import MediaPlayer
|
||||||
|
import Kingfisher
|
||||||
|
|
||||||
|
class MediaInfoController {
|
||||||
|
init() {
|
||||||
|
App.store.subscribe(self) {
|
||||||
|
$0.select { $0.playerState.currentSong }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyTrack(_ song: Song) {
|
||||||
|
let provider = MPDAlbumArtImageDataProvider(
|
||||||
|
songUri: song.mpdSong.uriString,
|
||||||
|
cacheKey: song.album.hash
|
||||||
|
)
|
||||||
|
|
||||||
|
let infoCenter = MPNowPlayingInfoCenter.default()
|
||||||
|
|
||||||
|
var nowPlayingInfo = [
|
||||||
|
MPMediaItemPropertyTitle: song.title,
|
||||||
|
MPMediaItemPropertyArtist: song.artist,
|
||||||
|
MPMediaItemPropertyAlbumArtist: song.album.artist,
|
||||||
|
MPMediaItemPropertyAlbumTitle: song.album.title,
|
||||||
|
MPMediaItemPropertyPlaybackDuration: NSNumber(value: song.duration.timeInSeconds),
|
||||||
|
MPNowPlayingInfoPropertyMediaType: NSNumber(value: MPNowPlayingInfoMediaType.audio.rawValue),
|
||||||
|
MPNowPlayingInfoPropertyIsLiveStream: NSNumber(value: false),
|
||||||
|
] as [String : Any]
|
||||||
|
|
||||||
|
if let elapsedTime = App.store.state.playerState.elapsedTimeMs {
|
||||||
|
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = NSNumber(value: elapsedTime / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
if #available(OSX 10.13.2, *) {
|
||||||
|
_ = KingfisherManager.shared.retrieveImage(
|
||||||
|
with: .provider(provider),
|
||||||
|
options: [
|
||||||
|
.processor(DownsamplingImageProcessor(size: .notificationCoverSize)),
|
||||||
|
.scaleFactor(2),
|
||||||
|
]
|
||||||
|
) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let value):
|
||||||
|
let artwork = MPMediaItemArtwork.init(boundsSize: CGSize(width: 100.0, height: 100.0)) { (size: CGSize) in value.image }
|
||||||
|
nowPlayingInfo[MPMediaItemPropertyArtwork] = artwork
|
||||||
|
infoCenter.nowPlayingInfo = nowPlayingInfo
|
||||||
|
case .failure:
|
||||||
|
infoCenter.nowPlayingInfo = nowPlayingInfo
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
infoCenter.nowPlayingInfo = nowPlayingInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MediaInfoController: StoreSubscriber {
|
||||||
|
typealias StoreSubscriberStateType = Song?
|
||||||
|
|
||||||
|
|
||||||
|
func newState(state: StoreSubscriberStateType) {
|
||||||
|
guard let song = state else {return}
|
||||||
|
|
||||||
|
notifyTrack(song)
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Mac/Components/Shared/PlayerStateInfoController.swift
Normal file
72
Mac/Components/Shared/PlayerStateInfoController.swift
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// MediaInfoController.swift
|
||||||
|
// Persephone
|
||||||
|
//
|
||||||
|
// Created by Alan Harper on 18/11/20.
|
||||||
|
// Copyright © 2020 Dan Barber. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ReSwift
|
||||||
|
import MediaPlayer
|
||||||
|
import Kingfisher
|
||||||
|
|
||||||
|
class PlayerStateInfoController {
|
||||||
|
init() {
|
||||||
|
App.store.subscribe(self) {
|
||||||
|
$0.select { $0.playerState.state }
|
||||||
|
}
|
||||||
|
let commandCenter = MPRemoteCommandCenter.shared()
|
||||||
|
commandCenter.playCommand.addTarget { _ in
|
||||||
|
App.mpdClient.playPause()
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
commandCenter.togglePlayPauseCommand.addTarget { _ in
|
||||||
|
App.mpdClient.playPause()
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
commandCenter.pauseCommand.addTarget { _ in
|
||||||
|
App.mpdClient.playPause()
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
|
||||||
|
commandCenter.nextTrackCommand.addTarget { _ in
|
||||||
|
App.mpdClient.nextTrack()
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
|
||||||
|
commandCenter.previousTrackCommand.addTarget { _ in
|
||||||
|
App.mpdClient.prevTrack()
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyState(_ state: MPDClient.MPDStatus.State?) {
|
||||||
|
let infoCenter = MPNowPlayingInfoCenter.default()
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
|
case .unknown:
|
||||||
|
infoCenter.playbackState = .unknown
|
||||||
|
break;
|
||||||
|
case .paused:
|
||||||
|
infoCenter.playbackState = .paused
|
||||||
|
break;
|
||||||
|
case .stopped:
|
||||||
|
infoCenter.playbackState = .stopped
|
||||||
|
break;
|
||||||
|
case .playing:
|
||||||
|
infoCenter.playbackState = .playing
|
||||||
|
break;
|
||||||
|
case .none:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PlayerStateInfoController: StoreSubscriber {
|
||||||
|
typealias StoreSubscriberStateType = MPDClient.MPDStatus.State?
|
||||||
|
|
||||||
|
func newState(state: StoreSubscriberStateType) {
|
||||||
|
notifyState(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -307,6 +307,8 @@
|
|||||||
E4FF7190227601B400D4C412 /* PreferencesReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF718F227601B400D4C412 /* PreferencesReducer.swift */; };
|
E4FF7190227601B400D4C412 /* PreferencesReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF718F227601B400D4C412 /* PreferencesReducer.swift */; };
|
||||||
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF71912276029000D4C412 /* PreferencesActions.swift */; };
|
E4FF71922276029000D4C412 /* PreferencesActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF71912276029000D4C412 /* PreferencesActions.swift */; };
|
||||||
E4FF71942276043A00D4C412 /* MPDServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF71932276043A00D4C412 /* MPDServer.swift */; };
|
E4FF71942276043A00D4C412 /* MPDServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4FF71932276043A00D4C412 /* MPDServer.swift */; };
|
||||||
|
E72BF0CE2567F45E00419CB0 /* PlayerStateInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E72BF0CD2567F45E00419CB0 /* PlayerStateInfoController.swift */; };
|
||||||
|
E7AF1B642565124D00057784 /* MediaInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7AF1B632565124D00057784 /* MediaInfoController.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -650,6 +652,8 @@
|
|||||||
E4FF718F227601B400D4C412 /* PreferencesReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesReducer.swift; sourceTree = "<group>"; };
|
E4FF718F227601B400D4C412 /* PreferencesReducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesReducer.swift; sourceTree = "<group>"; };
|
||||||
E4FF71912276029000D4C412 /* PreferencesActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesActions.swift; sourceTree = "<group>"; };
|
E4FF71912276029000D4C412 /* PreferencesActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesActions.swift; sourceTree = "<group>"; };
|
||||||
E4FF71932276043A00D4C412 /* MPDServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDServer.swift; sourceTree = "<group>"; };
|
E4FF71932276043A00D4C412 /* MPDServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MPDServer.swift; sourceTree = "<group>"; };
|
||||||
|
E72BF0CD2567F45E00419CB0 /* PlayerStateInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerStateInfoController.swift; sourceTree = "<group>"; };
|
||||||
|
E7AF1B632565124D00057784 /* MediaInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaInfoController.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -958,6 +962,8 @@
|
|||||||
E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */,
|
E489E3A222B9D31800CA8CBD /* DraggedSongView.swift */,
|
||||||
E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */,
|
E489E3A322B9D31800CA8CBD /* DraggedSongView.xib */,
|
||||||
E4B11BB52275374B0075461B /* UserNotificationsController.swift */,
|
E4B11BB52275374B0075461B /* UserNotificationsController.swift */,
|
||||||
|
E7AF1B632565124D00057784 /* MediaInfoController.swift */,
|
||||||
|
E72BF0CD2567F45E00419CB0 /* PlayerStateInfoController.swift */,
|
||||||
);
|
);
|
||||||
path = Shared;
|
path = Shared;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1643,6 +1649,7 @@
|
|||||||
E48059D82426D73600362CF3 /* database.c in Sources */,
|
E48059D82426D73600362CF3 /* database.c in Sources */,
|
||||||
E43AC1F522C6A4F4001E483C /* DraggedAlbum.swift in Sources */,
|
E43AC1F522C6A4F4001E483C /* DraggedAlbum.swift in Sources */,
|
||||||
E40FE71B221B904300A4223F /* NSEvent.swift in Sources */,
|
E40FE71B221B904300A4223F /* NSEvent.swift in Sources */,
|
||||||
|
E72BF0CE2567F45E00419CB0 /* PlayerStateInfoController.swift in Sources */,
|
||||||
E4B11BB62275374B0075461B /* UserNotificationsController.swift in Sources */,
|
E4B11BB62275374B0075461B /* UserNotificationsController.swift in Sources */,
|
||||||
E43AC1F622C6AD0B001E483C /* AlbumViewController+NSCollectionViewDelegate.swift in Sources */,
|
E43AC1F622C6AD0B001E483C /* AlbumViewController+NSCollectionViewDelegate.swift in Sources */,
|
||||||
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
E4B11B68226A4FA00075461B /* QueueState.swift in Sources */,
|
||||||
@ -1674,6 +1681,7 @@
|
|||||||
E4805A0A2426D73600362CF3 /* sync.c in Sources */,
|
E4805A0A2426D73600362CF3 /* sync.c in Sources */,
|
||||||
E4DA820623D6236200C1EE58 /* NSSize.swift in Sources */,
|
E4DA820623D6236200C1EE58 /* NSSize.swift in Sources */,
|
||||||
E408D3B6220DD8970006D9BE /* Notification.swift in Sources */,
|
E408D3B6220DD8970006D9BE /* Notification.swift in Sources */,
|
||||||
|
E7AF1B642565124D00057784 /* MediaInfoController.swift in Sources */,
|
||||||
E48059E42426D73600362CF3 /* run.c in Sources */,
|
E48059E42426D73600362CF3 /* run.c in Sources */,
|
||||||
E4805A1A2426D73600362CF3 /* cmessage.c in Sources */,
|
E4805A1A2426D73600362CF3 /* cmessage.c in Sources */,
|
||||||
E48059C42426D73600362CF3 /* replay_gain.c in Sources */,
|
E48059C42426D73600362CF3 /* replay_gain.c in Sources */,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user