Source code for ly.barcheck

# This file is part of python-ly, https://pypi.python.org/pypi/python-ly
#
# Copyright (c) 2008 - 2015 by Wilbert Berendsen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# See http://www.gnu.org/licenses/ for more information.

"""
Add, check or remove bar checks in selected music.
"""

from __future__ import unicode_literals
from __future__ import print_function

import collections
import itertools

import ly.document
import ly.lex.lilypond


[docs]def remove(cursor): """Remove bar checks from the selected music.""" s = ly.document.Source(cursor, tokens_with_position=True) prv, cur = None, None with cursor.document as d: for nxt in itertools.chain(s, (None,)): if isinstance(cur, ly.lex.lilypond.PipeSymbol): if isinstance(prv, ly.lex.Space): # pipesymbol and adjacent space may be deleted if nxt == '\n': del d[prv.pos:cur.end] elif isinstance(nxt, ly.lex.Space): del d[cur.pos:nxt.end] else: del d[cur.pos:cur.end] elif isinstance(nxt, ly.lex.Space): # delete if followed by a space del d[cur.pos:cur.end] else: # replace "|" with a space d[cur.pos:cur.end] = " " prv, cur = cur, nxt
[docs]class event(object): """A limited event type at a certain time.""" def __init__(self): self._nodes = [] self.cadenza = None self.barcheck = False self.timesig = None self.partial = None
[docs] def append(self, node): self._nodes.append(node)
def __repr__(self): s = [] if self.cadenza is not None: s.append('cadenza' + ('On' if self.cadenza else 'Off')) if self.barcheck: s.append('bar') if self.timesig is not None: s.append('T{0}'.format(self.timesig)) if self.partial is not None: s.append('P{0}'.format(self.partial)) if self._nodes: s.append(repr(self._nodes)) return '<event {0}>'.format(' '.join(s))
[docs]def insert(cursor, music=None): """Insert bar checks within the selected range.""" if music is None: import ly.music music = ly.music.document(cursor.document) if len(music) == 0: return if cursor.start: n = music.node(cursor.start, 1) nodes = itertools.chain((n,), n.forward()) else: nodes = music if cursor.end is None: iter_nodes = iter else: predicate = lambda node: node.position < cursor.end def iter_nodes(it): return itertools.takewhile(predicate, it) # make time-based lists of events event_lists = [] def do_topnode(node): if not isinstance(node, ly.music.items.Music): for n in node: do_topnode(n) return def do_node(node, time, scaling): if isinstance(node, (ly.music.items.Durable, ly.music.items.UserCommand)): if node.position >= cursor.start: events[time].append(node) time += node.length() * scaling elif isinstance(node, ly.music.items.TimeSignature): events[time].timesig = node.measure_length() elif isinstance(node, ly.music.items.Partial): events[time].partial = node.length() elif isinstance(node, ly.music.items.PipeSymbol): events[time].barcheck = True elif isinstance(node, ly.music.items.Command) and node.token in ( 'cadenzaOn', 'cadenzaOff'): events[time].cadenza = node.token == 'cadenzaOn' elif isinstance(node, ly.music.items.Grace): pass elif isinstance(node, ly.music.items.LyricMode): pass elif isinstance(node, ly.music.items.MusicList) and node.simultaneous: time = max(do_node(n, time, scaling) for n in iter_nodes(node)) elif isinstance(node, ly.music.items.Music): if isinstance(node, ly.music.items.Scaler): scaling *= node.scaling for n in iter_nodes(node): time = do_node(n, time, scaling) else: do_topnode(node) return time events = collections.defaultdict(event) do_node(node, 0, 1) event_lists.append(sorted(events.items())) do_topnode(nodes) for event_list in event_lists: # default to 4/4 without pickup measure_length = 1 measure_pos = 0 for time, evt in event_list: print(time, evt)