class Sequencer(object): def __init__(self, graph, sendToCollector): self.graph = graph self.sendToCollector = sendToCollector self.music = MusicTime(period=.2, pollCurvecalc=False) self.recentUpdateTimes = [] self.lastStatLog = 0 self._compileGraphCall = None self.notes = {} # song: [notes] self.graph.addHandler(self.compileGraph) self.update() self.codeWatcher = CodeWatcher( onChange=lambda: self.graph.addHandler(self.compileGraph)) def compileGraph(self): log.info('compileGraph request') self._compileGraphRun() return # may not help if self._compileGraphCall: self._compileGraphCall.cancel() self._compileGraphCall = reactor.callLater( .5, self.graph.addHandler, self._compileGraphRun) def _compileGraphRun(self): """rebuild our data from the graph""" self._compileGraphCall = None log.info('compileGraph start') g = self.graph sharedEffectOutputs = {} for song in g.subjects(RDF.type, L9['Song']): self.notes[song] = [] for note in g.objects(song, L9['note']): self.notes[song].append(Note(g, note, effecteval, sharedEffectOutputs)) log.info('compileGraph done') @stats.update.time() def update(self): now = time.time() self.recentUpdateTimes = self.recentUpdateTimes[-20:] + [now] stats.recentFps = len(self.recentUpdateTimes) / (self.recentUpdateTimes[-1] - self.recentUpdateTimes[0] + .0001) if now > self.lastStatLog + 10: log.info("%.2f fps", stats.recentFps) self.lastStatLog = now reactor.callLater(1/50, self.update) musicState = self.music.getLatest() song = URIRef(musicState['song']) if musicState.get('song') else None if 't' not in musicState: return t = musicState['t'] settings = [] for note in self.notes.get(song, []): outs = note.outputSettings(t) #print 'out', outs settings.extend(outs) self.sendToCollector(settings)
class Gui(object): def __init__(self, graph): wtree = gtk.Builder() wtree.add_from_file(sibpath(__file__, "vidref.glade")) mainwin = wtree.get_object("MainWindow") mainwin.connect("destroy", gtk.main_quit) wtree.connect_signals(self) gtk.rc_parse("theme/marble-ice/gtk-2.0/gtkrc") self.recordingTo = wtree.get_object('recordingTo') self.musicScale = wtree.get_object("musicScale") self.musicScale.connect("value-changed", self.onMusicScaleValue) # tiny race here if onMusicScaleValue tries to use musicTime right away self.musicTime = MusicTime(onChange=self.onMusicTimeChange, pollCurvecalc=False) self.ignoreScaleChanges = False # self.attachLog(wtree.get_object("lastLog")) # disabled due to crashing # wtree.get_object("replayPanel").show() # demo only rp = wtree.get_object("replayVbox") self.replayViews = ReplayViews(rp) mainwin.show_all() vid3 = wtree.get_object("vid3") if 0: self.pipeline = Pipeline( liveVideoXid=vid3.window.xid, musicTime=self.musicTime, recordingTo=self.recordingTo) else: self.pipeline = remotepivideo.Pipeline( liveVideo=vid3, musicTime=self.musicTime, recordingTo=self.recordingTo, graph=graph) vid3.props.width_request = 360 vid3.props.height_request = 220 wtree.get_object("frame1").props.height_request = 220 self.pipeline.setInput('v4l') # auto seems to not search for dv gobject.timeout_add(1000 // framerate, self.updateLoop) def snapshot(self): return self.pipeline.snapshot() def attachLog(self, textBuffer): """write log lines to this gtk buffer""" class ToBuffer(logging.Handler): def emit(self, record): textBuffer.set_text(record.getMessage()) h = ToBuffer() h.setLevel(logging.INFO) log.addHandler(h) def updateLoop(self): position = self.musicTime.getLatest() try: with gtk.gdk.lock: self.replayViews.update(position) except: traceback.print_exc() return True def getInputs(self): return ['auto', 'dv', 'video0'] def on_liveVideoEnabled_toggled(self, widget): self.pipeline.setLiveVideo(widget.get_active()) def on_liveFrameRate_value_changed(self, widget): print widget.get_value() def onMusicTimeChange(self, position): self.ignoreScaleChanges = True try: self.musicScale.set_range(0, position['duration']) self.musicScale.set_value(position['t']) finally: self.ignoreScaleChanges = False def onMusicScaleValue(self, scaleRange): """the scale position has changed. if it was by the user, send it back to music player""" if not self.ignoreScaleChanges: self.musicTime.sendTime(scaleRange.get_value()) def incomingTime(self, t, source): self.musicTime.lastHoverTime = t
class Sequencer(object): def __init__(self, graph, sendToCollector, fps=40): self.graph = graph self.fps = fps self.sendToCollector = sendToCollector self.music = MusicTime(period=.2, pollCurvecalc=False) self.recentUpdateTimes = [] self.lastStatLog = 0 self._compileGraphCall = None self.notes = {} # song: [notes] self.simpleOutputs = SimpleOutputs(self.graph) self.graph.addHandler(self.compileGraph) self.updateLoop() self.codeWatcher = CodeWatcher( onChange=lambda: self.graph.addHandler(self.compileGraph)) @stats.compileGraph.time() def compileGraph(self): """rebuild our data from the graph""" t1 = time.time() g = self.graph for song in g.subjects(RDF.type, L9['Song']): self.graph.addHandler(lambda song=song: self.compileSong(song)) log.info('compileGraph took %.2f ms', 1000 * (time.time() - t1)) @stats.compileSong.time() def compileSong(self, song): t1 = time.time() self.notes[song] = [] for note in self.graph.objects(song, L9['note']): self.notes[song].append(Note(self.graph, note, effecteval, self.simpleOutputs)) log.info(' compile %s took %.2f ms', song, 1000 * (time.time() - t1)) def updateLoop(self): # print "updateLoop" now = time.time() self.recentUpdateTimes = self.recentUpdateTimes[-40:] + [now] stats.recentFps = len(self.recentUpdateTimes) / (self.recentUpdateTimes[-1] - self.recentUpdateTimes[0] + .0001) if now > self.lastStatLog + .2: dispatcher.send('state', update={ 'recentDeltas': sorted([round(t1 - t0, 4) for t0, t1 in zip(self.recentUpdateTimes[:-1], self.recentUpdateTimes[1:])]), 'recentFps': stats.recentFps}) self.lastStatLog = now def done(sec): # print "sec", sec # delay = max(0, time.time() - (now + 1 / self.fps)) # print 'cl', delay delay = 0.005 reactor.callLater(delay, self.updateLoop) def err(e): log.warn('updateLoop: %r', e) reactor.callLater(2, self.updateLoop) d = self.update() d.addCallbacks(done, err) @stats.update.time() def update(self): # print "update" try: musicState = self.music.getLatest() song = URIRef(musicState['song']) if musicState.get('song') else None if 't' not in musicState: return defer.succeed(0) t = musicState['t'] dispatcher.send('state', update={'song': str(song), 't': t}) settings = [] songNotes = sorted(self.notes.get(song, []), key=lambda n: n.uri) noteReports = [] for note in songNotes: s, report = note.outputSettings(t) noteReports.append(report) settings.append(s) dispatcher.send('state', update={'songNotes': noteReports}) return self.sendToCollector(DeviceSettings.fromList(self.graph, settings)) except Exception: traceback.print_exc() raise