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 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)
class Session(GameObject): def __init__(self, other_members, tempo, bars, divs, inst_set): super(Session, self).__init__() self.tempo = tempo self.bars = bars self.divs = divs self.inst_set = inst_set spb = 60. / tempo beats = bars * 4 self.seconds = spb * beats self.clock = Clock() self.temp_map = SimpleTempoMap(bpm=tempo) self.sched = Scheduler(self.clock, self.temp_map) # self.players = players self.IM = InstrumentManager(self.sched) self.add(self.IM) ### NEW CODE ### self.pattern_list = PatternList(self.bars, self.tempo, self.inst_set) self.add(self.pattern_list) track = Track(num_lanes, self.bars, self.tempo) track.position.y = Window.height * 0.025 controller = InstrumentKeyboard(default_keycodes, lock_in_keycode) self.player = Player(controller, track, inst_set) self.player.position.x = Window.width - player_size[0] - 20 self.add(self.player) self.vplayers = [] self.add_band_members(other_members) self.IM.add(self.player.instrument) self.clock.offset = self.seconds - spb self.paused = True self.start() def add_band_members(self, other_members): for other_member in other_members: vcontroller = InstrumentController(16, other_member['id']) vtrack = VirtualTrack(num_lanes, self.bars, self.tempo) vplayer = VirtualPlayer(vcontroller, vtrack) self.vplayers.append(vplayer) self.add(vplayer) def on_key_down(self, event): # if event.keycode[1] == 'enter':on # self.toggle() pass def toggle(self): if self.paused: self.paused = False self.start() else: self.paused = True self.stop() def stop(self): self.clock.stop() def start(self): self.clock.start() def next_player(self, sequence): if self.current_player < self.num_players: self.players[self.current_player].note_sequence = sequence self.players[self.current_player].stop_composing() self.current_player += 1 if self.current_player < self.num_players: self.players[self.current_player].start_composing() def on_lock_in(self, event): self.next_player(event.action['sequence']) def on_update(self): self.sched.on_update() # for player in self.players: now = self.clock.get_time() % self.seconds for vplayer in self.vplayers: vplayer.set_now(now) self.player.set_now(now) self.pattern_list.set_now(self.clock.get_time() % self.seconds)