source: trunk/StreamVision/StreamVision.py @ 211

Last change on this file since 211 was 211, checked in by Nicholas Riley, 14 years ago

setup.py: use HotKey? module (shared with LocationDo?) instead of
_StreamVision module

HotKeymodule?.c: the aforementioned module

StreamVision?.py: use HotKey? module instead of _StreamVision module.
Fix StreamVision?.displayTrackInfo to not crash when iTunes jealously
hides the names of iTMS tracks from us. Switch track rating keys to
shift-F10/F11 to avoid conflicting with my preferred Expose/Dashboard?
key bindings on my iBook.

File size: 5.3 KB
Line 
1#!/usr/bin/pythonw
2# -*- coding: utf-8 -*-
3
4from appscript import app, k
5from AppKit import NSApplication, NSBeep, NSSystemDefined, NSURL, NSWorkspace
6from Foundation import NSDistributedNotificationCenter
7from PyObjCTools import AppHelper
8from Carbon.CarbonEvt import RegisterEventHotKey, GetApplicationEventTarget
9from Carbon.Events import cmdKey, shiftKey
10import struct
11import scrape
12import HotKey
13
14GROWL_APP_NAME = 'StreamVision'
15NOTIFICATION_TRACK_INFO = 'iTunes Track Info'
16NOTIFICATIONS_ALL = [NOTIFICATION_TRACK_INFO]
17
18kEventHotKeyPressedSubtype = 6
19kEventHotKeyReleasedSubtype = 9
20
21growl = app('GrowlHelperApp')
22
23growl.register(
24    as_application=GROWL_APP_NAME,
25    all_notifications=NOTIFICATIONS_ALL,
26    default_notifications=NOTIFICATIONS_ALL,
27    icon_of_application='iTunes.app')
28    # if we leave off the .app, we can get Classic iTunes's icon
29
30def growlNotify(title, description, **kw):
31    growl.notify(
32        with_name=NOTIFICATION_TRACK_INFO,
33        title=title,
34        description=description,
35        application_name=GROWL_APP_NAME,
36        **kw)
37
38def radioParadiseURL():
39    session = scrape.Session()
40    session.go('http://www2.radioparadise.com/nowplay_b.php')
41    return session.region.firsttag('a')['href']
42
43def cleanStreamTitle(title):
44    if title == k.MissingValue:
45        return ''
46    title = title.split(' [')[0] # XXX move to description
47    title = title.replace('`', u'’')
48    return title
49
50def cleanStreamTrackName(name):
51    name = name.split('. ')[0]
52    name = name.split(': ')[0]
53    name = name.split(' - ')
54    if len(name) > 1:
55        name = ' - '.join(name[:-1])
56    else:
57        name = name[0]
58    return name
59
60def iTunesApp(): return app(id='com.apple.iTunes')
61def XTensionApp(): return app(creator='SHEx')
62
63HAVE_XTENSION = False
64try:
65    XTensionApp()
66    HAVE_XTENSION = True
67except:
68    pass
69
70class StreamVision(NSApplication):
71
72    hotKeyActions = {}
73    hotKeys = []
74
75    def displayTrackInfo(self):
76        iTunes = iTunesApp()
77
78        trackClass = iTunes.current_track.class_.get()
79        trackName = ''
80        if trackClass != k.Property:
81            trackName = iTunes.current_track.name.get()
82
83        if iTunes.player_state.get() != k.playing:
84            growlNotify('iTunes is not playing.', trackName)
85            return
86        if trackClass == k.URL_track:
87            growlNotify(cleanStreamTitle(iTunes.current_stream_title.get()),
88                        cleanStreamTrackName(trackName))
89            return
90        if trackClass == k.Property:
91           growlNotify('iTunes is playing.', '')
92           return
93        kw = {}
94        # XXX iTunes doesn't let you get artwork for shared tracks
95        if trackClass != k.shared_track:
96            artwork = iTunes.current_track.artworks.get()
97            if artwork:
98                kw['pictImage'] = artwork[0].data.get()
99        growlNotify(trackName + '  ' +
100                    '★' * (iTunes.current_track.rating.get() / 20),
101                    iTunes.current_track.album.get() + "\n" +
102                    iTunes.current_track.artist.get(),
103                    **kw)
104
105    def goToSite(self):
106        iTunes = iTunesApp()
107        if iTunes.player_state.get() == k.playing:
108            url = iTunes.current_stream_URL.get()
109            if url:
110                if 'radioparadise.com' in url:
111                    url = radioParadiseURL()
112                NSWorkspace.sharedWorkspace().openURL_(NSURL.URLWithString_(url))
113                return
114        NSBeep()
115
116    def registerHotKey(self, func, keyCode, mods=0):
117        hotKeyRef = RegisterEventHotKey(keyCode, mods, (0, 0),
118                                        GetApplicationEventTarget(), 0)
119        self.hotKeys.append(hotKeyRef)
120        self.hotKeyActions[HotKey.HotKeyAddress(hotKeyRef)] = func
121
122    def incrementRatingBy(self, increment):
123        iTunes = iTunesApp()
124        rating = iTunes.current_track.rating.get()
125        rating += increment
126        if rating < 0:
127            rating = 0
128            NSBeep()
129        elif rating > 100:
130            rating = 100
131            NSBeep()
132        iTunes.current_track.rating.set(rating)
133
134    def playPause(self):
135        iTunes = iTunesApp()
136        iTunes.playpause()
137        if HAVE_XTENSION:
138            if iTunes.player_state.get() == k.playing:
139                XTensionApp().turnon('Stereo')
140            else:
141                XTensionApp().turnoff('Stereo')
142
143    def finishLaunching(self):
144        super(StreamVision, self).finishLaunching()
145        self.registerHotKey(self.displayTrackInfo, 100) # F8
146        self.registerHotKey(self.goToSite, 100, cmdKey) # cmd-F8
147        self.registerHotKey(self.playPause, 101) # F9
148        self.registerHotKey(lambda: iTunesApp().previous_track(), 109) # F10
149        self.registerHotKey(lambda: iTunesApp().next_track(), 103) # F11
150        self.registerHotKey(lambda: self.incrementRatingBy(-20), 109, shiftKey) # shift-F10
151        self.registerHotKey(lambda: self.incrementRatingBy(20), 103, shiftKey) # shift-F11
152        NSDistributedNotificationCenter.defaultCenter().addObserver_selector_name_object_(self, self.displayTrackInfo, 'com.apple.iTunes.playerInfo', None)
153
154    def sendEvent_(self, theEvent):
155        if theEvent.type() == NSSystemDefined and \
156               theEvent.subtype() == kEventHotKeyPressedSubtype:
157            self.hotKeyActions[theEvent.data1()]()
158        super(StreamVision, self).sendEvent_(theEvent)
159
160if __name__ == "__main__":
161    AppHelper.runEventLoop()
Note: See TracBrowser for help on using the repository browser.