Files
iTunesRating/iTunes Rating App.py
T
2015-03-25 14:39:51 +01:00

244 lines
9.3 KiB
Python

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.setDaemon(1)
self.start() # start the thread
#----------------------------------------------------------------------
def run(self):
"""Run Worker Thread."""
#----------------------------------------------------------------------
#Declare variables
program_running = True
current_track = None
artwork = None
self.set_rating = False
prev_track = None
#Create bridge to iTunes for sending and recieving data to/from itunes
self.iTunes = iTunesBridge()
#Subscribe to the rate publisher for messages about updating ratings
Publisher.subscribe(self.setRating, "rate")
#Main loop
while(program_running):
#Only execute itunes code if it is running
if self.iTunes.is_running():
#Get dictionary of information about the current track
current_track = self.iTunes.get_current_track_info()
#If the track has changed since the previous loop, update the
#displayed artwork
update_artwork = False
if prev_track != current_track:
update_artwork = True
#Get the file location of the new artwork to display
artwork = (
self.iTunes.get_artwork(os.getcwd())
)
#If the track has no artwork then display the no artwork
#picture
if not artwork:
artwork = '/'.join((os.getcwd(), "nocover.png"))
#If the rating needs to be updated then set it to the updated
#value
if self.set_rating:
self.iTunes.set_current_track_rating(self.rating)
prev_track = current_track
#Update the display with the new information
wx.CallAfter(self.postInfo, current_track, artwork, update_artwork)
#pause loop briefly
time.sleep(0.25)
#----------------------------------------------------------------------
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,
style= wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.STAY_ON_TOP
)
#--------------------------------------------------------------
#Create a file manu
filemenu = wx.Menu()
#Create a panel
self.panel = wx.Panel(self)
self.flashing_panel = False
#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(6):
#Store each button object in a list
self.buttons.append(wx.Button(
self,
-1,
"&" + str(i),
style=wx.BU_EXACTFIT,
size = (40, 28)
))
#Add each button object to the sizer
self.button_sizer.AddStretchSpacer(prop = 1)
self.button_sizer.Add(self.buttons[i], 0, wx.ALIGN_CENTER)
self.button_sizer.AddStretchSpacer(prop = 1)
self.buttons[i].Bind(wx.EVT_BUTTON, self.OnButton)
#Create a text object
self.artist_text = wx.StaticText(self.panel, label="Artist:\t")
self.song_text = wx.StaticText(self.panel, label="Title:\t")
self.album_text = wx.StaticText(self.panel, label="Album:\t")
self.rating_text = wx.StaticText(self.panel, label="Rating:\t")
for i in (
self.song_text,
self.artist_text,
self.album_text,
self.rating_text
):
self.text_sizer.Add(i, 1, wx.EXPAND)
self.info_sizer.Add(self.text_sizer, 8, wx.EXPAND)
self.info_sizer.Add(self.button_sizer, 5, 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))
#Add the artwork and the information sizer to the main sizer
self.main_sizer.Add(self.icon, 1, wx.EXPAND)
self.main_sizer.Add(self.info_sizer, 2, wx.EXPAND)
#Select the sizer to use for the main window
self.SetAutoLayout(1)
#Fit sizer 1 to window
self.panel.SetSizerAndFit(self.main_sizer)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.panel)
self.SetSizerAndFit(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"])
self.rating_text.SetLabel("Rating:\t" + str(t["rating"]/20))
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))
if t["duration"] - t["position"] <= 30:
if self.panel.GetBackgroundColour() == "Yellow":
self.panel.SetBackgroundColour(wx.NullColour)
self.panel.Refresh()
else:
self.panel.SetBackgroundColour("Yellow")
self.panel.Refresh()
else:
if self.panel.GetBackgroundColour() == "Yellow":
self.panel.SetBackgroundColour(wx.NullColour)
self.panel.Refresh()
#--------------------------------------------------------------
app = wx.App(False)
frame = MainWindow(None, title="iTunes Rating")
frame.Show()
app.MainLoop()