def fill_skips(self, voice): """ Add Skips at the end of the bar, so that it is filled. We assume that any elements already added are placed at the correct timepos. """ # nt = short for "next timepos", the timepos to start fill skips to if voice.get_timeposes_of(self): nt = voice.get_timeposes_of(self)[-1] nt = nt + voice.m_tdict[nt]['elem'][0].m_duration.get_rat_value() else: # we get here if the bar is empty nt = self.m_timepos default_skip = Rat(1, 4) # pos within default skip pp = nt - int (nt / default_skip) * default_skip if pp != Rat(0, 1): # Here we add a skip so that the next column will be X times # default_skip voice.set_elem([Skip(Duration.new_from_rat(default_skip - pp))], nt) nt += (default_skip - pp) # And the we fill the bar with Skips as long as default_skip. while nt < self.end(): voice.set_elem([Skip(Duration.new_from_rat(default_skip))], nt) nt += default_skip
def fill_skips(self, voice): """ Add Skips at the end of the bar, so that it is filled. We assume that any elements already added are placed at the correct timepos. """ # nt = short for "next timepos", the timepos to start fill skips to if voice.get_timeposes_of(self): nt = voice.get_timeposes_of(self)[-1] nt = nt + voice.m_tdict[nt]['elem'][0].m_duration.get_rat_value() else: # we get here if the bar is empty nt = self.m_timepos default_skip = Rat(1, 4) # pos within default skip pp = nt - int(nt / default_skip) * default_skip if pp != Rat(0, 1): # Here we add a skip so that the next column will be X times # default_skip voice.set_elem([Skip(Duration.new_from_rat(default_skip - pp))], nt) nt += (default_skip - pp) # And the we fill the bar with Skips as long as default_skip. while nt < self.end(): voice.set_elem([Skip(Duration.new_from_rat(default_skip))], nt) nt += default_skip
def f(widget, i): added = self.g_rwidget.on_add_item(elems.Rest(Duration(i, 0))) if self.g_add_dots_toggle.get_active(): self.g_rwidget.on_toggle_dots(1) if added: self.g_rwidget.cursor_next() self.g_rwidget.grab_focus() self.g_rwidget.score_updated()
def on_key_press(self, window, event): if not self.m_editable: return key_dict = { Gdk.KEY_1: 1, Gdk.KEY_2: 2, Gdk.KEY_3: 4, Gdk.KEY_4: 8, Gdk.KEY_5: 16, Gdk.KEY_6: 32, } if event.keyval in (Gdk.KEY_Right, Gdk.KEY_KP_Right): self.cursor_next() self.queue_draw() elif event.keyval in (Gdk.KEY_Left, Gdk.KEY_KP_Left): self.cursor_prev() self.queue_draw() elif event.keyval == Gdk.KEY_BackSpace: self.backspace() elif event.keyval in (Gdk.KEY_Delete, Gdk.KEY_KP_Delete): self.delete() elif event.keyval in key_dict: if self.m_input_mode == self.NOTE_INPUT: added = self.on_add_item( elems.Note(MusicalPitch.new_from_notename("c"), Duration(key_dict[event.keyval], 0))) else: assert self.m_input_mode == self.REST_INPUT added = self.on_add_item( elems.Rest(Duration(key_dict[event.keyval], 0))) if added: self.cursor_next() self.queue_draw() self.grab_focus() elif event.keyval == Gdk.KEY_period: self.on_toggle_dots(1) elif event.keyval == Gdk.KEY_colon: self.on_toggle_dots(-1) elif event.keyval == Gdk.KEY_t: self.on_toggle_tie() elif event.keyval == Gdk.KEY_r: if self.m_input_mode == self.NOTE_INPUT: self.m_input_mode = self.REST_INPUT else: self.m_input_mode = self.NOTE_INPUT
def f(widget, i): added = self.g_rwidget.on_add_item(elems.Note( MusicalPitch.new_from_notename("c"), Duration(i, 0))) if self.g_add_dots_toggle.get_active(): self.g_rwidget.on_toggle_dots(1) if added: self.g_rwidget.cursor_next() self.g_rwidget.grab_focus()
def new_from_string(string): s = string.strip() m = re_melodic.match(s) if m.end() < len(s) - 1: # FIXME: raise ValueError like rest raise Note.Exception("characters left in string", string) return Note( MusicalPitch.new_from_notename("%s%s" % (m.group('notename'), m.group('octave'))), Duration.new_from_string("%s%s" % (m.group('len'), m.group('dots'))) )
def new_from_string(string): s = string.strip() m = re_melodic.match(s) if m.end() < len(s) - 1: # FIXME: raise ValueError like rest raise Note.Exception("characters left in string", string) return Note( MusicalPitch.new_from_notename( "%s%s" % (m.group('notename'), m.group('octave'))), Duration.new_from_string("%s%s" % (m.group('len'), m.group('dots'))))
def new_from_string(string): return Skip(Duration.new_from_string(string))
def new_from_string(string): return Rest(Duration.new_from_string(string))
class RhythmWidget(MusicDisplayer): """ Rhythm widget editor. Before editing, we feed it a Score objects with notes and/or skips. The user is not allowed to add skips in the middle of the rhythm. Only rests. """ skipdur = Duration(4, 0) NOTE_INPUT = 1 REST_INPUT = 2 def __init__(self): MusicDisplayer.__init__(self) self.g_d.connect("expose_event", self.on_draw_cursor) self.add_events(gtk.gdk.KEY_RELEASE_MASK) self.add_events(gtk.gdk.BUTTON_PRESS_MASK) self.connect("key-press-event", self.on_key_press) self.set_flags(gtk.CAN_FOCUS) def f(*w): self.grab_focus() self.connect("button-press-event", f) self.m_cursor = None self.m_input_mode = RhythmWidget.NOTE_INPUT def get_cursor_timepos(self): """ Return the timepos the cursor has. Return None if the cursor is not visible, for example when the staff is completely empty. """ if self.m_cursor is None: return if not self.m_score.m_staffs: return None timeposes = self.m_score.m_staffs[0].get_timeposes() if timeposes: return self.m_score.m_staffs[0].get_timeposes()[self.m_cursor] return def cursor_prev(self): if self.m_cursor > 0: self.m_cursor -= 1 self.adjust_hadjustment() self.emit('cursor-moved') def cursor_next(self): if self.m_cursor < len(self.m_score.m_staffs[0].get_timeposes()) - 1: self.m_cursor += 1 self.adjust_hadjustment() self.emit('cursor-moved') def backspace(self): if self.m_cursor > 0: self.cursor_prev() self.delete() self.adjust_hadjustment() self.emit('cursor-moved') def on_key_press(self, window, event): if not self.m_editable: return key_dict = {gtk.keysyms._1: 1, gtk.keysyms._2: 2, gtk.keysyms._3: 4, gtk.keysyms._4: 8, gtk.keysyms._5: 16, gtk.keysyms._6: 32, } if event.keyval in (gtk.keysyms.Right, gtk.keysyms.KP_Right): self.cursor_next() self.queue_draw() elif event.keyval in (gtk.keysyms.Left, gtk.keysyms.KP_Left): self.cursor_prev() self.queue_draw() elif event.keyval == gtk.keysyms.BackSpace: self.backspace() elif event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete): self.delete() elif event.keyval in key_dict: if self.m_input_mode == self.NOTE_INPUT: added = self.on_add_item(elems.Note(MusicalPitch.new_from_notename("c"), Duration(key_dict[event.keyval], 0))) else: assert self.m_input_mode == self.REST_INPUT added = self.on_add_item(elems.Rest( Duration(key_dict[event.keyval], 0))) if added: self.cursor_next() self.queue_draw() self.grab_focus() elif event.keyval == gtk.keysyms.period: self.on_toggle_dots(1) elif event.keyval == gtk.keysyms.colon: self.on_toggle_dots(-1) elif event.keyval == gtk.keysyms.t: self.on_toggle_tie() elif event.keyval == gtk.keysyms.r: if self.m_input_mode == self.NOTE_INPUT: self.m_input_mode = self.REST_INPUT else: self.m_input_mode = self.NOTE_INPUT def on_toggle_tie(self): timepos = self.get_cursor_timepos() if not isinstance(self.m_score.voice11.m_tdict[timepos]['elem'][0], elems.Note): return if self.m_score.voice11.m_tdict[timepos]['elem'][0].m_tieinfo in (None, 'end'): if self.m_score.voice11.tie_timepos(timepos): self.score_updated() elif self.m_score.voice11.m_tdict[timepos]['elem'][0].m_tieinfo in ('start', 'go'): if self.m_score.voice11.untie_next(timepos): self.score_updated() def delete(self): timepos = self.get_cursor_timepos() self.m_score.voice11.del_elem(timepos) self.score_updated() def on_toggle_dots(self, delta): """ delta is the number of dots to add or remove. Return True if the number of dots was changed. Return False if not allowed. """ timepos = self.get_cursor_timepos() elem = self.m_score.voice11.m_tdict[timepos]['elem'][0] if isinstance(elem, elems.Skip): return False if elem.m_duration.m_dots + delta < 0: return False new_elem = copy.deepcopy(self.m_score.voice11.m_tdict[timepos]['elem'][0]) new_elem.m_duration.m_dots += delta if self.m_score.voice11.try_set_elem(new_elem, timepos, False): self.score_updated() return True def on_add_item(self, item): """ Return True if an item was added. Return False if it was not added. """ if self.m_score.voice11.try_set_elem(item, self.get_cursor_timepos(), self.m_ins_mode): self.score_updated() self.adjust_hadjustment() return True return False def set_score(self, score, cursor=0): self.m_score = score self.m_cursor = cursor self.score_updated() def score_updated(self): """ Redraw the staff. This should be called whenever m_score is updated. It is not necessary to call when only the cursor have been moved. """ self.m_scorecontext = engravers.ScoreContext(self.m_score) self.m_engravers = self.m_scorecontext.m_contexts self._display() if self.m_score.m_staffs: timeposes = self.m_score.m_staffs[0].get_timeposes() if self.m_cursor > len(timeposes) - 1: self.m_cursor = len(timeposes) - 1 else: self.m_cursor = None self.emit('score-updated') def on_draw_cursor(self, darea, event): timepos = self.get_cursor_timepos() if not timepos: return engraver = None for e in self.m_scorecontext.m_contexts[0].m_engravers[timepos]['elem']: if isinstance(e, (engravers.NoteheadEngraver, engravers.RestEngraver, engravers.SkipEngraver)): engraver = e break if not engraver: return red = self.window.get_colormap().alloc_color('#FF0000', True, True) red = self.window.new_gc(red) y = engravers.dim20.first_staff_ypos + 10 self.m_cursor_xpos = engraver.m_xpos darea.window.draw_rectangle(red, True, engraver.m_xpos, y, 10, 3) def adjust_hadjustment(self): # Auto scrolling adj = self.get_hadjustment() if self.m_cursor_xpos > adj.value + adj.page_size * 0.7: x = self.m_cursor_xpos - adj.page_size * 0.7 if x > adj.upper - adj.page_size: x = adj.upper - adj.page_size adj.set_value(x) if self.m_cursor == 0: adj.set_value(0.0) if self.m_cursor_xpos < adj.value + adj.page_size * 0.3: x = self.m_cursor_xpos - adj.page_size * 0.3 if x < 0: x = 0 adj.set_value(x)