changeset 698:2aac2ef23495

time cursor, control-p over curveviews Ignore-this: 4b3becacd1ea8ee86cf53a178ea851c4
author Drew Perttula <drewp@bigasterisk.com>
date Sun, 10 Jun 2012 04:03:00 +0000
parents 6e9b5ed1e863
children d12bc8919d6e
files bin/curvecalc light9/curvecalc/curvecalc.glade light9/curvecalc/curveview.py light9/curvecalc/musicaccess.py
diffstat 4 files changed, 81 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/bin/curvecalc	Sat Jun 09 10:28:06 2012 +0000
+++ b/bin/curvecalc	Sun Jun 10 04:03:00 2012 +0000
@@ -15,7 +15,7 @@
 gtk2reactor.install()
 from twisted.internet import reactor
 
-import time, textwrap, os, optparse, urllib2, gtk, gobject
+import time, textwrap, os, optparse, urllib2, gtk, gobject, linecache
 import louie as dispatcher 
 from twisted.python.util import sibpath
 from rdflib import URIRef
@@ -46,8 +46,9 @@
     return graph
 
 class Main(object):
-    def __init__(self, graph, opts, song, curveset, subterms):
+    def __init__(self, graph, opts, song, curveset, subterms, music):
         self.graph = graph
+        self.music = music
         wtree = gtk.Builder()
         wtree.add_from_file(sibpath(__file__, "../light9/curvecalc/curvecalc.glade"))
         mainwin = wtree.get_object("MainWindow")
@@ -70,21 +71,24 @@
                 curvesVBox = wtree.get_object("curves")
                 [curvesVBox.remove(c) for c in curvesVBox.get_children()]
                 try:
+                    linecache.clearcache()
                     reload(curveview)
                     # mem problem somewhere; need to hold a ref to this
                     self.curvesetView = curveview.Curvesetview(
                         curvesVBox, curveset)
                     self.curvesetView._mtime = m
 
-                    # curvesetview must already exist, since this makes 'add_curve'
-                    # signals for all the initial curves
+                    # curvesetview must already exist, since this
+                    # makes 'add_curve' signals for all the initial
+                    # curves
                     curveset.load(basename=os.path.join(
                         showconfig.curvesDir(),
                         showconfig.songFilenameFromURI(song)),
                                   skipMusic=opts.skip_music)
-                    # this is scheduled after some tk shuffling, to try to minimize
-                    # the number of times we redraw the curve at startup. If tk is
-                    # very slow, it's ok. You'll just get some wasted redraws.
+                    # this is scheduled after some tk shuffling, to
+                    # try to minimize the number of times we redraw
+                    # the curve at startup. If tk is very slow, it's
+                    # ok. You'll just get some wasted redraws.
                     self.curvesetView.goLive()
                 except Exception, e:
                     print "reload failed:", e
@@ -95,6 +99,13 @@
 
         #zc = Zoomcontrol(root)
 
+    def onPlayPause(self, item):
+        # since the X coord in a curveview affects the handling, one
+        # of them may be able to pick this up
+        results = dispatcher.send("onPlayPause")
+        times = [t for listener, t in results if t is not None]
+        self.music.playOrPause(t=times[0] if times else None)
+
     def onSave(self, *args):
         savekey(song, subterms, curveset)
 
@@ -193,7 +204,7 @@
     maxtime = wavelength(musicfilename)
     dispatcher.connect(lambda: maxtime, "get max time", weak=False)
 
-    start = Main(graph, opts, song, curveset, subterms)
+    start = Main(graph, opts, song, curveset, subterms, music)
 
     dispatcher.send("max time", maxtime=maxtime)
     dispatcher.send("show all")
--- a/light9/curvecalc/curvecalc.glade	Sat Jun 09 10:28:06 2012 +0000
+++ b/light9/curvecalc/curvecalc.glade	Sun Jun 10 04:03:00 2012 +0000
@@ -167,8 +167,10 @@
                         <property name="use_action_appearance">False</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Play/pause (C-p)</property>
+                        <property name="label" translatable="yes">_Play/pause</property>
                         <property name="use_underline">True</property>
+                        <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+                        <signal name="activate" handler="onPlayPause" swapped="no"/>
                       </object>
                     </child>
                   </object>
@@ -182,6 +184,7 @@
                 <property name="can_focus">False</property>
                 <property name="label" translatable="yes">Poin_ts</property>
                 <property name="use_underline">True</property>
+                <signal name="activate" handler="onPlayPause" swapped="no"/>
                 <child type="submenu">
                   <object class="GtkMenu" id="menu4">
                     <property name="visible">True</property>
@@ -327,7 +330,6 @@
                           <object class="GtkViewport" id="viewport1">
                             <property name="visible">True</property>
                             <property name="can_focus">False</property>
-                            <property name="vscroll_policy">natural</property>
                             <property name="shadow_type">none</property>
                             <child>
                               <object class="GtkTable" id="subterms">
--- a/light9/curvecalc/curveview.py	Sat Jun 09 10:28:06 2012 +0000
+++ b/light9/curvecalc/curveview.py	Sun Jun 10 04:03:00 2012 +0000
@@ -8,7 +8,7 @@
 from light9.dmxchanedit import gradient
 
 log = logging.getLogger()
-
+print "curveview.py toplevel"
 def vlen(v):
     return math.sqrt(v[0]*v[0] + v[1]*v[1])
 
@@ -74,6 +74,7 @@
     def __init__(self, curve, knobEnabled=False, isMusic=False, **kw):
         """knobEnabled=True highlights the previous key and ties it to a
         hardware knob"""
+        print "new curveview" 
         self.widget = goocanvas.Canvas()
         self.widget.set_property("background-color", "gray20")
         self.widget.set_size_request(-1, 100)
@@ -85,8 +86,10 @@
         self._isMusic = isMusic
         self._time = 0
         self.last_mouse_world = None
+        self.entered = False # is the mouse currently over this widget
         self.selected_points=[] # idx of points being dragged
         # self.bind("<Enter>",self.focus)
+        dispatcher.connect(self.playPause, "onPlayPause")
         dispatcher.connect(self.input_time, "input time")
         dispatcher.connect(self.update_curve, "zoom changed")
         dispatcher.connect(self.update_curve, "points changed",
@@ -100,8 +103,10 @@
 
         self.widget.connect("size-allocate", self.update_curve)
 
-        self.root.connect("motion-notify-event", self.dotmotion)
-        self.root.connect("button-release-event", self.dotrelease)
+        self.widget.connect("leave-notify-event", self.onLeave)
+        self.widget.connect("enter-notify-event", self.onEnter)
+        self.widget.connect("motion-notify-event", self.onMotion)
+        self.widget.connect("button-release-event", self.onRelease)
         
         if 0:
 
@@ -129,15 +134,6 @@
                       dispatcher.send("see time until end",
                                       t=self.current_time()))
             self.bind("<Control-Escape>", lambda ev: dispatcher.send("show all"))
-            self.bind("<Control-p>", lambda ev:
-                      dispatcher.send("music seek",
-                                      t=self.world_from_screen(ev.x,0)[0]))
-
-            self.bind("<Motion>",
-                      self.dotmotion, add=True)
-            self.bind("<ButtonRelease-1>",
-                      self.dotrelease, add=True)
-
 
         # this binds on c-a-b1, etc
         if 0:
@@ -166,6 +162,20 @@
             self.bind("<Key-c>", lambda *args: dispatcher.send('toggle collapse',
                                                                sender=self.curve))
 
+    def playPause(self):
+        """
+        user has pressed ctrl-p over a curve view, possibly this
+        one. Returns the time under the mouse if we know it, or else
+        None
+        """
+        print id(self), "checking", self.entered
+        if self.entered:
+            t = self.world_from_screen(self.lastMouseX, 0)[0]
+            print self.lastMouseX, t
+            return t
+        return None
+        #dispatcher.send("music seek", t=self.world_from_screen(ev.x,0)[0])
+
     def goLive(self):
         """this is for startup performance only, since the curves were
         getting redrawn many times. """
@@ -263,19 +273,26 @@
         start,end = self.zoom
         ht = self.size.height
         return x/self.size.width*(end-start)+start, ((ht-5)-y)/(ht-10)
-    
+
     def input_time(self, val, forceUpdate=False):
         # i tried various things to make this not update like crazy,
         # but the timeline was always missing at startup, so i got
         # scared that things were getting built in a funny order.        
         #if self._time == val:
         #    return
-        return
         t=val
-        pts = self.screen_from_world((val,0))+self.screen_from_world((val,1))
-        self.delete('timecursor')
-        self.create_line(*pts,**dict(width=2,fill='red',tags=('timecursor',)))
-        self.have_time_line = True
+
+        if not getattr(self, 'timelineLine', None):
+            self.timelineGroup = goocanvas.Group(parent=self.root)
+            self.timelineLine = goocanvas.Polyline(
+                parent=self.timelineGroup,
+                points=goocanvas.Points([(0,0), (0,0)]),
+                line_width=2, stroke_color='red')
+
+        self.timelineLine.set_property('points', goocanvas.Points([
+            self.screen_from_world((val,0)),
+            self.screen_from_world((val,1))]))
+        
         self._time = t
         if self.knobEnabled:
             self.delete('knob')
@@ -292,7 +309,7 @@
         if not self.redrawsEnabled:
             return
         self.size = self.widget.get_allocation()
-
+ 
         self.zoom = 0, 228#dispatcher.send("zoom area")[0][1]
         cp = self.curve.points
 
@@ -537,15 +554,23 @@
         self.selected_points = self.curve.indices_between(start,end)
         self.highlight_selected_dots()
 
-    def dotmotion(self, group, hitObject, ev):
+    def onEnter(self, widget, event):
+        self.entered = True
+
+    def onLeave(self, widget, event):
+        self.entered = False
+
+    def onMotion(self, widget, event):
+        self.lastMouseX = event.x
+        
         if not self.dragging_dots:
             return
-        if not ev.state & 256:
+        if not event.state & 256:
             return # not lmb-down
         cp = self.curve.points
         moved=0
 
-        cur = self.world_from_screen(ev.x, ev.y)
+        cur = self.world_from_screen(event.x, event.y)
         if self.last_mouse_world:
             delta = (cur[0] - self.last_mouse_world[0],
                      cur[1] - self.last_mouse_world[1])
@@ -572,7 +597,7 @@
         self.selected_points=[]
         self.highlight_selected_dots()
         
-    def dotrelease(self, group, hitObject, ev):
+    def onRelease(self, widget, event):
         self.print_state("dotrelease")
         if not self.dragging_dots:
             return
@@ -699,12 +724,12 @@
         entry = tk.Entry(f, textvariable=self.newcurvename)
         entry.pack(side='left', fill='x',exp=1)        
         entry.bind("<Key-Return>", self.new_curve)
-
-        def focus_entry():
-            entry.focus()
+        self.entry = entry
         
         
-        dispatcher.connect(focus_entry, "focus new curve", weak=False)
+        dispatcher.connect(self.focus_entry, "focus new curve")
+    def focus_entry(self):
+        self.entry.focus()
 
     def new_curve(self, event):
         self.curveset.new_curve(self.newcurvename.get())
--- a/light9/curvecalc/musicaccess.py	Sat Jun 09 10:28:06 2012 +0000
+++ b/light9/curvecalc/musicaccess.py	Sun Jun 10 04:03:00 2012 +0000
@@ -46,7 +46,6 @@
     def __init__(self):
         self.recenttime=0
         self.player = Agent(reactor)
-        dispatcher.connect(self.seekplay_or_pause,"music seek")
         self.timePath = networking.musicPlayer.path("time")
         
     def current_time(self):
@@ -66,13 +65,15 @@
         dispatcher.send("input time", val=data['t'])
         return data['t'] # pass along to the real receiver
     
-    def seekplay_or_pause(self,t):
-        d = self.player.request("POST",
+    def playOrPause(self, t=None):
+        if t is None:
+            # could be better
+            self.current_time().addCallback(lambda t: self.playOrPause(t))
+        else:
+            self.player.request("POST",
                                 networking.musicPlayer.path("seekPlayOrPause"),
                                 bodyProducer=StringProducer(json.dumps({"t" : t})))
 
-
-
 def currentlyPlayingSong():
     """ask the music player what song it's on"""
     player = restkit.Resource(networking.musicPlayer.url)