Mercurial > code > home > repos > light9
annotate bin/ascoltami @ 258:c9940e4e68d6
TkGyro: read subs from argv or stdin, cleanups
Some documentation and code reorganization/cleanups
author | David McClosky <dmcc@bigasterisk.com> |
---|---|
date | Thu, 16 Jun 2005 05:16:30 +0000 |
parents | feb7910eb6d4 |
children | 77c39b6e71ab |
rev | line source |
---|---|
217 | 1 #!/usr/bin/env python |
2 | |
3 # this is a fork from semprini/ascotalmi to use mpd | |
4 | |
5 """ a separate player program from Semprini.py. name means 'listen to | |
6 me' in italian. | |
7 | |
8 features and limitations: | |
9 | |
10 xmlrpc interface for: | |
11 getting the current time in the playing song | |
12 requesting what song is playing | |
13 saying what song should play | |
14 | |
15 todo: | |
16 | |
17 presong and postsong silence | |
18 | |
19 """ | |
20 | |
21 from __future__ import division,nested_scopes | |
22 | |
23 from optparse import OptionParser | |
227 | 24 import os,math,time |
217 | 25 import Tkinter as tk |
26 | |
27 from twisted.internet import reactor,tksupport | |
28 from twisted.internet.error import CannotListenError | |
29 from twisted.web import xmlrpc, server | |
30 | |
31 import run_local | |
243
fff8762db48a
finished incomplete patch- asco now measures the length of songs (only for .wav)
drewp@bigasterisk.com
parents:
242
diff
changeset
|
32 from light9 import networking, showconfig, wavelength |
217 | 33 |
34 from pympd import Mpd | |
35 | |
36 appstyle={'fg':'white','bg':'black'} | |
37 | |
38 class XMLRPCServe(xmlrpc.XMLRPC): | |
39 def __init__(self,player): | |
40 xmlrpc.XMLRPC.__init__(self) | |
41 self.player=player | |
42 | |
43 def xmlrpc_echo(self,x): | |
44 return x | |
45 | |
46 def xmlrpc_playfile(self,musicfilename): | |
47 self.player.play(musicfilename) | |
48 return 'ok' | |
49 def xmlrpc_stop(self): | |
50 self.player.state.set('stop') | |
51 return 'ok' | |
52 def xmlrpc_gettime(self): | |
53 """returns seconds from start of song""" | |
227 | 54 return float(self.player.smoothCurrentTime()) |
217 | 55 def xmlrpc_songlength(self): |
56 """song length, in seconds""" | |
57 return float(self.player.total_time.get()) | |
58 def xmlrpc_songname(self): | |
59 """song filename, or None""" | |
223 | 60 return self.player.filename_var.get() or "No song" |
217 | 61 |
62 class Player: | |
223 | 63 """semprini-style access to mpd. in here is where we add the padding""" |
217 | 64 |
65 def __init__(self, app, playlist, media=None): | |
66 | |
67 self.mpd = Mpd() | |
226 | 68 reactor.connectTCP(*(networking.mpdServer()+(self.mpd,))) |
217 | 69 |
70 self.state = tk.StringVar() | |
71 self.state.set("stop") # 'stop' 'pause' 'play' | |
72 | |
73 self.current_time = tk.DoubleVar() | |
74 self.total_time = tk.DoubleVar() | |
75 self.filename_var = tk.StringVar() | |
76 | |
227 | 77 self.pre_post_names = showconfig.prePostSong() |
78 | |
79 self.last_poll_time = None | |
80 | |
217 | 81 self.pollStatus() |
227 | 82 |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
83 self.autopausedthissong = False # a song only autopauses once |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
84 self.mpd_is_lying = False # mpd reports bad times in certain intervals |
227 | 85 |
86 def smoothCurrentTime(self): | |
87 """like self.current_time.get, but more accurate""" | |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
88 |
227 | 89 if self.last_poll_time and self.state.get() == 'play': |
90 dt = time.time() - self.last_poll_time | |
91 else: | |
92 dt = 0 | |
93 return self.current_time.get() + dt | |
94 | |
217 | 95 def pollStatus(self): |
227 | 96 if self.state.get() == 'stop': |
97 self.current_time.set(-4) | |
98 | |
217 | 99 self.mpd.status().addCallback(self.pollStatus2) |
100 | |
227 | 101 def pollStatus2(self, stat): |
102 | |
103 if self.state.get() != stat.state: | |
104 self.state.set(stat.state) | |
105 | |
217 | 106 |
227 | 107 if hasattr(stat, 'time_elapsed'): |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
108 elapsed = stat.time_elapsed |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
109 songnum = stat.song |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
110 total = stat.time_total |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
111 if self.mpd_is_lying and elapsed < 3: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
112 self.mpd_is_lying = False |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
113 |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
114 # mpd lies about elapsed, song, and total during the last |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
115 # .5sec of each song. so we coast through that part |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
116 if elapsed > total - .75 or self.mpd_is_lying: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
117 if not self.mpd_is_lying: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
118 self.mpd_is_lying = True |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
119 self.true_song_total = songnum, total |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
120 self.marked_time = time.time() |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
121 self.marked_val = elapsed |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
122 elapsed = self.marked_val + (time.time() - self.marked_time) |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
123 songnum, total = self.true_song_total |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
124 |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
125 if songnum == 1: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
126 t = elapsed |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
127 elif songnum == 0: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
128 t = elapsed - total |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
129 elif songnum == 2: |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
130 t = self.total_time.get() + elapsed |
217 | 131 |
227 | 132 self.current_time.set(t) |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
133 |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
134 self.last_poll_time = time.time() |
227 | 135 |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
136 self.check_autopause() |
227 | 137 |
217 | 138 reactor.callLater(.05, self.pollStatus) |
139 | |
242
561b4202461d
fixing extra audio stutter - this is currently broken
drewp@bigasterisk.com
parents:
241
diff
changeset
|
140 def set_total_time(self, song_path): |
243
fff8762db48a
finished incomplete patch- asco now measures the length of songs (only for .wav)
drewp@bigasterisk.com
parents:
242
diff
changeset
|
141 # currently only good for .wav |
fff8762db48a
finished incomplete patch- asco now measures the length of songs (only for .wav)
drewp@bigasterisk.com
parents:
242
diff
changeset
|
142 p = os.path.join(showconfig.musicDir(), song_path) |
fff8762db48a
finished incomplete patch- asco now measures the length of songs (only for .wav)
drewp@bigasterisk.com
parents:
242
diff
changeset
|
143 self.total_time.set(wavelength.wavelength(p)) |
242
561b4202461d
fixing extra audio stutter - this is currently broken
drewp@bigasterisk.com
parents:
241
diff
changeset
|
144 |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
145 def play(self, song_path=None): |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
146 if song_path is None: |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
147 self.mpd.play() |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
148 return |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
149 |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
150 self.autopausedthissong = False |
220
13c089886f61
added the forgotten curve.py; mpd song path fix
drewp@bigasterisk.com
parents:
218
diff
changeset
|
151 self.mpd.clear() |
227 | 152 self.mpd.add(showconfig.songInMpd(self.pre_post_names[0])) |
153 self.mpd.add(showconfig.songInMpd(song_path)) | |
154 self.mpd.add(showconfig.songInMpd(self.pre_post_names[1])) | |
155 self.filename_var.set(song_path) | |
156 | |
242
561b4202461d
fixing extra audio stutter - this is currently broken
drewp@bigasterisk.com
parents:
241
diff
changeset
|
157 self.set_total_time(song_path) |
227 | 158 self.mpd.seek(seconds=0, song=0) |
217 | 159 |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
160 def check_autopause(self): |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
161 pause_time = self.total_time.get() + 10 |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
162 if (not self.autopausedthissong and |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
163 self.state.get() == "play" and |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
164 self.current_time.get() > pause_time): |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
165 self.autopausedthissong = True |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
166 self.mpd.pause() |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
167 |
217 | 168 def stop(self): |
227 | 169 self.mpd.seek(seconds=0, song=0) |
217 | 170 self.mpd.stop() |
171 | |
172 def seek_to(self, time): | |
227 | 173 if time < 0: |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
174 # seeking to anything within my 4-sec silence ogg goes |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
175 # right to zero. maybe ogg seeking is too coarse? |
227 | 176 self.mpd.seek(seconds=time - (-4), song=0) |
177 elif time > self.total_time.get(): | |
178 self.mpd.seek(seconds=time - self.total_time.get(), song=2) | |
179 else: | |
180 self.mpd.seek(seconds=time, song=1) | |
217 | 181 |
182 def play_pause_toggle(self): | |
183 def finish(status): | |
184 if status.state == 'play': | |
185 self.mpd.pause() | |
186 else: | |
187 self.mpd.play() | |
188 self.mpd.status().addCallback(finish) | |
189 | |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
190 def pause(self): |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
191 self.mpd.pause() |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
192 |
217 | 193 |
194 def buildsonglist(root,songfiles,player): | |
195 songlist=tk.Frame(root,bd=2,relief='raised',bg='black') | |
196 | |
197 prefixlen=len(os.path.commonprefix(songfiles)) | |
198 # include to the last os.sep- dont crop path elements in the middle | |
199 prefixlen=songfiles[0].rfind(os.sep)+1 | |
200 maxsfwidth=max([len(x[prefixlen:]) for x in songfiles]) | |
201 | |
202 for i,sf in enumerate(songfiles): | |
203 b=tk.Button(songlist,text=sf[prefixlen:],width=maxsfwidth, | |
204 anchor='w',pady=0,bd=0,relief='flat', | |
235 | 205 font="arial 14 bold") |
217 | 206 b.bind("<Configure>",lambda ev,b=b: |
235 | 207 b.config(font="arial %d bold" % min(12,int((ev.height-3)*.8)))) |
217 | 208 try: |
209 # rainbow colors | |
210 frac=i/len(songfiles) | |
211 b.config(bg='black', | |
212 fg="#%02x%02x%02x" % tuple([int(255*(.7+.3* | |
213 math.sin(frac*4+x)) | |
214 ) for x in 1,2,3])) | |
215 except Exception,e: | |
216 print "rainbow failed: %s"%e | |
217 | |
218 b.config(command=lambda sf=sf: player.play(sf)) | |
219 b.pack(side='top',fill='both',exp=1,padx=0,pady=0,ipadx=0,ipady=0) | |
220 | |
221 | |
222 def color_buttons(x, y, z, sf=sf, b=b): | |
223 name = player.filename_var.get() | |
224 if name == sf[prefixlen:]: | |
225 b['bg'] = 'grey50' | |
226 else: | |
227 b['bg'] = 'black' | |
228 player.filename_var.trace("w", color_buttons) | |
229 return songlist | |
218 | 230 |
217 | 231 |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
232 class TimeScale(tk.Scale): |
218 | 233 def __init__(self,master,player): |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
234 tk.Scale.__init__(self, master, orient="horiz", |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
235 from_=-4,to_=100, |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
236 sliderlen=20,width=20, |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
237 res=0.001, |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
238 showvalue=0, |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
239 troughcolor='black', |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
240 bg='lightblue3', |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
241 ) |
217 | 242 |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
243 self.player = player |
217 | 244 |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
245 self.dragging = False |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
246 self.button_down = False |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
247 self.drag_start_player_state = None |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
248 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
249 self.bind("<ButtonPress-1>", self.b1down) |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
250 self.config(command=self.scale_changed) |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
251 self.bind("<ButtonRelease-1>", self.b1up) |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
252 |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
253 self.player.current_time.trace('w', self.current_time_changed) |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
254 |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
255 def current_time_changed(self, *args): |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
256 """attach player.current_time to scale (one-way)""" |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
257 if not self.dragging: |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
258 self.set(self.player.current_time.get()) |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
259 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
260 def b1down(self,evt): |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
261 self.button_down = True |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
262 self.dragging = False |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
263 |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
264 def scale_changed(self, time): |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
265 if not self.button_down: |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
266 return |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
267 |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
268 if not self.dragging: |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
269 self.dragging = True |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
270 self.drag_start_player_state = self.player.state.get() |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
271 if self.drag_start_player_state == "play": |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
272 # due to mpd having to seemingly play a whole block at |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
273 # every new seek point, it is better to pause playback |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
274 # while the mouse is down |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
275 self.player.pause() |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
276 |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
277 # ok to seek around when paused. this keeps the displayed time |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
278 # up to date, which is how the user knows where he is |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
279 self.player.seek_to(float(time)) |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
280 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
281 def b1up(self,evt): |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
282 self.button_down = False |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
283 self.dragging = False |
245
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
284 |
feb7910eb6d4
scrubbing while playing works pretty well now
drewp@bigasterisk.com
parents:
244
diff
changeset
|
285 if self.drag_start_player_state == "play": |
244
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
286 self.player.play() |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
287 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
288 class Seeker(tk.Frame): |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
289 """includes scale AND labels below it""" |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
290 def __init__(self,master,player): |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
291 tk.Frame.__init__(self,master,bg='black') |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
292 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
293 self.scl = TimeScale(self,player) |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
294 self.scl.pack(fill='x',side='top') |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
295 |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
296 self.buildstatus(player) |
1f7edb2e4724
asco scale now pauses while you seek (mostly)
drewp@bigasterisk.com
parents:
243
diff
changeset
|
297 |
217 | 298 |
218 | 299 def buildstatus(self,player): |
300 left_var=tk.DoubleVar() | |
301 for txt,var,fmt in (('Current',player.current_time,"%.2f"), | |
302 ('Song len',player.total_time,"%.2f",), | |
303 ('Left',left_var, "%.2f"), | |
304 ('Song',player.filename_var, "%s"), | |
305 ('State', player.state, "%s")): | |
306 tk.Label(self,text=txt, | |
307 relief='raised',bd=1,font='arial 9', | |
223 | 308 **appstyle).pack(side='left',fill='y') |
218 | 309 l = tk.Label(self,width=7, anchor='w', text=var.get(), |
310 relief='sunken',bd=1,font='arial 12 bold', | |
223 | 311 padx=2,pady=2, |
218 | 312 bg='#800000',fg='white') |
313 if txt == 'Song': | |
314 l.config(anchor='e') | |
315 l.pack(side='left',expand=1, fill='x') | |
316 | |
317 var.trace_variable('w', | |
318 lambda a,b,c,l=l,fmt=fmt,var=var: | |
319 l.config(text=fmt % var.get())) | |
320 | |
321 # update end time as the song changes | |
322 player.total_time.trace("w",lambda *args: ( | |
323 self.scl.config(to_=player.total_time.get()+15))) | |
217 | 324 |
218 | 325 def fixleft(*args): |
326 # update time-left variable | |
327 left_var.set(player.total_time.get()-player.current_time.get()) | |
328 | |
329 if player.current_time.get() < 0 or left_var.get() < 0: | |
330 self.scl['troughcolor'] = 'blue' | |
331 else: | |
332 self.scl['troughcolor'] = 'black' | |
333 | |
334 player.total_time.trace("w",fixleft) | |
335 player.current_time.trace("w",fixleft) | |
217 | 336 |
218 | 337 class ControlButtons(tk.Frame): |
338 def __init__(self,master): | |
339 tk.Frame.__init__(self,master,bg='black') | |
340 | |
341 self.statebuttons = {} # lowercased name : Button | |
241
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
342 for txt,cmd,key in [ |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
343 ('Stop', player.stop, "<Control-s>"), |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
344 ('Pause', player.play_pause_toggle, "<Control-p>"), |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
345 ('Skip Intro',lambda: player.seek_to(0), "<Control-i>"), |
0a2239379466
added autopause. workaround for mpd's incorrect times
drewp@bigasterisk.com
parents:
235
diff
changeset
|
346 ]: |
218 | 347 b = tk.Button(self, text=txt, command=cmd, font='arial 16 bold', |
348 height=3,**appstyle) | |
349 b.pack(side='left', fill='x', expand=1) | |
350 # keyboard bindings | |
351 root.bind(key, lambda evt, cmd=cmd: cmd()) | |
352 self.statebuttons[txt.lower()] = b | |
353 | |
354 def update_state_buttons(self,*args): | |
355 state = player.state.get() | |
356 | |
357 if state in ('stop', 'pause'): | |
358 self.statebuttons['pause']['text'] = 'Play' | |
359 else: | |
360 self.statebuttons['pause']['text'] = 'Pause' | |
361 | |
362 colors = {'stop' : 'red', | |
363 'play' : 'blue', | |
364 'pause' : 'green'} # very confusing -- play and pause supply colors | |
365 # for each other! | |
366 for name, button in self.statebuttons.items(): | |
367 if name == 'pause' and state not in ('stop', 'pause'): | |
368 name = 'play' | |
369 | |
370 if state == name: # name gets changed sometimes for 'pause' -- see right above | |
371 button['bg'] = colors.get(name, 'black') | |
372 else: | |
373 button['bg'] = 'black' | |
217 | 374 |
375 ############################ | |
376 | |
377 parser=OptionParser() | |
378 | |
379 (options,songfiles)=parser.parse_args() | |
380 | |
381 if len(songfiles)<1: | |
382 songfiles = [f for f in os.listdir(showconfig.musicDir()) | |
383 if f.endswith('wav')] | |
235 | 384 songfiles.sort() |
217 | 385 |
386 root=tk.Tk() | |
387 root.wm_title("ascoltami") | |
235 | 388 #root.wm_geometry("+1270+440") |
217 | 389 root.config(bg="black") |
390 player=Player(None,None) | |
391 | |
218 | 392 songlist = buildsonglist(root,songfiles,player) |
217 | 393 songlist.pack(fill='both',exp=1) |
394 | |
218 | 395 f2 = tk.Frame(bg='black') |
396 buts = ControlButtons(f2) | |
397 buts.pack(side='top',fill='x') | |
217 | 398 |
218 | 399 player.state.trace_variable('w', buts.update_state_buttons) |
400 buts.update_state_buttons() | |
217 | 401 |
218 | 402 seeker = Seeker(f2,player) |
217 | 403 seeker.pack(fill='x',exp=1) |
404 f2.pack(side='bottom',fill='x') | |
405 | |
406 tksupport.install(root,ms=10) | |
407 | |
408 try: | |
218 | 409 reactor.listenTCP(networking.musicPort(),server.Site(XMLRPCServe(player))) |
410 print "started server on %s" % networking.musicPort() | |
217 | 411 except CannotListenError: |
218 | 412 print "no server started- %s is in use" % networking.musicPort() |
217 | 413 |
414 root.bind("<Destroy>",lambda ev: reactor.stop) | |
415 root.protocol('WM_DELETE_WINDOW', reactor.stop) | |
416 | |
417 reactor.run() |