Compare commits
No commits in common. "04a976f6f3f9f30e152575d2e40f680c4ae29b63" and "eb7509a4e04c4affc3ae17263a71dbf343777d1f" have entirely different histories.
04a976f6f3
...
eb7509a4e0
5 changed files with 4 additions and 68 deletions
|
@ -3,7 +3,7 @@ from os import environ
|
||||||
|
|
||||||
from corefoundationasyncio import CoreFoundationEventLoop
|
from corefoundationasyncio import CoreFoundationEventLoop
|
||||||
|
|
||||||
from .cocoa.now_playing import CocoaNowPlaying
|
from .cocoa import CocoaNowPlaying
|
||||||
from .mpd.listener import MpdStateListener
|
from .mpd.listener import MpdStateListener
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,8 @@ from Foundation import CGSize, NSMutableDictionary
|
||||||
from MediaPlayer import (
|
from MediaPlayer import (
|
||||||
MPMediaItemArtwork,
|
MPMediaItemArtwork,
|
||||||
MPMediaItemPropertyAlbumTitle,
|
MPMediaItemPropertyAlbumTitle,
|
||||||
MPMediaItemPropertyAlbumTrackNumber,
|
|
||||||
MPMediaItemPropertyArtist,
|
MPMediaItemPropertyArtist,
|
||||||
MPMediaItemPropertyArtwork,
|
MPMediaItemPropertyArtwork,
|
||||||
MPMediaItemPropertyComposer,
|
|
||||||
MPMediaItemPropertyDiscNumber,
|
|
||||||
MPMediaItemPropertyGenre,
|
|
||||||
MPMediaItemPropertyPersistentID,
|
|
||||||
MPMediaItemPropertyPlaybackDuration,
|
MPMediaItemPropertyPlaybackDuration,
|
||||||
MPMediaItemPropertyTitle,
|
MPMediaItemPropertyTitle,
|
||||||
MPMusicPlaybackState,
|
MPMusicPlaybackState,
|
||||||
|
@ -23,20 +18,15 @@ from MediaPlayer import (
|
||||||
MPNowPlayingInfoMediaTypeAudio,
|
MPNowPlayingInfoMediaTypeAudio,
|
||||||
MPNowPlayingInfoMediaTypeNone,
|
MPNowPlayingInfoMediaTypeNone,
|
||||||
MPNowPlayingInfoPropertyElapsedPlaybackTime,
|
MPNowPlayingInfoPropertyElapsedPlaybackTime,
|
||||||
MPNowPlayingInfoPropertyExternalContentIdentifier,
|
|
||||||
MPNowPlayingInfoPropertyMediaType,
|
MPNowPlayingInfoPropertyMediaType,
|
||||||
MPNowPlayingInfoPropertyPlaybackQueueCount,
|
|
||||||
MPNowPlayingInfoPropertyPlaybackQueueIndex,
|
|
||||||
MPNowPlayingInfoPropertyPlaybackRate,
|
|
||||||
MPRemoteCommandCenter,
|
MPRemoteCommandCenter,
|
||||||
MPRemoteCommandEvent,
|
MPRemoteCommandEvent,
|
||||||
MPRemoteCommandHandlerStatus,
|
MPRemoteCommandHandlerStatus,
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..async_tools import run_background_task
|
from .async_tools import run_background_task
|
||||||
from ..player import Player
|
from .player import Player
|
||||||
from ..song import PlaybackState, Song
|
from .song import PlaybackState, Song
|
||||||
from .persistent_id import song_to_persistent_id
|
|
||||||
|
|
||||||
|
|
||||||
def logo_to_ns_image() -> NSImage:
|
def logo_to_ns_image() -> NSImage:
|
||||||
|
@ -80,25 +70,12 @@ def song_to_media_item(song: Song) -> NSMutableDictionary:
|
||||||
nowplaying_info = nothing_to_media_item()
|
nowplaying_info = nothing_to_media_item()
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaTypeAudio
|
nowplaying_info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaTypeAudio
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = song.elapsed
|
nowplaying_info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = song.elapsed
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyExternalContentIdentifier] = song.file
|
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyPlaybackQueueCount] = song.queue_length
|
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyPlaybackQueueIndex] = song.queue_index
|
|
||||||
nowplaying_info[MPMediaItemPropertyPersistentID] = song_to_persistent_id(song)
|
|
||||||
|
|
||||||
nowplaying_info[MPMediaItemPropertyTitle] = song.title
|
nowplaying_info[MPMediaItemPropertyTitle] = song.title
|
||||||
nowplaying_info[MPMediaItemPropertyArtist] = song.artist
|
nowplaying_info[MPMediaItemPropertyArtist] = song.artist
|
||||||
nowplaying_info[MPMediaItemPropertyAlbumTitle] = song.album
|
nowplaying_info[MPMediaItemPropertyAlbumTitle] = song.album
|
||||||
nowplaying_info[MPMediaItemPropertyAlbumTrackNumber] = song.track
|
|
||||||
nowplaying_info[MPMediaItemPropertyDiscNumber] = song.disc
|
|
||||||
nowplaying_info[MPMediaItemPropertyGenre] = song.genre
|
|
||||||
nowplaying_info[MPMediaItemPropertyComposer] = song.composer
|
|
||||||
nowplaying_info[MPMediaItemPropertyPlaybackDuration] = song.duration
|
nowplaying_info[MPMediaItemPropertyPlaybackDuration] = song.duration
|
||||||
|
|
||||||
# MPD can't play back music at different rates, so we just want to set it
|
|
||||||
# to 1.0 if the song is playing. (Leave it at 0.0 if the song is paused.)
|
|
||||||
if song.state == PlaybackState.play:
|
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
|
|
||||||
|
|
||||||
if song.art:
|
if song.art:
|
||||||
nowplaying_info[MPMediaItemPropertyArtwork] = ns_image_to_media_item_artwork(
|
nowplaying_info[MPMediaItemPropertyArtwork] = ns_image_to_media_item_artwork(
|
||||||
data_to_ns_image(song.art)
|
data_to_ns_image(song.art)
|
||||||
|
@ -111,7 +88,6 @@ def nothing_to_media_item() -> NSMutableDictionary:
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaTypeNone
|
nowplaying_info[MPNowPlayingInfoPropertyMediaType] = MPNowPlayingInfoMediaTypeNone
|
||||||
nowplaying_info[MPMediaItemPropertyArtwork] = MPD_LOGO
|
nowplaying_info[MPMediaItemPropertyArtwork] = MPD_LOGO
|
||||||
nowplaying_info[MPMediaItemPropertyTitle] = "MPD (stopped)"
|
nowplaying_info[MPMediaItemPropertyTitle] = "MPD (stopped)"
|
||||||
nowplaying_info[MPNowPlayingInfoPropertyPlaybackRate] = 0.0
|
|
||||||
|
|
||||||
return nowplaying_info
|
return nowplaying_info
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
from hashlib import blake2b
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Final
|
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
from ..song import Song
|
|
||||||
|
|
||||||
# The maximum size for a BLAKE2b "person" value is sixteen bytes, so we need to be concise.
|
|
||||||
HASH_PERSON_PREFIX: Final = b"mnp.mac."
|
|
||||||
TRACKID_HASH_PERSON: Final = HASH_PERSON_PREFIX + b"mb_tid"
|
|
||||||
FILE_HASH_PERSON: Final = HASH_PERSON_PREFIX + b"f"
|
|
||||||
|
|
||||||
PERSISTENT_ID_BITS: Final = 64
|
|
||||||
PERSISTENT_ID_BYTES: Final = PERSISTENT_ID_BITS // 8
|
|
||||||
|
|
||||||
|
|
||||||
def digest_trackid(trackid: UUID) -> bytes:
|
|
||||||
return blake2b(
|
|
||||||
trackid.bytes, digest_size=PERSISTENT_ID_BYTES, person=TRACKID_HASH_PERSON
|
|
||||||
).digest()
|
|
||||||
|
|
||||||
|
|
||||||
def digest_file_uri(file: Path) -> bytes:
|
|
||||||
return blake2b(
|
|
||||||
bytes(file), digest_size=PERSISTENT_ID_BYTES, person=FILE_HASH_PERSON
|
|
||||||
).digest()
|
|
||||||
|
|
||||||
|
|
||||||
# The MPMediaItemPropertyPersistentID is only 64 bits, while a UUID is 128
|
|
||||||
# bits and not all tracks will even have their MusicBrainz track ID included.
|
|
||||||
# To work around this, we compute a BLAKE2 hash from the UUID, or failing
|
|
||||||
# that from the file URI. BLAKE2 can be customised to different digest sizes,
|
|
||||||
# making it perfect for this problem.
|
|
||||||
def song_to_persistent_id(song: Song) -> int:
|
|
||||||
if song.musicbrainz_trackid:
|
|
||||||
hashed_id = digest_trackid(song.musicbrainz_trackid)
|
|
||||||
else:
|
|
||||||
hashed_id = digest_file_uri(song.file)
|
|
||||||
return int.from_bytes(hashed_id)
|
|
|
@ -24,7 +24,6 @@ MPNowPlayingInfoPropertyMediaType: Final = "MPNowPlayingInfoPropertyMediaType"
|
||||||
MPNowPlayingInfoMediaTypeAudio: Final = 1
|
MPNowPlayingInfoMediaTypeAudio: Final = 1
|
||||||
MPNowPlayingInfoMediaTypeNone: Final = 0
|
MPNowPlayingInfoMediaTypeNone: Final = 0
|
||||||
|
|
||||||
MPNowPlayingInfoPropertyPlaybackRate: Final = "MPNowPlayingInfoPropertyPlaybackRate"
|
|
||||||
MPNowPlayingInfoPropertyPlaybackQueueCount: Final = (
|
MPNowPlayingInfoPropertyPlaybackQueueCount: Final = (
|
||||||
"MPNowPlayingInfoPropertyPlaybackQueueCount"
|
"MPNowPlayingInfoPropertyPlaybackQueueCount"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue