class MainWidget2(BaseWidget): def __init__(self): super(MainWidget2, self).__init__() # create a clock and a tempo map self.clock = Clock() self.tempo_map = SimpleTempoMap(120) # and text to display our status self.label = topleft_label() self.add_widget(self.label) def on_key_down(self, keycode, modifiers): if keycode[1] == 'c': self.clock.toggle() def on_update(self): time = self.clock.get_time() tick = self.tempo_map.time_to_tick(time) bpm = self.tempo_map.get_tempo() self.label.text = 'time:{:.2f}\n'.format(time) self.label.text += tick_str(tick) + '\n' self.label.text += 'bpm:{}\n'.format(bpm) self.label.text += 'c: toggle clock\n'
class MainWidget4(BaseWidget): def __init__(self): super(MainWidget4, self).__init__() self.audio = Audio(2) self.synth = Synth('../data/FluidR3_GM.sf2') self.audio.set_generator(self.synth) # create clock, tempo_map, scheduler self.clock = Clock() self.tempo_map = SimpleTempoMap(120) self.sched = Scheduler(self.clock, self.tempo_map) # create the metronome: self.metro = Metronome(self.sched, self.synth) # and text to display our status self.label = topleft_label() self.add_widget(self.label) def on_key_down(self, keycode, modifiers): if keycode[1] == 'c': self.clock.toggle() if keycode[1] == 'm': self.metro.toggle() bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10)) if bpm_adj: new_tempo = self.tempo_map.get_tempo() + bpm_adj self.tempo_map.set_tempo(new_tempo, self.sched.get_time()) def on_update(self): # scheduler and audio get poked every frame self.sched.on_update() self.audio.on_update() bpm = self.tempo_map.get_tempo() self.label.text = self.sched.now_str() + '\n' self.label.text += 'Metronome:' + ("ON" if self.metro.playing else "OFF") + '\n' self.label.text += 'tempo:{}\n'.format(bpm) self.label.text += 'm: toggle Metronome\n' self.label.text += 'up/down: change speed\n'
class MainWidget3(BaseWidget): def __init__(self): super(MainWidget3, self).__init__() # create a clock and TempoMap self.clock = Clock() self.tempo = SimpleTempoMap(120) # create a Scheduler self.sched = Scheduler(self.clock, self.tempo) # and text to display our status self.label = topleft_label() self.add_widget(self.label) # to see accumulated output: self.output_text = '' def on_key_down(self, keycode, modifiers): if keycode[1] == 'c': self.clock.toggle() if keycode[1] == 'a': now = self.sched.get_tick() later = now + (2 * kTicksPerQuarter) self.output_text += "now={}. post at tick={}\n".format(now, later) self.cmd = self.sched.post_at_tick(self._do_it, later, 'hello') if keycode[1] == 'b': self.sched.remove(self.cmd) def _do_it(self, tick, msg): self.output_text += "{} (at {})\n".format(msg, tick) def on_update(self): # scheduler gets called every frame to process events self.sched.on_update() self.label.text = self.sched.now_str() + '\n' self.label.text += 'c: toggle clock\n' self.label.text += 'a: post event\n' self.label.text += 'b: remove event\n' self.label.text += self.output_text
class TempoCursorHandler(object): """ Handles the TempoCursor GUI. Also stores and updates all currently active TempoCursors. """ def __init__(self, norm, sandbox, mixer, client, client_id, block_handler, tempo=60): self.norm = norm self.module_name = 'TempoCursor' self.sandbox = sandbox self.mixer = mixer self.client = client self.cid = client_id self.block_handler = block_handler self.tempo = tempo self.clock = Clock() self.tempo_map = SimpleTempoMap(bpm=self.tempo) self.touch_points = {} self.cursors = AnimGroup() self.sandbox.add(self.cursors) self.gui = CursorGUI(norm, pos=self.norm.nt((20, 300)), beat_callback=self.update_touch_points) self.delete_mode = {} def on_touch_down(self, cid, pos): if cid == self.cid: self.gui.on_touch_down(pos) if not self.sandbox.in_bounds(pos): return for cursor in self.cursors.objects: cursor_pos = (cursor.pos[0] - cursor.size[0] / 2, cursor.pos[1] - cursor.size[1] / 2) if in_bounds(pos, cursor_pos, cursor.size): if self.delete_mode[cid]: self.cursors.objects.remove(cursor) self.cursors.remove(cursor) return if self.delete_mode[cid]: return touch_points = self.touch_points[cid] if len(touch_points) == 0: return cursor = TempoCursor(self.norm, pos, self.tempo, self.clock, self.tempo_map, copy.deepcopy(touch_points), self.block_handler) self.cursors.add(cursor) def on_touch_move(self, cid, pos): pass def on_touch_up(self, cid, pos): pass def on_key_down(self, cid, key): if key == 'p': self.clock.toggle() if key == 'v' and cid == self.cid: self.delete_mode[cid] = not self.delete_mode[cid] self.update_server_state(post=True) if key == 'up': self.tempo += 4 self.tempo_map.set_tempo(self.tempo) self.update_server_state(post=True) if key == 'down': self.tempo -= 4 self.tempo_map.set_tempo(self.tempo) self.update_server_state(post=True) def on_update(self): self.cursors.on_update() def update_touch_points(self, touch_points): self.touch_points[self.cid] = touch_points self.update_server_state(post=True) def display_controls(self): cur_time = self.clock.get_time() cur_tick = self.tempo_map.time_to_tick(cur_time) info = 'delete mode: {}\n\n'.format(self.delete_mode[self.cid]) info += 'tempo: {}\n'.format(self.tempo) return info def update_server_state(self, post=False): """Update server state. If post is True, relay this updated state to all clients.""" state = { 'touch_points': self.touch_points, 'delete_mode': self.delete_mode, 'tempo': self.tempo } data = { 'module': self.module_name, 'cid': self.cid, 'state': state, 'post': post } self.client.emit('update_state', data) def update_client_state(self, cid, state): """Update this handler's state.""" if cid != self.cid: # this client already updated its own state self.touch_points = state['touch_points'] self.delete_mode = state['delete_mode'] self.tempo = state['tempo'] def sync_state(self, state): """ Initial sync with the server's copy of module state. """ self.touch_points = state['touch_points'] self.delete_mode = state['delete_mode'] self.tempo = state['tempo'] # after initial sync, add default values for this client self.touch_points[self.cid] = [] self.delete_mode[self.cid] = False # update server with these default values # post=True here because we want all other clients' states to update with this client's # default values. self.update_server_state(post=True)