function.
* music.py (ClefEvent.__init__): add
(NoteEvent.ly_expression): add
(Music.has_children): new method.
* musictree.py (MusicTreeView.selection_changed): add Tree view of
music model.
+2005-07-29 Han-Wen Nienhuys <hanwen@xs4all.nl>
+
+ * ikebana.py (NotationApplication.tree_selection_changed): new
+ function.
+
+ * music.py (ClefEvent.__init__): add
+ (NoteEvent.ly_expression): add
+ (Music.has_children): new method.
+
+ * musictree.py (MusicTreeView.selection_changed): add Tree view of
+ music model.
+
2005-07-28 Han-Wen Nienhuys <hanwen@xs4all.nl>
* server.ly: use Completion_heads_engraver
+ use version number.
* music.py (Music.set_start): use Rationals for lengths.
#!/usr/bin/env python
+import musictree
import os
import gtk
import gnomecanvas
class NotationApplication:
def __init__ (self):
- self.music = music.Music_document ()
+ self.document = music.Music_document ()
- nc = notation.Notation_controller (self.music)
+ nc = notation.Notation_controller (self.document)
self.notation_controller = nc
ncc = notationcanvas.Notation_canvas_controller (nc.notation)
self.notation_canvas_controller = ncc
self.window = self.create_window ()
+ self.tree_window =self.create_tree_window ()
+
+ def tree_selection_changed (self, music_obj):
+ nc = self.notation_controller
+ nc.notation.set_cursor (music_obj)
+ self.notation_canvas_controller.check_update()
+
+ def create_tree_window (self):
+ win = gtk.Window ()
+ (w,h) = (500,300)
+ win.set_size_request (w, h)
+
+ win.connect ('destroy', mainquit)
+ win.set_title ('Ikebana - music representation')
+ treeview = musictree.MusicTreeView (self.document.music)
+ win.add(treeview)
+ win.show()
+ treeview.selection_change_callback = self.tree_selection_changed
+
+ notation = self.notation_canvas_controller.notation
+ notation.set_cursor_callback = treeview.cursor_changed
+
+ return win
+
def create_window (self):
win = gtk.Window ()
win.connect ('destroy', mainquit)
def steps (self):
return self.step + self.octave * 7
- def ly_expression (self):
-
+ def ly_step_expression (self):
str = 'cdefgab'[self.step]
if self.alteration > 0:
str += 'is'* (self.alteration/2)
elif self.alteration < 0:
str += 'es'* (-self.alteration/2)
-
+ return str
+
+ def ly_expression (self):
+ str = self.ly_step_expression ()
if self.octave >= 0:
str += "'" * (self.octave + 1)
elif self.octave < -1:
def get_properties (self):
return ''
+ def has_children (self):
+ return False
+
+ def get_index (self):
+ if self.parent:
+ return self.parent.elements.index (self)
+ else:
+ return None
+
def lisp_expression (self):
name = self.name()
tag = ''
def __init__ (self):
Music.__init__ (self)
self.elements = []
-
+ def has_children (self):
+ return self.elements
def set_tag (self, counter, dict):
counter = Music.set_tag (self, counter, dict)
for e in self.elements :
return '%s%s' % (self.pitch.ly_expression (),
self.duration.ly_expression ())
+
+
+class KeySignatureEvent (Event):
+ def __init__ (self, tonic, scale):
+ Event.__init__ (self)
+ self.scale = scale
+ self.tonic = tonic
+ def name (self):
+ return 'KeySignatureEvent'
+ def ly_expression (self):
+ return '\\key %s \\major' % self.tonic.ly_step_expression ()
+
+ def lisp_expression (self):
+ pairs = ['(%d . %d)' % (i , self.scale[i]) for i in range (0,7)]
+ scale_str = ("'(%s)" % string.join (pairs))
+
+ return """ (make-music 'KeyChangeEvent
+ 'pitch-alist %s) """ % scale_str
+
+class ClefEvent (Event):
+ def __init__ (self, t):
+ Event.__init__ (self)
+ self.type = t
+ def name (self):
+
+ return 'ClefEvent'
+ def ly_expression (self):
+ return '\\clef "%s"' % self.type
+ clef_dict = {
+ "G": ("clefs.G", -2, -6),
+ "C": ("clefs.C", 0, 0),
+ "F": ("clefs.F", 2, 6),
+ }
+
+ def lisp_expression (self):
+ (glyph, pos, c0) = self.clef_dict [self.type]
+ clefsetting = """
+ (make-music 'SequentialMusic
+ 'elements (list
+ (context-spec-music
+ (make-property-set 'clefGlyph "%s") 'Staff)
+ (context-spec-music
+ (make-property-set 'clefPosition %d) 'Staff)
+ (context-spec-music
+ (make-property-set 'middleCPosition %d) 'Staff)))
+""" % (glyph, pos, c0)
+ return clefsetting
+
def test_expr ():
m = SequentialMusic()
l =2
evc.insert_around (None, n, 0)
m.insert_around (None, evc, 0)
-
evc = EventChord()
n = NoteEvent()
n.duration.duration_log = l
evc.insert_around (None, n, 0)
m.insert_around (None, evc, 0)
+ evc = ClefEvent("G")
+ m.insert_around (None, evc, 0)
+
+ evc = EventChord()
+ tonic = Pitch ()
+ tonic.step = 2
+ tonic.alteration = -2
+ n = KeySignatureEvent(tonic, [0, 0, -2, 0, 0,-2,-2] )
+ evc.insert_around (None, n, 0)
+ m.insert_around (None, evc, 0)
+
return m
if __name__ == '__main__':
expr = test_expr()
expr.set_start (Rational (0))
-
- start = 0.25
- stop = 0.5
+ print expr.ly_expression()
+ start = Rational (0,4)
+ stop = Rational (4,2)
def sub(x, start=start, stop=stop):
ok = x.start >= start and x.start +x.length() <= stop
return ok
--- /dev/null
+#!/usr/bin/env python
+'''Tree View/Generic Tree Model
+
+This test is designed to demonstrate creating a new type of tree model
+in python for use with the new tree widget in gtk 2.0.'''
+
+import gtk
+import gobject
+
+# to create a new GtkTreeModel from python, you must derive from
+# TreeModel.
+class MusicTreeModel(gtk.GenericTreeModel):
+ '''This class represents the model of a tree. The iterators used
+ to represent positions are converted to python objects when passed
+ to the on_* methods. This means you can use any python object to
+ represent a node in the tree. The None object represents a NULL
+ iterator.
+
+ In this tree, we use simple tuples to represent nodes, which also
+ happen to be the tree paths for those nodes. This model is a tree
+ of depth 3 with 5 nodes at each level of the tree. The values in
+ the tree are just the string representations of the nodes.'''
+
+ def __init__(self, music):
+ '''constructor for the model. Make sure you call
+ PyTreeModel.__init__'''
+ gtk.GenericTreeModel.__init__(self)
+ self.music = music
+
+ # the implementations for TreeModel methods are prefixed with on_
+ def on_get_flags(self):
+ '''returns the GtkTreeModelFlags for this particular type of model'''
+ return 0
+
+ def on_get_n_columns(self):
+ '''returns the number of columns in the model'''
+ return 2
+
+ def on_get_column_type(self, index):
+ '''returns the type of a column in the model'''
+ return gobject.TYPE_STRING
+
+ def on_get_path(self, node):
+ '''returns the tree path(a tuple of indices at the various
+ levels) for a particular node.'''
+
+# print 'on_get_path'
+ if node.parent:
+ return tuple (list (self.on_get_path (node.parent))
+ +
+ [node.get_index ()])
+ else:
+ return (0,)
+
+ def on_get_iter(self, path):
+ '''returns the node corresponding to the given path. In our
+ case, the node is the path'''
+
+# print 'on_get_iter' , path
+
+ ptr = self.music
+ for i in path[1:]:
+ ptr = ptr.elements[i]
+
+ return ptr
+
+ def on_get_value(self, node, column):
+ '''returns the value stored in a particular column for the node'''
+
+ str = ''
+ if column == 0:
+ str = node.name()
+ elif column==1:
+ str = node.ly_expression()
+
+ return str
+
+ def on_iter_next(self, node):
+ '''returns the next node at this level of the tree'''
+# print 'on_iter_next', node
+ if not node.parent:
+ return None
+
+ neigh = node.parent.get_neighbor (node, 1)
+ if neigh <> node:
+ return neigh
+ else:
+ return None
+
+ def on_iter_children(self, node):
+ '''returns the first child of this node'''
+# print 'on_iter_children', node
+ if node.has_children ():
+ return node.elements[0]
+ else:
+ return None
+
+ def on_iter_has_child(self, node):
+ '''returns true if this node has children'''
+ hc = node.has_children ()
+
+# print node, 'has_child', hc
+
+ return hc
+
+ def on_iter_n_children(self, node):
+ '''returns the number of children of this node'''
+ assert node <> None
+
+# print 'on_iter_n_children', node
+
+ return len (node.elements)
+
+ def on_iter_nth_child(self, node, n):
+ '''returns the nth child of this node'''
+ if node == None:
+ return self.music
+
+# print 'on_iter_nth_child', node , n
+
+ return node.elements[n]
+
+ def on_iter_parent(self, node):
+ '''returns the parent of this node'''
+
+# print 'on_iter_parent', node
+
+ return node.parent
+
+class MusicTreeView(gtk.ScrolledWindow):
+ def __init__(self, music):
+ gtk.ScrolledWindow.__init__(self)
+ self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+
+ model = MusicTreeModel (music)
+ self.model = model
+ tree_view = gtk.TreeView(model)
+ cell = gtk.CellRendererText()
+
+ # the text in the column comes from column 0
+ column = gtk.TreeViewColumn("Type", cell, text=0)
+ tree_view.append_column(column)
+ column = gtk.TreeViewColumn("Contents", cell, text=1)
+ tree_view.append_column(column)
+ self.tree_selection = tree_view.get_selection()
+
+ self.add(tree_view)
+ self.show_all()
+
+ self.tree_selection.connect ('changed', self.selection_changed)
+ self.selection_change_callback = None
+
+ def selection_changed (self, a):
+ if self.selection_change_callback:
+ (model, iter) = a.get_selected()
+ path = model.get_path (iter)
+ obj = model.on_get_iter (path)
+ if obj.name() in ('RestEvent', 'NoteEvent'):
+ self.selection_change_callback(obj)
+
+ def select_music (self, music):
+ path = self.model.on_get_path (music)
+ self.tree_selection.select_path (path)
+
+ def cursor_changed (self, notation):
+ self.select_music (notation.music_cursor)
+
+def main():
+ GenericTreeModelDemo()
+ gtk.main()
+
+if __name__ == '__main__':
+ main()
+
measure_length = Rational (time_sig[0], time_sig[1])
measure_count = 4
-scale_str = ("'(%s)" %
- string.join (['(%d . %d)' % (i , scale_alterations[i]) for i in range (0,7)], ' '))
-
-"'((0 . 0) (1 . 0) (2 . -2) (3 . 0) (4 . 0) (5 . -2) (6 . -2))"
-clefsetting = """
- (context-spec-music
- (make-property-set 'clefGlyph "clefs.C") 'Staff)
- (context-spec-music
- (make-property-set 'clefPosition 0) 'Staff)
- (context-spec-music
- (make-property-set 'middleCPosition 0) 'Staff)
-"""
try:
server = os.environ['IKEBANASERVER']
(make-property-set 'beatLength (ly:make-moment 1 %d)) 'Score)
(context-spec-music
(make-property-set 'currentBarNumber %d) 'Score)
- (context-spec-music
- (make-music 'EventChord
- 'elements
- (list
- (make-music 'KeyChangeEvent
- 'pitch-alist
- %s)
- ))
- 'Staff)
-
+
%s))""" % (time_sig[0], time_sig[1], time_sig[0],
- time_sig[1], time_sig[1], num, scale_str, str)
+ time_sig[1], time_sig[1], num, str)
def render_score (filename, ly):
print ly
def interpret_line (self, offset, cause, bbox, name, fields):
notation_item = self.notation.add_item (offset, cause, bbox, fields)
notation_item.name = name
+
def touch_document (self):
self.document.touched = True
new_stop = new_start + Rational (measure_count) * measure_length
if new_start <> self.start_moment or new_stop <> self.stop_moment:
- print "render interval", new_start, new_stop
+# print "render interval", new_start, new_stop
self.touch_document()
self.start_moment = new_start
self.notation_controller = controller
self.touched = True
self.cursor_touched = True
+ self.cursor_callback = None
toplevel = controller.document.music
self.music_cursor = toplevel.find_first (lambda x: x.name()== "NoteEvent")
canvas.set_cursor_to_music (self.music_cursor)
self.touched = False
-
+
def set_cursor (self, music_expr):
- self.music_cursor = music_expr
- self.cursor_touched = True
- self.ensure_cursor_visible ()
+ if music_expr <> self.music_cursor:
+ self.music_cursor = music_expr
+ self.cursor_touched = True
+ self.ensure_cursor_visible ()
+ proc = self.set_cursor_callback
+ if proc:
+ proc (self)
def cursor_move (self, dir):
mus = self.music_cursor
arp = music.ArpeggioEvent()
par.insert_around (self.music_cursor, arp, -1)
self.touch_document()
+
def print_score(self):
doc = self.notation_controller.document
ly = doc.music.ly_expression()
('Shift+B', '+B',
lambda: self.notation.add_step (6), 2),
('c', 'C',
- lambda: self.notation.set_step (0), 3),
+ lambda: self.notation.set_step (0), 2),
('d', 'D',
- lambda: self.notation.set_step (1), 3),
+ lambda: self.notation.set_step (1), 2),
('e', 'E',
- lambda: self.notation.set_step (2), 3),
+ lambda: self.notation.set_step (2), 2),
('f', 'F',
- lambda: self.notation.set_step (3), 3),
+ lambda: self.notation.set_step (3), 2),
('g', 'G',
- lambda: self.notation.set_step (4), 3),
+ lambda: self.notation.set_step (4), 2),
('a', 'A',
- lambda: self.notation.set_step (5), 3),
+ lambda: self.notation.set_step (5), 2),
('b', 'B',
- lambda: self.notation.set_step (6), 3)]:
+ lambda: self.notation.set_step (6), 2)]:
self.add_button (text, key_name, func, row)
gnomecanvas.Canvas.__init__ (self,
#aa=True
)
- (w,h) = (400,200)
+ (w,h) = (400,150)
self.set_size_request (w, h)
self.set_scroll_region (0, 0, w, h)
root = self.root ()