Changeset - feb7910eb6d4
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 20 years ago 2005-06-15 01:05:36
drewp@bigasterisk.com
scrubbing while playing works pretty well now
1 file changed with 34 insertions and 39 deletions:
0 comments (0 inline, 0 general)
bin/ascoltami
Show inline comments
 
@@ -166,150 +166,145 @@ class Player:
 
            self.mpd.pause()
 

	
 
    def stop(self):
 
        self.mpd.seek(seconds=0, song=0)
 
        self.mpd.stop()
 
        
 
    def seek_to(self, time):
 
        if time < 0:
 
            # seeking to anything within my 4-sec silence ogg goes
 
            # right to zero. maybe ogg seeking is too coarse?
 
            self.mpd.seek(seconds=time - (-4), song=0)
 
        elif time > self.total_time.get():
 
            self.mpd.seek(seconds=time - self.total_time.get(), song=2)
 
        else:
 
            self.mpd.seek(seconds=time, song=1)
 

	
 
    def play_pause_toggle(self):
 
        def finish(status):
 
            if status.state == 'play':
 
                self.mpd.pause()
 
            else:
 
                self.mpd.play()
 
        self.mpd.status().addCallback(finish)
 

	
 
    def pause(self): self.mpd.pause()
 
    def is_playing(self): return self.state.get() == "play"
 
    def pause(self):
 
        self.mpd.pause()
 

	
 

	
 
def buildsonglist(root,songfiles,player):
 
    songlist=tk.Frame(root,bd=2,relief='raised',bg='black')
 

	
 
    prefixlen=len(os.path.commonprefix(songfiles))
 
    # include to the last os.sep- dont crop path elements in the middle
 
    prefixlen=songfiles[0].rfind(os.sep)+1 
 
    maxsfwidth=max([len(x[prefixlen:]) for x in songfiles])
 

	
 
    for i,sf in enumerate(songfiles):
 
        b=tk.Button(songlist,text=sf[prefixlen:],width=maxsfwidth,
 
                    anchor='w',pady=0,bd=0,relief='flat',
 
                    font="arial 14 bold")
 
        b.bind("<Configure>",lambda ev,b=b:
 
               b.config(font="arial %d bold" % min(12,int((ev.height-3)*.8))))
 
        try:
 
            # rainbow colors
 
            frac=i/len(songfiles)
 
            b.config(bg='black',
 
                     fg="#%02x%02x%02x" % tuple([int(255*(.7+.3*
 
                                                          math.sin(frac*4+x))
 
                                                     ) for x in 1,2,3]))
 
        except Exception,e:
 
            print "rainbow failed: %s"%e
 
        
 
        b.config(command=lambda sf=sf: player.play(sf))
 
        b.pack(side='top',fill='both',exp=1,padx=0,pady=0,ipadx=0,ipady=0)
 

	
 

	
 
        def color_buttons(x, y, z, sf=sf, b=b):
 
            name = player.filename_var.get()
 
            if name == sf[prefixlen:]:
 
                b['bg'] = 'grey50'
 
            else:
 
                b['bg'] = 'black'
 
        player.filename_var.trace("w", color_buttons)
 
    return songlist
 
 
 

	
 
class TimeScale(tk.Scale):
 
    def __init__(self,master,player):
 
        self.player = player
 
        tk.Scale.__init__(self, master, orient="horiz",
 
                          from_=-4,to_=100,
 
                          sliderlen=20,width=20,
 
                          res=0.001,
 
                          showvalue=0,
 
                          variable=player.current_time,
 
                          troughcolor='black',
 
                          bg='lightblue3',
 
                          )
 

	
 
        # dragging the scl changes the player time (which updates the scl)
 

	
 
        # due to mpd having to seemingly play a whole block at every new
 
        # seek point, we may want a mode that pauses playback while the
 
        # mouse is down (or is moving too fast; or we've sent a seek too
 
        # recently)
 
        self.player = player
 

	
 
        self.dragging = False
 
        self.just_started_dragging = False
 
        self.player_state = None
 
        self.button_down = False
 
        self.drag_start_player_state = None
 

	
 
        self.config(command=self.seeker_cb)
 
        self.bind("<Motion>", self.set_mouse_state)
 
        self.bind("<B1-Motion>", self.set_mouse_state)
 
        self.bind("<ButtonPress-1>", self.b1down)
 
        self.config(command=self.scale_changed)
 
        self.bind("<ButtonRelease-1>", self.b1up)
 

	
 
    def set_mouse_state(self,evt):
 
        pass#self.dragging = True
 
        self.player.current_time.trace('w', self.current_time_changed)
 

	
 
    def current_time_changed(self, *args):
 
        """attach player.current_time to scale (one-way)"""
 
        if not self.dragging:
 
            self.set(self.player.current_time.get())
 

	
 
    def b1down(self,evt):
 
        self.just_started_dragging = True
 
        self.button_down = True
 
        self.dragging = False
 

	
 
    def scale_changed(self, time):
 
        if not self.button_down:
 
            return
 
        
 
        if not self.dragging:
 
            self.dragging = True
 
            self.drag_start_player_state = self.player.state.get()
 
            if self.drag_start_player_state == "play":
 
                # due to mpd having to seemingly play a whole block at
 
                # every new seek point, it is better to pause playback
 
                # while the mouse is down
 
                self.player.pause()
 

	
 
        # ok to seek around when paused. this keeps the displayed time 
 
        # up to date, which is how the user knows where he is
 
        self.player.seek_to(float(time))
 

	
 
    def b1up(self,evt):
 
        self.button_down = False
 
        self.dragging = False
 
        self.player.seek_to(float(self.newtime))
 
        if self.player_state == "play":
 
            
 
        if self.drag_start_player_state == "play":
 
            self.player.play()
 
        self.config(variable=player.current_time)
 

	
 
    def seeker_cb(self, time):
 
        if self.just_started_dragging:
 
            self.just_started_dragging = False
 
            self.player_state = self.player.state.get()
 
            if self.player_state == "play":
 
                player.pause()
 
            self.config(variable=tk.DoubleVar())
 

	
 
        self.newtime = time
 

	
 
        if self.player_state != "play":
 
            # ok to seek around when paused. this keeps the displayed time 
 
            # up to date, which is how the user knows where he is
 
            self.player.seek_to(float(self.newtime))
 

	
 

	
 
        
 

	
 
class Seeker(tk.Frame):
 
    """includes scale AND labels below it"""
 
    def __init__(self,master,player):
 
        tk.Frame.__init__(self,master,bg='black')
 

	
 
        self.scl = TimeScale(self,player)
 
        self.scl.pack(fill='x',side='top')
 

	
 
        self.buildstatus(player)
 

	
 

	
 
    def buildstatus(self,player):
 
        left_var=tk.DoubleVar()
 
        for txt,var,fmt in (('Current',player.current_time,"%.2f"),
 
                            ('Song len',player.total_time,"%.2f",),
 
                            ('Left',left_var, "%.2f"),
 
                            ('Song',player.filename_var, "%s"),
 
                            ('State', player.state, "%s")):
 
            tk.Label(self,text=txt,
 
                     relief='raised',bd=1,font='arial 9',
 
                     **appstyle).pack(side='left',fill='y')
 
            l = tk.Label(self,width=7, anchor='w', text=var.get(),
 
                         relief='sunken',bd=1,font='arial 12 bold',
0 comments (0 inline, 0 general)