Skip to content

Commit

Permalink
overhauled
Browse files Browse the repository at this point in the history
Added menu bar app with basic music player info and controls, Switched to iTunes search API for album art
  • Loading branch information
amaroo2006 committed Mar 17, 2023
1 parent b1ea8c2 commit 105de13
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 27 deletions.
60 changes: 60 additions & 0 deletions Music.py
Original file line number Diff line number Diff line change
@@ -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()
44 changes: 44 additions & 0 deletions StatusBar.py
Original file line number Diff line number Diff line change
@@ -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(_)
108 changes: 81 additions & 27 deletions applemusicrp.py
Original file line number Diff line number Diff line change
@@ -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()

0 comments on commit 105de13

Please sign in to comment.