def __init__(self): gtk.Window.__init__(self) vbox = gtk.VBox() self.add(vbox) self.set_default_size(600, 400) self.w = RhythmWidget() s = elems.Score() s.add_staff(staff_class=elems.RhythmStaff) s.add_bar(elems.TimeSignature(3, 4)) s.add_bar(elems.TimeSignature(3, 4)) s.voice11.fill_with_skips() self.w.set_score(s) vbox.pack_start(self.w) # c = RhythmWidgetController(self.w) vbox.pack_start(c, False) c.show() c.set_editable(True) self.connect('delete_event', self.quit)
def __init__(self, staff, last_timepos): """ Create engraver objects for the staff, one timepos at the time. Append them to self, and add refs to them in the m_engravers dict to access them by timepos and type. """ list.__init__(self) self.m_label = getattr(staff, 'm_label', None) self.m_engravers = {} # When joining two empty Scores with Score.concat2, we need to return # to avoid IndexErrors further down this method. if not staff.w_parent().m_bars: return # make a set of all timeposes in the staffs voices t = set() # We need to add the timepos of the beginning of all bars, since # all staffs has to display the time signature if it changes. Normally # it is not necessary to do this here, since staff.m_tdict will have # the timepos. But it is necessary for Scores created by Score.concat2 [t.add(b.m_timepos) for b in staff.w_parent().m_bars] # Then we add the timepos of all notes and rests [t.add(tp) for tp in staff.m_tdict] for voice in staff.m_voices: [t.add(tp) for tp in voice.m_tdict] if last_timepos is None: # display all notes timeposes = sorted(t) else: timeposes = [x for x in sorted(t) if x < last_timepos] # clef = None keysig = ("c", "major") self.refill_accidentals_info(keysig) for voice in staff.m_voices: # tmp variable needed to keep track of the beams. Deleted at method exit. voice.m_beam = None voice.m_ties = {} # tuplet voice.m_tuplet = None bar_idx = 0 props = { 'hide-timesignature': False, } beams = [] for timepos in timeposes: if (bar_idx < len(staff.w_parent().m_bars) - 1 and timepos == staff.w_parent().m_bars[bar_idx + 1].m_timepos): bar_idx += 1 if timepos not in self.m_engravers: self.m_engravers[timepos] = {} eng = self.m_engravers[timepos] ############## # Properties # ############## if (timepos in staff.m_tdict and 'properties' in staff.m_tdict[timepos]): props.update(staff.m_tdict[timepos]['properties']) # Forget accidentals at bar lines if timepos == staff.w_parent().m_bars[bar_idx].m_timepos: self.refill_accidentals_info(keysig) ######## # Clef # ######## if timepos in staff.m_tdict and 'clef' in staff.m_tdict[timepos]: clef = staff.m_tdict[timepos]['clef'] eng['clef'] = ClefEngraver(staff.m_tdict[timepos]['clef']) self.append(eng['clef']) ################# # Key signature # ################# if timepos in staff.m_tdict and 'keysig' in staff.m_tdict[timepos]: eng['keysig'] = KeySignatureEngraver( keysig, staff.m_tdict[timepos]['keysig'], clef) self.append(eng['keysig']) keysig = staff.m_tdict[timepos]['keysig'] self.refill_accidentals_info(keysig) ################## # Time signature # ################## if not staff.w_parent().m_bars: return if (props['hide-timesignature'] == False and ((timepos == staff.w_parent().m_bars[bar_idx].m_timepos and bar_idx > 0 and staff.w_parent().m_bars[bar_idx].m_timesig != staff.w_parent().m_bars[bar_idx - 1].m_timesig) or timepos == elems.TimeSignature(0, 1))): eng['timesig'] = TimeSignatureEngraver( staff.w_parent().m_bars[bar_idx].m_timesig) self.append(eng['timesig']) ############### # Accidentals # ############### if isinstance(self, StaffContext): v = {} for voice in staff.m_voices: if timepos not in voice.m_tdict: continue # If the 'elem' is a rest or skip, # then there are no accidentals. if isinstance(voice.m_tdict[timepos]['elem'][0], (elems.Rest, elems.Skip)): continue for elem in voice.m_tdict[timepos]['elem']: e = self.needed_accidental(elem.m_musicalpitch) if e is not None: v[clef.steps_to_ylinepos( elem.m_musicalpitch.steps())] = e if v: self.append(AccidentalsEngraver(v)) eng['accidentals'] = self[-1] ############################################ # Create stems, noteheads and ledger lines # ############################################ # These two count show many ledger lines we need. yline_up = 0 yline_down = 0 for voice in staff.m_voices: if timepos not in voice.m_tdict: continue if 'elem' in voice.m_tdict[timepos]: elem = voice.m_tdict[timepos]['elem'] if isinstance(elem, elems.Stem): if elem.m_beaminfo == 'start': voice.m_beam = BeamEngraver() beams.append(voice.m_beam) self.append(voice.m_beam) # If the tuplet contain only one tone, then elem.m_tupletinfo == 'end' and # voice.m_tuplet will be None if elem.m_tupletinfo == 'start' or ( elem.m_tupletinfo == 'end' and voice.m_tuplet == None): voice.m_tuplet = TupletEngraver( elem.m_tuplet_ratio, elem.m_tuplet_dir) if 'elem' not in eng: eng['elem'] = [] if isinstance(voice.m_tdict[timepos]['elem'][0], elems.Rest): e = RestEngraver( 0, voice.m_tdict[timepos]['elem'][0].m_duration) self.append(e) eng['elem'].append(e) elif isinstance(elem[0], elems.Skip): e = SkipEngraver(elem[0].m_duration) self.append(e) eng['elem'].append(e) elif not isinstance(voice.m_tdict[timepos]['elem'][0], elems.Skip): elist, stemengraver = self.create_notehead_engraver( clef, voice.m_tdict[timepos]['elem']) for note, engraver in zip( voice.m_tdict[timepos]['elem'], elist): if note.m_tieinfo == 'start': voice.m_ties[note.m_musicalpitch. get_octave_notename()] = engraver elif note.m_tieinfo == 'go': self.append( TieEngraver( voice.m_ties[note.m_musicalpitch. get_octave_notename()], engraver)) del voice.m_ties[ note.m_musicalpitch.get_octave_notename()] voice.m_ties[note.m_musicalpitch. get_octave_notename()] = engraver elif note.m_tieinfo == 'end': self.append( TieEngraver( voice.m_ties[note.m_musicalpitch. get_octave_notename()], engraver)) del voice.m_ties[ note.m_musicalpitch.get_octave_notename()] if voice.m_beam: stemengraver.m_is_beamed = True voice.m_beam.add_stem(stemengraver) if voice.m_tuplet: voice.m_tuplet.add_stem(stemengraver) eng['elem'].extend(elist) eng['elem'].append(stemengraver) self.extend(elist) self.append(stemengraver) if isinstance(elem, elems.Stem): if elem.m_beaminfo == 'end': voice.m_beam = None if elem.m_tupletinfo == 'end': self.append(voice.m_tuplet) voice.m_tuplet = None # Ledger lines for elem in voice.m_tdict[timepos]['elem']: if isinstance(elem, elems.Note): if not clef: # clef is None on a rhythm staff. Then we need no # ledger lines continue ypos = clef.steps_to_ylinepos( elem.m_musicalpitch.steps()) if yline_up > ypos < -5: yline_up = ypos if yline_down < ypos > 5: yline_down = ypos if yline_up: yline_up = -yline_up / 2 - 2 if yline_down: yline_down = yline_down / 2 - 2 if yline_up or yline_down: e = LedgerLineEngraver(yline_up, yline_down) eng['elem'].append(e) self.append(e) # We do this here instead of further up where we check for' # if m_beaminfo == 'end' because we need to do do_layout for beams # even when we only want to engrave the first note in a beam. for b in beams: b.do_layout()
def _next(self): # Doing this while loop inside the exception clause is a little # faster than using a regular expression. try: while self.m_string[self.m_idx] in (' ', '\n', '\t'): self.m_idx += 1 except IndexError: raise StopIteration self.m_last_idx = self.m_idx m = self.re_rest.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() resttype, notelen, dots = m.groups() numdots = len(dots) if notelen: notelen = int(notelen) else: notelen = 0 if numdots: raise LexerError( 'Need a digit before dots. Write "%(goodcode)s", not "%(badcode)s".' % { 'badcode': m.group().strip(), 'goodcode': '%s%i%s' % (resttype, self.m_notelen.m_nh, dots) }, self) if notelen is 0: return self.REST, RestRequest(None, None) else: self.m_notelen = Duration(notelen, numdots) return self.REST, RestRequest(notelen, numdots) m = self.re_skip.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() IGN1, skiplen, dots = m.groups() numdots = len(dots) if skiplen: skiplen = int(skiplen) self.m_notelen = Duration(skiplen, numdots) else: skiplen = 0 if numdots: raise LexerError( 'Need a digit before dots. Write "%(goodcode)s", not "%(badcode)s".' % { 'badcode': m.group().strip(), 'goodcode': 's%i%s' % (self.m_notelen.m_nh, dots) }, self) if skiplen is 0: return self.SKIP, SkipRequest(skiplen, numdots) else: self.m_notelen = Duration(skiplen, numdots) return self.SKIP, SkipRequest(skiplen, numdots) m = self.re_partial.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() num, dot = m.groups() num = int(num) dot = len(dot) return self.PARTIAL, Duration(num, dot) m = self.re_melodic.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() notename, IGN1, IGN2, notelen, dots = m.groups() numdots = len(dots) if notelen: notelen = int(notelen) self.m_notelen = Duration(notelen, numdots) else: notelen = 0 if dots: raise LexerError( 'Need a digit before dots. Write "%(goodcode)s", not "%(badcode)s".' % { 'badcode': m.group().strip(), 'goodcode': '%s%i%s' % (notename, self.m_notelen.m_nh, dots) }, self) n = MusicRequest(notename, notelen, numdots) return self.NOTE, n m = self.re_staff.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.STAFF, None m = self.re_rhythmstaff.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.RHYTHMSTAFF, None m = self.re_voice.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.VOICE, None m = self.re_relative.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.RELATIVE, MusicalPitch.new_from_notename(m.group(1)) m = self.re_clef_quoted.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.CLEF, m.group(1) m = self.re_clef.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.CLEF, m.group(1) m = self.re_stem_updown.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() d = [const.UP, const.DOWN, const.BOTH][['Up', 'Down', 'Both'].index(m.group(2))] return self.STEMDIR, d m = self.re_tuplet_updown.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() d = [const.UP, const.DOWN, const.BOTH][['Up', 'Down', 'Both'].index(m.group(2))] return self.TUPLETDIR, d m = self.re_transpose.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.TRANSPOSE, MusicalPitch.new_from_notename(m.group(1)) m = self.re_time.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.TIME, elems.TimeSignature(int(m.group(1)), int(m.group(2))) m = self.re_key.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.KEY, (m.group(1), m.group(2)) m = self.re_times.match(self.m_string, self.m_idx) if m: self.m_idx = m.end() return self.TIMES, Rat(int(m.groups()[0]), int(m.groups()[1])) if self.m_idx == len(self.m_string): raise StopIteration self.m_idx += 1 return self.m_string[self.m_idx - 1], None