d.duration_log = self.duration_log
d.factor = self.factor
return d
+
+ def length (self):
+ dot_fact = ((1 << (1 + self.dots))-1.0)/ (1 << self.dots)
+
+ return 1.0/(1 << self.duration_log) * dot_fact * self.factor[0]/self.factor[1]
class Pitch:
def __init__ (self):
str = 'cdefgab'[self.step]
if self.alteration > 0:
- str += 'is'* self.alteration
+ str += 'is'* (self.alteration/2)
elif self.alteration < 0:
- str += 'is'* (-self.alteration)
+ str += 'es'* (-self.alteration/2)
if self.octave >= 0:
str += "'" * (self.octave + 1)
def __init__ (self):
self.tag = None
self.parent = None
+ self.start = 0.0
pass
+ def length(self):
+ return 0.0
+
def set_tag (self, counter, tag_dict):
self.tag = counter
tag_dict [counter] = self
tag = "'input-tag %d" % self.tag
props = self.get_properties ()
+# props += 'start %f ' % self.start
return "(make-music '%s %s %s)" % (name, tag, props)
+ def set_start (self, start):
+ start = round (start * 384) / 384.0
+ self.start = start
+
def find_first (self, predicate):
if predicate (self):
return self
self.music = test_expr ()
self.tag_dict = {}
- def reset_tags (self):
+ def recompute (self):
+ print 'recop'
self.tag_dict = {}
self.music.set_tag (0, self.tag_dict)
-
+ self.music.set_start (0.0)
+
class NestedMusic(Music):
def __init__ (self):
Music.__init__ (self)
for e in self.elements :
counter = e.set_tag (counter, dict)
return counter
-
+
def insert_around (self, succ, elt, dir):
assert elt.parent == None
assert succ == None or succ in self.elements
return ("'elements (list %s)"
% string.join (map (lambda x: x.lisp_expression(),
self.elements)))
+
+ def get_subset_properties (self, predicate):
+ return ("'elements (list %s)"
+ % string.join (map (lambda x: x.lisp_expression(),
+ filter ( predicate, self.elements))))
def get_neighbor (self, music, dir):
assert music.parent == self
idx = self.elements.index (music)
self.elements.remove (element)
element.parent = None
+ def set_start (self, start):
+ self.start = start
+ for e in self.elements:
+ e.set_start (start)
+
def find_first (self, predicate):
r = Music.find_first (self, predicate)
if r:
def ly_expression (self):
return '{ %s }' % string.join (map (lambda x:x.ly_expression(),
self.elements))
+ def lisp_sub_expression (self, pred):
+ name = self.name()
+ tag = ''
+ if self.tag:
+ tag = "'input-tag %d" % self.tag
+ props = self.get_subset_properties (pred)
+
+ return "(make-music '%s %s %s)" % (name, tag, props)
+
+ def set_start (self, start):
+ for e in self.elements:
+ e.set_start (start)
+ start += e.length()
+
class EventChord(NestedMusic):
def name(self):
return "EventChord"
+
+ def length (self):
+ l = 0.0
+ for e in self.elements:
+ l = max(l, e.length())
+ return l
+
def ly_expression (self):
str = string.join (map (lambda x: x.ly_expression(),
self.elements))
Event.__init__ (self)
self.duration = Duration()
+ def length (self):
+ return self.duration.length()
+
def get_properties (self):
return ("'duration %s"
% self.duration.lisp_expression ())
def test_expr ():
m = SequentialMusic()
+ l =2
+ evc = EventChord()
+ n = NoteEvent()
+ n.duration.duration_log = l
+ n.pitch.step = 1
+ evc.insert_around (None, n, 0)
+ m.insert_around (None, evc, 0)
+
+ evc = EventChord()
+ n = NoteEvent()
+ n.duration.duration_log = l
+ n.pitch.step = 2
+ evc.insert_around (None, n, 0)
+ m.insert_around (None, evc, 0)
evc = EventChord()
n = NoteEvent()
+ n.duration.duration_log = l
+ n.pitch.step = 3
evc.insert_around (None, n, 0)
m.insert_around (None, evc, 0)
if __name__ == '__main__':
expr = test_expr()
- print expr.lisp_expression()
- print expr.ly_expression()
+ expr.set_start (0.0)
+
+ start = 0.25
+ stop = 0.5
+ def sub(x, start=start, stop=stop):
+ ok = x.start >= start and x.start +x.length() <= stop
+ return ok
+
+ print expr.lisp_sub_expression(sub)
import socket
import music
import pango
+import math
def talk_to_lilypond (expression_str):
"""Send a LISP expression to LilyPond, wait for return value."""
return retval
+def set_measure_number (str, num):
+ return """(make-music 'SequentialMusic 'elements (list
+ (context-spec-music
+ (make-property-set 'currentBarNumber %d) 'Score)
+ %s))""" % (num,str)
class Lilypond_socket_parser:
"""Maintain state of reading multi-line lilypond output for socket transport."""
self.notation = Notation (self)
self.parser = Lilypond_socket_parser (self.interpret_line)
+ self.start_moment = 0.0
+ self.stop_moment = 3.0
def interpret_line (self, offset, cause, bbox, fields):
notation_item = self.notation.add_item (offset, cause, bbox, fields)
def update_notation(self):
doc = self.document
- doc.reset_tags()
+ doc.recompute()
expr = doc.music
+ print 'subexp', self.start_moment, self.stop_moment
- str = expr.lisp_expression()
+ def sub(x):
+ ok = (x.start >= self.start_moment and
+ x.start +x.length() <= self.stop_moment)
+ return ok
+
+
+ str = expr.lisp_sub_expression (sub)
+ str = set_measure_number (str, int (self.start_moment) + 1)
+ print str
str = talk_to_lilypond (str)
self.parse_socket_file (str)
-
+
+ def ensure_visible (self, when):
+ print when
+ self.start_moment = max (math.floor (when - 1.0), 0.0)
+ self.stop_moment = self.start_moment + 3.0
+
def parse_socket_file (self, str):
self.notation.clear ()
lines = string.split (str, '\n')
self.items = []
self.notation_controller = controller
-
toplevel = controller.document.music
self.music_cursor = toplevel.find_first (lambda x: x.name()== "NoteEvent")
mus = mus.parent.get_neighbor (mus, dir)
mus = mus.find_first (lambda x: x.name() in ('NoteEvent', 'RestEvent'))
self.music_cursor = mus
-
+
def insert_at_cursor (self, music, dir):
mus = self.music_cursor
if mus.parent.name() == 'EventChord':
elif p.dots == 0:
p.dots = 1
-
+ def ensure_cursor_visible(self):
+ self.notation_controller.document.recompute()
+ self.notation_controller.ensure_visible (self.music_cursor.start)
+
def change_alteration (self, dir):
if self.music_cursor.name() == 'NoteEvent':
p = self.music_cursor.pitch
if abs (new_alt) <= 4:
p.alteration = new_alt
-
+ def print_score(self):
+ doc = self.notation_controller.document
+ ly = doc.music.ly_expression()
+ print ly