Added NSAlert-based interaction.
[~jspiros/PostTunes.git] / PostTunesAppDelegate.py
1 #
2 #  PostTunesAppDelegate.py
3 #  PostTunes
4 #
5 #  Created by Joseph Spiros on 3/5/09.
6 #  Copyright iThink Software 2009. All rights reserved.
7 #
8
9 import objc
10 from urllib import urlencode
11 from urllib2 import urlopen, URLError
12 from base64 import b64encode
13 from PyObjCTools import AppHelper
14 from Foundation import *
15 from AppKit import *
16 from ScriptingBridge import *
17
18 class PostTunesAppDelegate(NSObject):
19         preferencesWindow = objc.IBOutlet()
20         warnFailure = objc.ivar(u"warnFailure")
21         lastPersistentID = objc.ivar(u"lastPersistentID")
22         handlerURL = objc.ivar(u"handlerURL")
23         secretKey = objc.ivar(u"secretKey")
24         
25         def init(self):
26                 self = super(PostTunesAppDelegate, self).init()
27                 if not self:
28                         return None
29                 self.warnFailure = True
30                 self.lastPersistentID = None
31                 self.handlerURL = None
32                 self.secretKey = None
33                 return self
34         
35         def awakeFromNib(self):
36                 self.handlerURL = NSUserDefaults.standardUserDefaults().stringForKey_("handlerURL")
37                 self.secretKey = NSUserDefaults.standardUserDefaults().stringForKey_("secretKey")
38                 if not self.handlerURL:
39                         self.runConfigurationAlert_title_description_(None, "In order for PostTunes to post tracks, you must set a Handler URL. The optional Secret Key may be used by the script at the Handler URL to validate your posts.")
40                 self.observeNote()
41         
42         def runConfigurationAlert_title_description_(self, title, description):
43                 if not title:
44                         title = "PostTunes Configuration"
45                 alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(title, "OK", "Quit PostTunes", None, description)
46                 alert.setAccessoryView_(self.preferencesWindow.contentView().retain())
47                 alert.setAlertStyle_(NSCriticalAlertStyle)
48                 alertReturn = alert.runModal()
49                 if alertReturn == NSAlertDefaultReturn:
50                         self.handlerURL = NSUserDefaults.standardUserDefaults().stringForKey_("handlerURL")
51                         if not self.handlerURL:
52                                 self.runConfigurationAlert_title_description_("PostTunes Handler URL Missing", "You must set a Handler URL for PostTunes to function.")
53                 elif alertReturn == NSAlertAlternateReturn:
54                         AppHelper.stopEventLoop()
55         
56         def observeNote(self):
57                 NSDistributedNotificationCenter.defaultCenter().addObserver_selector_name_object_(self, "gotNotification:", "com.apple.iTunes.playerInfo", None)
58         
59         def gotNotification_(self, notification):
60                 self.handlerURL = NSUserDefaults.standardUserDefaults().stringForKey_("handlerURL")
61                 self.secretKey = NSUserDefaults.standardUserDefaults().stringForKey_("secretKey")
62                 if notification:
63                         noteInfo = notification.userInfo()
64                         playerState = noteInfo["Player State"]
65                         if "PersistentID" in noteInfo:
66                                 persistentID = noteInfo["PersistentID"]
67                                 if (persistentID != self.lastPersistentID) and ("Name" in noteInfo):
68                                         if playerState == "Playing":
69                                                 if self.handlerURL:
70                                                         # started playing a new track
71                                                         # get the applescript track and make sure it's the same (compare name)
72                                                         iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
73                                                         iTunesTrack = iTunes.currentTrack()
74                                                         if iTunesTrack.name() == noteInfo["Name"]:
75                                                                 self.trackChanged_iTunesTrack_(noteInfo, iTunesTrack)
76                                                                 self.lastPersistentID = persistentID
77                                                 else:
78                                                         self.runConfigurationAlert_title_description_("PostTunes Handler URL Missing", "PostTunes was unable to post a track due to the Handler URL being missing. You must set a Handler URL for PostTunes to function.")
79                                                                 
80                         else:
81                                 self.lastPersistentID = None
82                                 # stopped playing
83         
84         def trackChanged_iTunesTrack_(self, noteInfo, iTunesTrack):
85                 trackData = {"title": noteInfo["Name"]}
86                 if self.secretKey:
87                         trackData["key"] = self.secretKey
88                 if "Artist" in noteInfo:
89                         trackData["artist"] = noteInfo["Artist"]
90                 if "Album" in noteInfo:
91                         trackData["album"] = noteInfo["Album"]
92                 if "Store URL" in noteInfo:
93                         trackData["url"] = noteInfo["Store URL"]
94                 iTunesArtworks = iTunesTrack.artworks()
95                 if len(iTunesArtworks) >= 1:
96                         artwork = iTunesArtworks[0]
97                         artworkTIFF = artwork.data().TIFFRepresentation()
98                         artworkPNG = NSBitmapImageRep.imageRepWithData_(artworkTIFF).representationUsingType_properties_(NSPNGFileType, None)
99                         trackData["artpng"] = b64encode(artworkPNG.bytes())
100                 try:
101                         urlopen(self.handlerURL, urlencode(trackData))
102                 except URLError:
103                         description = (u"PostTunes encountered an error when attempting to post the track \"%s\" to your Handler URL." % trackData["title"])
104                         NSLog(u"%s Handler URL: %s" % (description, self.handlerURL))
105                         if self.warnFailure:
106                                 alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_("PostTunes Could Not Post Track", "OK", "Configure PostTunes", "Quit PostTunes", description)
107                                 alert.setAlertStyle_(NSCriticalAlertStyle)
108                                 alert.setShowsSuppressionButton_(True)
109                                 alertReturn = alert.runModal()
110                                 if alert.suppressionButton().state() == NSOnState:
111                                         self.warnFailure = False
112                                 if alertReturn == NSAlertAlternateReturn:
113                                         self.runConfigurationAlert_title_description_(None, (u"%s Please confirm your Handler URL." % description))
114                                 elif alertReturn == NSAlertOtherReturn:
115                                         AppHelper.stopEventLoop()