# the default placement for text in abc is above the staff.
# %%LY now supported.
# \breve and \longa supported.
-
+# M:none doesn't crash lily.
+
# Limitations
#
# Multiple tunes in single file not supported
#TODO:
+#
+# Convert to new chord styles.
+#
# UNDEF -> None
-
+#
program_name = 'abc2ly'
UNDEF = 255
state = UNDEF
+strict = 0
voice_idx_dict = {}
header = {}
header['footnotes'] = ''
DIGITS='0123456789'
alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
HSPACE=' \t'
+midi_specs = ''
+
+def error (msg):
+ sys.stderr.write (msg)
+ if strict:
+ sys.exit (1)
+
def check_clef(s):
if not s:
ks = hdr.keys ()
ks.sort ()
for k in ks:
+ hdr[k] = re.sub('"', '\\"', hdr[k])
outf.write ('\t%s = "%s"\n'% (k,hdr[k]))
outf.write ('}')
outf.write(" >\n \\paper{}\n}\n")
def dump_default_bar (outf):
- outf.write ("\n\\property Score.defaultBarType=\"empty\"\n")
+ """
+ Nowadays abc2ly outputs explicits barlines (?)
+ """
+ outf.write ("\n\\property Score.defaultBarType=\"empty\"\n")
def dump_slyrics (outf):
outf.write("}")
outf.write ("\n}")
+def try_parse_q(a):
+ global midi_specs
+ #assume that Q takes the form "Q:1/4=120"
+ #There are other possibilities, but they are deprecated
+ if string.count(a, '/') == 1:
+ array=string.split(a,'/')
+ numerator=array[0]
+ if numerator != 1:
+ sys.stderr.write("abc2ly: Warning, unable to translate a Q specification with a numerator of %s: %s\n" % (numerator, a))
+ array2=string.split(array[1],'=')
+ denominator=array2[0]
+ perminute=array2[1]
+ duration=str(string.atoi(denominator)/string.atoi(numerator))
+ midi_specs=string.join(["\\tempo", duration, "=", perminute])
+ else:
+ sys.stderr.write("abc2ly: Warning, unable to parse Q specification: %s\n" % a)
+
def dump_score (outf):
outf.write (r"""\score{
\notes <
outf.write ("\t\t\\StaffContext\n")
# outf.write ("\t\t\\consists Staff_margin_engraver\n")
outf.write ("\t }\n")
- outf.write ("\t}\n\t\\midi {}\n}\n")
+ outf.write ("\t}\n\t\\midi {%s}\n}\n" % midi_specs)
key_count = flat_key_seq.index (keytup)
accseq = map (lambda x: (3*x + 3 ) % 7, range (1, key_count + 1))
else:
+ error ("Huh?")
raise "Huh"
key_table = [0] * 7
if re.match ('\([2-9]', str):
dig = str[1]
str = str[2:]
- state.parsing_tuplet = string.atoi (dig[0])
-
+ prev_tuplet_state = state.parsing_tuplet
+ state.parsing_tuplet = string.atoi (dig[0])
+ if prev_tuplet_state:
+ voices_append ("}")
voices_append ("\\times %s {" % tup_lookup[dig])
return str
a = re.sub('[ \t]*$','', a) #strip trailing blanks
if header.has_key('title'):
if a:
- header['title'] = header['title'] + '\\\\\\\\' + a
+ if len(header['title']):
+ header['title'] = header['title'] + '\\\\\\\\' + a
+ else:
+ header['subtitle'] = a
else:
header['title'] = a
if g == 'M': # Meter
set_default_len_from_time_sig (a)
else:
length_specified = 0
- voices_append ('\\time %s' % a)
+ if not a == 'none':
+ voices_append ('\\time %s' % a)
state.next_bar = ''
if g == 'K': # KEY
a = check_clef(a)
lyrics_append(a)
if g == 'w': # vocals
slyrics_append (a)
-
+ if g == 'Q': #tempo
+ try_parse_q (a)
return ''
return ln
if base == 1:
if (multiply_tup[0] / multiply_tup[1]) == 2:
base = '\\breve'
+ if (multiply_tup[0] / multiply_tup[1]) == 3:
+ base = '\\breve'
+ dots = 1
if (multiply_tup[0] / multiply_tup[1]) == 4:
base = '\longa'
return '%s%s' % ( base, '.'* dots)
(str, num,den,current_dots) = parse_duration (str, parser_state)
-
if re.match('[ \t]*\)', str):
str = string.lstrip (str)
str = str[1:]
- if slur_end:
- voices_append ('%s' % ')' *slur_end )
-
bar_acc = get_bar_acc(notename, octave, parser_state)
pit = pitch_to_lilypond_name(notename, acc, bar_acc, global_key[notename])
oct = octave_to_lilypond_quotes (octave)
if not parser_state.parsing_tuplet:
voices_append ("}")
if slur_begin:
- voices_append ('%s' % '(' * slur_begin )
+ voices_append ('-(' * slur_begin )
+ if slur_end:
+ voices_append ('-)' *slur_end )
+
return str
ln = junk_space (ln)
if ln:
- msg = "%s: %d: Huh? Don't understand\n" % (fn, lineno)
- sys.stderr.write (msg)
+ error ("%s: %d: Huh? Don't understand\n" % (fn, lineno))
left = orig_ln[0:-len (ln)]
sys.stderr.write (left + '\n')
sys.stderr.write (' ' * len (left) + ln + '\n')
Usage: abc2ly [OPTIONS]... ABC-FILE
Options:
- -h, --help this help
+ -h, --help print this help
-o, --output=FILE set output filename to FILE
- -v, --version version information
-
+ -v, --version show version information
+ -s, --strict be strict about succes
+
This program converts ABC music files (see
http://www.gre.ac.uk/~c.walshaw/abc2mtex/abc.txt) To LilyPond input.
+
+
+Report bugs to bug-lilypond@gnu.org
+
+Written by Han-Wen Nienhuys <hanwen@cs.uu.nl>, Laura Conrad
+<lconrad@laymusic.org>, Roy Rankin <Roy.Rankin@@alcatel.com.au>
"""
def print_version ():
-(options, files) = getopt.getopt (sys.argv[1:], 'vo:h', ['help','version', 'output='])
+(options, files) = getopt.getopt (sys.argv[1:], 'vo:hs', ['help','version', 'output=', 'strict'])
out_filename = ''
for opt in options:
if o== '--help' or o == '-h':
help ()
sys.exit (0)
- if o == '--version' or o == '-v':
+ elif o == '--version' or o == '-v':
print_version ()
sys.exit(0)
-
- if o == '--output' or o == '-o':
+ elif o == '--strict' or o == '-s':
+ strict = 1
+ elif o == '--output' or o == '-o':
out_filename = a
else:
print o