From 105de136a0f6f02178d0f2135ffd881772347b55 Mon Sep 17 00:00:00 2001 From: AM <35874441+amaroo2006@users.noreply.github.com> Date: Fri, 17 Mar 2023 13:52:40 -0700 Subject: [PATCH] overhauled Added menu bar app with basic music player info and controls, Switched to iTunes search API for album art --- Music.py | 60 +++++++++++++++++++++++++++ StatusBar.py | 44 ++++++++++++++++++++ applemusicrp.py | 108 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 Music.py create mode 100644 StatusBar.py diff --git a/Music.py b/Music.py new file mode 100644 index 0000000..794829e --- /dev/null +++ b/Music.py @@ -0,0 +1,60 @@ +from ScriptingBridge import SBObject, SBApplication +import os +import requests +import syslog + + +class Music: + def __init__(self): + self.musicApp = SBApplication.applicationWithBundleIdentifier_("com.apple.Music") + print(self.musicApp.currentTrack().name()) + def getArtURL(self, album, artist): + searchTerm = album.replace(" ", "+") + "+" + artist.split(",")[0].replace(" ", "+") + data = requests.get("https://itunes.apple.com/search?term=" + searchTerm + "&country=us&entity=album&limit=4") + url = "" + + for item in data.json()['results']: + #print(item) + if(item['collectionName'] == album and (item['artistName'] in artist or artist in item['artistName'])): + url = item['artworkUrl100'] + + if url == "": + url = "https://www.iphonefaq.org/files/styles/large/public/apple_music.jpg" + + return url + + def getTrackInfo(self): + # get track info + trackName = str(self.musicApp.currentTrack().name()) + album = str(self.musicApp.currentTrack().album()) + artist = str(self.musicApp.currentTrack().artist()) + year = str(self.musicApp.currentTrack().year()) + + # get image url as well as local copy of image + artURL = self.getArtURL(album, artist) + try: + art = self.musicApp.currentTrack().artworks()[0].rawData().get().data() + if (os.path.exists(os.path.join(os.getenv("HOME"), ".applemusicrp", "albumcover.png")) == False): + os.mkdir(os.path.join(os.getenv("HOME"), ".applemusicrp/")) + art.writeToFile_atomically_(os.path.join(os.getenv("HOME"), ".applemusicrp", "albumcover.png"), False) + + except Exception as e: + print(e) + + return [trackName, album, artist, artURL] + + def getPlayerState(self): + # get player state + playerPosition = self.musicApp.playerPosition() + playing = True if self.musicApp.playerState() == 1800426320 else False + + return [playerPosition, playing] + + def skip(self): + self.musicApp.nextTrack() + + def playPause(self): + self.musicApp.playpause() + + def backtrack(self): + self.musicApp.backTrack() \ No newline at end of file diff --git a/StatusBar.py b/StatusBar.py new file mode 100644 index 0000000..e012491 --- /dev/null +++ b/StatusBar.py @@ -0,0 +1,44 @@ +import rumps +import os + +class StatusBarApp(rumps.App): + def __init__(self, name, icon, music): + super(StatusBarApp, self).__init__(name=name, icon=icon) + self.music = music + self.menu.update([]) + + @rumps.timer(1) + def updateMenu(self,_): + trackInfo = self.music.getTrackInfo() + + self.menu.values()[0].title = trackInfo[0] + " - " + trackInfo[1] + self.menu.values()[0].icon = str(os.path.join(os.getenv("HOME"), ".applemusicrp", "albumcover.png")) + self.menu.values()[0].dimensions=(35,35) + + self.menu.update([]) + + + @rumps.clicked("Play/Pause") + def playPause(self,_): + # playing + playing = self.music.getPlayerState()[1] + if(playing): + self.menu.values()[1].title="Play" + self.updateMenu(_) + + # paused + else: + self.menu.values()[1].title="Pause" + self.updateMenu(_) + + self.music.playPause() + + @rumps.clicked("Skip") + def skip(self, _): + self.music.skip() + self.updateMenu(_) + + @rumps.clicked("Backtrack") + def shuffle(self, _): + self.music.backtrack() + self.updateMenu(_) \ No newline at end of file diff --git a/applemusicrp.py b/applemusicrp.py index 581886b..785a192 100644 --- a/applemusicrp.py +++ b/applemusicrp.py @@ -1,35 +1,89 @@ -from Foundation import * -from ScriptingBridge import * -import pypresence +#!/usr/bin/env python3.11 + +from ScriptingBridge import SBObject, SBApplication from pypresence import Presence -import coverpy +from rumps import * +from threading import Thread + +import datetime import time +import asyncio +import syslog import requests -client_id = "PUT-CLIENT-ID-HERE" # find your client ID by creating an application through the discord developer portal -music = SBApplication.applicationWithBundleIdentifier_("com.apple.Music") +import StatusBar +import Music + + +def richPresenceLoop(musicInfo): + # create asynchronous event loop for multithreaded execution + try: + asyncio.get_event_loop() + except: + asyncio.set_event_loop(asyncio.new_event_loop()) + + # application info + client_id = "1084641054055211128" + RPC = Presence(client_id) -RPC = Presence(client_id) -RPC.connect() -limit = 1 -c = coverpy.CoverPy() + # connect to discord + while True: + try: + RPC.connect() + + except: + time.sleep(2) + else: + break + + # update rich presence + while True: + try: + trackName, album, artist, artURL = musicInfo.getTrackInfo() + playerPosition = musicInfo.getPlayerState()[0] + RPC.update( + large_image = artURL, + details=trackName + + " - " + + album, + state="by " + + artist + + " - " + + str( + datetime.timedelta(minutes=0, seconds=int(playerPosition)) + )[-5:]) + + except: + time.sleep(1) + + else: + time.sleep(1) + +def main(): + + # create music object, get initial info + music = Music.Music() + trackInfo = music.getTrackInfo() + + # start rich presence + richPresence = Thread(target=richPresenceLoop, args=[music]) + richPresence.start() + + # create status bar app + app = StatusBar.StatusBarApp(name="Apple Music Rich Presence", icon="imgs/trayIcon.png", music=music) -while True: try: - result = c.get_cover(music.currentTrack().name(), limit) - - except coverpy.exceptions.NoResultsException: - print("Nothing found.") - except requests.exceptions.HTTPError: - print("Could not execute GET request") - - RPC.update( - large_image=result.artwork(100), - details=music.currentTrack().name() + " - " + music.currentTrack().album(), - state=music.currentTrack().artist(), - ) - # - # print(music.currentTrack().name() + " - " + music.currentTrack().artist()) - - time.sleep(0.5) + app.menu.add(rumps.MenuItem( + title = trackInfo[0] + " - " + trackInfo[1], + icon='imgs/default_img.png', + dimensions=(35,35))) + app.run() + + except Exception as error: + syslog.syslog(syslog.LOG_ALERT, str(error)) + syslog.syslog(syslog.LOG_ALERT, "except ran") + + +if __name__ == "__main__": + main()