Album artwork working,

Rating working
Problem with quiting where worker thread doesn't quit along with the GUI
This commit is contained in:
2015-03-23 17:31:36 +01:00
commit 78113cf862
3 changed files with 277 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python
import applescript
import os
class iTunesBridge:
def __init__(self, script_file="./itunes_scripts.scpt"):
with open("./itunes_scripts.scpt") as script_file:
script_data = ''.join([line for line in script_file])
self.as_bridge = applescript.AppleScript(script_data)
self.current_track = None
def is_running(self):
return self.as_bridge.call("is_running", "iTunes")
def set_current_track_rating(self, rating):
"""
Try to set the rating of the current track
Return True if succesful else False
"""
try:
self.as_bridge.call("set_current_track_rating", rating)
return True
except applescript.ScriptError:
return False
def get_artwork(self, directory):
directory = os.path.realpath(directory).replace('/', ':')[1:]
try:
artwork = self.as_bridge.call("get_album_artwork", directory+':')
except applescript.ScriptError:
return None
artwork = '/'+artwork.replace(':', '/')
return artwork
def get_current_track_info(self):
try:
track_info = self.as_bridge.call("get_current_track_info")
except applescript.ScriptError:
return None
return track_info
def main():
iTunes = iTunesBridge()
print iTunes.is_running()
iTunes.get_current_track_info()
if __name__ == "__main__":
main()
+39
View File
@@ -0,0 +1,39 @@
on is_running(appName)
tell application "System Events" to (name of processes) contains appName
end is_running
on get_current_track_info()
tell application "iTunes"
set current_track to the current track
set track_album to the album of the current track
set track_artist to the artist of the current track
set track_comments to the comment of the current track
set track_name to the name of the current track
set track_rating to the rating of the current track
end tell
return {album:track_album, artist:track_artist, track_name:track_name}
end get_current_track_info
on set_current_track_rating(track_rating)
tell application "iTunes"
set rating of current track to track_rating
end tell
end set_current_track_rating
on get_album_artwork(directory)
tell application "iTunes" to tell artwork 1 of current track
set d to raw data
if format is "class PNG" then
set x to "png"
else
set x to "jpg"
end if
end tell
(((directory) as text) & "cover." & x)
set b to open for access file result with write permission
set eof b to 0
write d to b
close access b
return (((directory) as text) & "cover." & x)
end get_album_artwork
+188
View File
@@ -0,0 +1,188 @@
import wx
import os
import time
from threading import Thread
from wx.lib.pubsub import pub as Publisher
from itunes_bridge import iTunesBridge
#--------------------------------------------------------------
class iTunes_com_thread(Thread):
"""A class for communications with itunes"""
def __init__(self):
"""Init Thread Class."""
Thread.__init__(self)
self.start() # start the thread
#----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
# This is the code executing in the new thread.
program_running = True
self.iTunes = iTunesBridge()
current_track = None
artwork = None
Publisher.subscribe(self.setRating, "rate")
self.set_rating = False
prev_track = None
while(program_running):
if self.iTunes.is_running():
current_track = self.iTunes.get_current_track_info()
update_artwork = False
if prev_track != current_track:
update_artwork = True
artwork = (
self.iTunes.get_artwork(os.getcwd())
)
if not artwork:
artwork = "/Users/samperry/Python_Projects/itunes_v2/nocover.png"
if self.set_rating:
self.iTunes.set_current_track_rating(self.rating)
prev_track = current_track
time.sleep(0.25)
wx.CallAfter(self.postInfo, current_track, artwork, update_artwork)
#----------------------------------------------------------------------
def postInfo(self, current_track, artwork, update_artwork):
"""Send track info to the GUI"""
Publisher.sendMessage("update", data = current_track, data2 = artwork,
data3 = update_artwork)
def setRating(self, data):
"""Set rating of the current track"""
self.set_rating = True
self.rating = data * 20
#--------------------------------------------------------------
class MainWindow(wx.Frame):
def __init__(self, parent, title=''):
#Create the main window?
super(MainWindow, self).__init__(
parent,
title=title,
)
#--------------------------------------------------------------
#Create a file manu
filemenu = wx.Menu()
#Define menu items
menu_about = filemenu.Append(
wx.ID_ABOUT,
"&About",
"Show information about this program"
)
menu_exit = filemenu.Append(
wx.ID_EXIT,
"E&XIT",
"End the program"
)
#Create the menu bar to place the filemenu in
menubar = wx.MenuBar()
menubar.Append(filemenu, "&File")
#Add the menu bar to the frame
self.SetMenuBar(menubar)
self.Bind(wx.EVT_MENU, self.OnAbout, menu_about)
self.Bind(wx.EVT_MENU, self.OnExit, menu_exit)
#set the directory variable to the current directory of this script
self.dirname = os.getcwd()
#Create 3 sizers to arange objects in
self.main_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.info_sizer = wx.BoxSizer(wx.VERTICAL)
self.text_sizer = wx.BoxSizer(wx.VERTICAL)
self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
#Create a list to store rating buttons in
self.buttons = []
for i in xrange(5):
#Store each button object in a list
self.buttons.append(wx.Button(self, -1, "&" + str(i+1)))
#Add each button object to the sizer
self.button_sizer.Add(self.buttons[i], 1, wx.EXPAND)
self.buttons[i].Bind(wx.EVT_BUTTON, self.OnButton)
#Create a text object
self.artist_text = wx.StaticText(self, label="Artist:\t")
self.song_text = wx.StaticText(self, label="Title:\t")
self.album_text = wx.StaticText(self, label="Album:\t")
for i in (self.song_text, self.artist_text, self.album_text):
self.text_sizer.Add(i, 1, wx.EXPAND)
self.info_sizer.Add(self.text_sizer, 1, wx.EXPAND)
self.info_sizer.Add(self.button_sizer, 1, wx.EXPAND)
#--------------------------------------------------------------
#Specify the maximum size of the album artwork
self.current_artwork = "nocover.png"
img = wx.Image("nocover.png", wx.BITMAP_TYPE_ANY)
img = img.Scale(120,120)
self.icon = wx.StaticBitmap(self, bitmap=wx.BitmapFromImage(img))
self.main_sizer.Add(self.icon, 1, wx.EXPAND)
self.main_sizer.Add(self.info_sizer, 3, wx.EXPAND)
#Select the sizer to use for the main window
self.SetSizer(self.main_sizer)
self.SetAutoLayout(1)
#Fit sizer 1 to window
self.SetSizerAndFit(self.main_sizer)
#initialize comunication thread
iTunes_com_thread()
#Create publisher reciever to recieve messages from thread
Publisher.subscribe(self.updateDisplay, "update")
self.Show()
#--------------------------------------------------------------
def OnAbout(self, event):
"""Show information about the program"""
#Create a dialog box containing theinformation about the program
dlg = wx.MessageDialog(self, "iTunes Rating App", "Created by Sam Perry")
#Show the dialog
dlg.ShowModal()
#Destroy when finished
dlg.Destroy()
#--------------------------------------------------------------
def OnExit(self, event):
"""Close the frame"""
self.Close(True)
#--------------------------------------------------------------
def OnButton(self, event):
"""Set the rating of a track based on the button pressed"""
btn = event.GetEventObject()
rating = int(btn.GetLabelText())
wx.CallAfter(Publisher.sendMessage, "rate", data = rating)
#--------------------------------------------------------------
def updateDisplay(self, data, data2, data3):
"""Receives data from thread and updates the display"""
t = data
artwork = data2
update_artwork = data3
if isinstance(t, dict):
self.artist_text.SetLabel("Artist:\t" + t["artist"])
self.song_text.SetLabel("Title:\t" + t["track_name"])
self.album_text.SetLabel("Album:\t" + t["album"])
if update_artwork:
if not artwork:
img = wx.Image("nocover.jpg", wx.BITMAP_TYPE_ANY)
img = img.Scale(120,120)
self.icon = wx.StaticBitmap(self, bitmap=wx.BitmapFromImage(img))
else:
img = wx.Image(artwork, wx.BITMAP_TYPE_ANY)
img = img.Scale(120,120)
self.icon = wx.StaticBitmap(self, bitmap=wx.BitmapFromImage(img))
self.icon.Refresh()
#--------------------------------------------------------------
app = wx.App(False)
frame = MainWindow(None, title="iTunes Rating")
frame.Show()
app.MainLoop()