From: fred Date: Wed, 27 Mar 2002 02:03:51 +0000 (+0000) Subject: lilypond-1.5.19 X-Git-Tag: release/1.5.59~419 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=bca2a04d754de46a4d32c300497feccefb070824;p=lilypond.git lilypond-1.5.19 --- diff --git a/buildscripts/GNUmakefile b/buildscripts/GNUmakefile index c8f569c25b..08b617bd20 100644 --- a/buildscripts/GNUmakefile +++ b/buildscripts/GNUmakefile @@ -1,11 +1,7 @@ depth = .. -#STEPMAKE_TEMPLATES=script install install-out po STEPMAKE_TEMPLATES=script install po -INSTALLATION_FILES=$(outdir)/gettext.py $(outdir)/lilylib.py -INSTALLATION_DIR=$(datadir)/python - include $(depth)/make/stepmake.make # Should we install these? This should be handled by sysadmin or diff --git a/make/lilypond-vars.make b/make/lilypond-vars.make index 3395536e9f..be760f25ae 100644 --- a/make/lilypond-vars.make +++ b/make/lilypond-vars.make @@ -16,7 +16,7 @@ export DVIPSMAKEPK := mktexpk --destdir $(topdir)/mf/out endif export LILYPONDPREFIX:=$(depth)/ -export PYTHONPATH:=$(buildscript-dir)/$(outdir):$(PYTHONPATH) +export PYTHONPATH:=$(topdir)/python:$(PYTHONPATH) # guile load path? diff --git a/python/GNUmakefile b/python/GNUmakefile new file mode 100644 index 0000000000..5cab304d0e --- /dev/null +++ b/python/GNUmakefile @@ -0,0 +1,10 @@ +depth = .. + +INSTALLATION_FILES=$(PY_MODULES) $(OUT_PY_MODULES) $(OUT_SO_MODULES) +INSTALLATION_DIR=$(datadir)/python + +STEPMAKE_TEMPLATES=c python-module install po + +include $(depth)/make/stepmake.make + +$(outdir)/midi.lo: $(outdir)/config.h diff --git a/python/gettext.py.in b/python/gettext.py.in new file mode 100644 index 0000000000..e34cc77a2e --- /dev/null +++ b/python/gettext.py.in @@ -0,0 +1,329 @@ +"""This module allows python programs to use GNU gettext message catalogs. + +Author: James Henstridge +(This is loosely based on gettext.pl in the GNU gettext distribution) + +The best way to use it is like so: + import gettext + gettext.bindtextdomain(PACKAGE, LOCALEDIR) + gettext.textdomain(PACKAGE) + _ = gettext.gettext + print _('Hello World') + +where PACKAGE is the domain for this package, and LOCALEDIR is usually +'$prefix/share/locale' where $prefix is the install prefix. + +If you have more than one catalog to use, you can directly create catalog +objects. These objects are created as so: + import gettext + cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR) + _ = cat.gettext + print _('Hello World') + +The catalog object can also be accessed as a dictionary (ie cat['hello']). + +There are also some experimental features. You can add to the catalog, just +as you would with a normal dictionary. When you are finished, you can call +its save method, which will create a new .mo file containing all the +translations: + import gettext + cat = Catalog() + cat['Hello'] = 'konichiwa' + cat.save('./tmp.mo') + +Once you have written an internationalized program, you can create a .po file +for it with "xgettext --keyword=_ fillename ...". Then do the translation and +compile it into a .mo file, ready for use with this module. Note that you +will have to use C style strings (ie. use double quotes) for proper string +extraction. +""" +import os, string + +prefix = '/usr/local' +localedir = prefix + '/share/locale' + +def _expandLang(str): + langs = [str] + # remove charset ... + if '.' in str: + langs.append(string.split(str, '.')[0]) + # also add 2 character language code ... + if len(str) > 2: + langs.append(str[:2]) + return langs + +lang = [] +for env in 'LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG': + if os.environ.has_key(env): + lang = string.split(os.environ[env], ':') + lang = map(_expandLang, lang) + lang = reduce(lambda a, b: a + b, lang) + break +if 'C' not in lang: + lang.append('C') + +# remove duplicates +i = 0 +while i < len(lang): + j = i + 1 + while j < len(lang): + if lang[i] == lang[j]: + del lang[j] + else: + j = j + 1 + i = i + 1 +del i, j + +if os.environ.has_key('PY_XGETTEXT'): + xgettext = os.environ['PY_XGETTEXT'] +else: + xgettext = None + +del os, string + +error = 'gettext.error' + +def _lsbStrToInt(str): + return ord(str[0]) + \ + (ord(str[1]) << 8) + \ + (ord(str[2]) << 16) + \ + (ord(str[3]) << 24) +def _msbStrToInt(str): + return (ord(str[0]) << 24) + \ + (ord(str[1]) << 16) + \ + (ord(str[2]) << 8) + \ + ord(str[3]) +def _intToLsbStr(int): + return chr(int & 0xff) + \ + chr((int >> 8) & 0xff) + \ + chr((int >> 16) & 0xff) + \ + chr((int >> 24) & 0xff) + +def _getpos(levels = 0): + """Returns the position in the code where the function was called. + The function uses some knowledge about python stack frames.""" + import sys + # get access to the stack frame by generating an exception. + try: + raise RuntimeError + except RuntimeError: + frame = sys.exc_traceback.tb_frame + frame = frame.f_back # caller's frame + while levels > 0: + frame = frame.f_back + levels = levels - 1 + return (frame.f_globals['__name__'], + frame.f_code.co_name, + frame.f_lineno) + +class Catalog: + def __init__(self, domain=None, localedir=localedir): + self.domain = domain + self.localedir = localedir + self.cat = {} + if not domain: return + for self.lang in lang: + if self.lang == 'C': + return + catalog = "%s//%s/LC_MESSAGES/%s.mo" % ( + localedir, self.lang, domain) + try: + f = open(catalog, "rb") + buffer = f.read() + del f + break + except IOError: + pass + else: + return # assume C locale + + strToInt = _lsbStrToInt + if strToInt(buffer[:4]) != 0x950412de: + # catalog is encoded with MSB offsets. + strToInt = _msbStrToInt + if strToInt(buffer[:4]) != 0x950412de: + # magic number doesn't match + raise error, 'Bad magic number in %s' % (catalog,) + + self.revision = strToInt(buffer[4:8]) + nstrings = strToInt(buffer[8:12]) + origTabOffset = strToInt(buffer[12:16]) + transTabOffset = strToInt(buffer[16:20]) + for i in range(nstrings): + origLength = strToInt(buffer[origTabOffset: + origTabOffset+4]) + origOffset = strToInt(buffer[origTabOffset+4: + origTabOffset+8]) + origTabOffset = origTabOffset + 8 + origStr = buffer[origOffset:origOffset+origLength] + + transLength = strToInt(buffer[transTabOffset: + transTabOffset+4]) + transOffset = strToInt(buffer[transTabOffset+4: + transTabOffset+8]) + transTabOffset = transTabOffset + 8 + transStr = buffer[transOffset:transOffset+transLength] + + self.cat[origStr] = transStr + + def gettext(self, string): + """Get the translation of a given string""" + if self.cat.has_key(string): + return self.cat[string] + else: + return string + # allow catalog access as cat(str) and cat[str] and cat.gettext(str) + __getitem__ = gettext + __call__ = gettext + + # this is experimental code for producing mo files from Catalog objects + def __setitem__(self, string, trans): + """Set the translation of a given string""" + self.cat[string] = trans + def save(self, file): + """Create a .mo file from a Catalog object""" + try: + f = open(file, "wb") + except IOError: + raise error, "can't open " + file + " for writing" + f.write(_intToLsbStr(0x950412de)) # magic number + f.write(_intToLsbStr(0)) # revision + f.write(_intToLsbStr(len(self.cat))) # nstrings + + oIndex = []; oData = '' + tIndex = []; tData = '' + for orig, trans in self.cat.items(): + oIndex.append((len(orig), len(oData))) + oData = oData + orig + '\0' + tIndex.append((len(trans), len(tData))) + tData = tData + trans + '\0' + oIndexOfs = 20 + tIndexOfs = oIndexOfs + 8 * len(oIndex) + oDataOfs = tIndexOfs + 8 * len(tIndex) + tDataOfs = oDataOfs + len(oData) + f.write(_intToLsbStr(oIndexOfs)) + f.write(_intToLsbStr(tIndexOfs)) + for length, offset in oIndex: + f.write(_intToLsbStr(length)) + f.write(_intToLsbStr(offset + oDataOfs)) + for length, offset in tIndex: + f.write(_intToLsbStr(length)) + f.write(_intToLsbStr(offset + tDataOfs)) + f.write(oData) + f.write(tData) + +_cat = None +_cats = {} + +if xgettext: + class Catalog: + def __init__(self, domain, localedir): + self.domain = domain + self.localedir = localedir + self._strings = {} + def gettext(self, string): + # there is always one level of redirection for calls + # to this function + pos = _getpos(2) # get this function's caller + if self._strings.has_key(string): + if pos not in self._strings[string]: + self._strings[string].append(pos) + else: + self._strings[string] = [pos] + return string + __getitem__ = gettext + __call__ = gettext + def __setitem__(self, item, data): + pass + def save(self, file): + pass + def output(self, fp): + import string + fp.write('# POT file for domain %s\n' % (self.domain,)) + for str in self._strings.keys(): + pos = map(lambda x: "%s(%s):%d" % x, + self._strings[str]) + pos.sort() + length = 80 + for p in pos: + if length + len(p) > 74: + fp.write('\n#:') + length = 2 + fp.write(' ') + fp.write(p) + length = length + 1 + len(p) + fp.write('\n') + if '\n' in str: + fp.write('msgid ""\n') + lines = string.split(str, '\n') + lines = map(lambda x: + '"%s\\n"\n' % (x,), + lines[:-1]) + \ + ['"%s"\n' % (lines[-1],)] + fp.writelines(lines) + else: + fp.write('msgid "%s"\n' % (str,)) + fp.write('msgstr ""\n') + + import sys + if hasattr(sys, 'exitfunc'): + _exitchain = sys.exitfunc + else: + _exitchain = None + def exitfunc(dir=xgettext, _exitchain=_exitchain): + # actually output all the .pot files. + import os + for file in _cats.keys(): + fp = open(os.path.join(dir, file + '.pot'), 'w') + cat = _cats[file] + cat.output(fp) + fp.close() + if _exitchain: _exitchain() + sys.exitfunc = exitfunc + del sys, exitfunc, _exitchain, xgettext + +def bindtextdomain(domain, localedir=localedir): + global _cat + if not _cats.has_key(domain): + _cats[domain] = Catalog(domain, localedir) + if not _cat: _cat = _cats[domain] + +def textdomain(domain): + global _cat + if not _cats.has_key(domain): + _cats[domain] = Catalog(domain) + _cat = _cats[domain] + +def gettext(string): + if _cat == None: raise error, "No catalog loaded" + return _cat.gettext(string) + +_ = gettext + +def dgettext(domain, string): + if domain is None: + return gettext(string) + if not _cats.has_key(domain): + raise error, "Domain '" + domain + "' not loaded" + return _cats[domain].gettext(string) + +def test(): + import sys + global localedir + if len(sys.argv) not in (2, 3): + print "Usage: %s DOMAIN [LOCALEDIR]" % (sys.argv[0],) + sys.exit(1) + domain = sys.argv[1] + if len(sys.argv) == 3: + bindtextdomain(domain, sys.argv[2]) + textdomain(domain) + info = gettext('') # this is where special info is often stored + if info: + print "Info for domain %s, lang %s." % (domain, _cat.lang) + print info + else: + print "No info given in mo file." + +if __name__ == '__main__': + test() + diff --git a/python/lilylib.py.in b/python/lilylib.py.in new file mode 100644 index 0000000000..1da987020c --- /dev/null +++ b/python/lilylib.py.in @@ -0,0 +1,176 @@ +# lilylib.py -- options and stuff +# +# source file of the GNU LilyPond music typesetter + +import os +from __main__ import * +try: + import gettext + gettext.bindtextdomain ('lilypond', localedir) + gettext.textdomain ('lilypond') + _ = gettext.gettext +except: + def _ (s): + return s + +if program_version == '@' + 'TOPLEVEL_VERSION' + '@': + program_version = '1.5.17' + +def identify (): + sys.stdout.write ('%s (GNU LilyPond) %s\n' % (program_name, program_version)) + +def warranty (): + identify () + sys.stdout.write ('\n') + sys.stdout.write (_ ('Copyright (c) %s by' % ' 2001')) + sys.stdout.write ('\n') + sys.stdout.write (' Han-Wen Nienhuys') + sys.stdout.write (' Jan Nieuwenhuizen') + sys.stdout.write ('\n') + sys.stdout.write (_ (r''' +Distributed under terms of the GNU General Public License. It comes with +NO WARRANTY.''')) + sys.stdout.write ('\n') + +def progress (s): + errorport.write (s + '\n') + +def warning (s): + progress (_ ("warning: ") + s) + +def error (s): + + + '''Report the error S. Exit by raising an exception. Please + do not abuse by trying to catch this error. If you do not want + a stack trace, write to the output directly. + + RETURN VALUE + + None + + ''' + + progress (_ ("error: ") + s) + raise _ ("Exiting ... ") + +def getopt_args (opts): + '''Construct arguments (LONG, SHORT) for getopt from list of options.''' + short = '' + long = [] + for o in opts: + if o[1]: + short = short + o[1] + if o[0]: + short = short + ':' + if o[2]: + l = o[2] + if o[0]: + l = l + '=' + long.append (l) + return (short, long) + +def option_help_str (o): + '''Transform one option description (4-tuple ) into neatly formatted string''' + sh = ' ' + if o[1]: + sh = '-%s' % o[1] + + sep = ' ' + if o[1] and o[2]: + sep = ',' + + long = '' + if o[2]: + long= '--%s' % o[2] + + arg = '' + if o[0]: + if o[2]: + arg = '=' + arg = arg + o[0] + return ' ' + sh + sep + long + arg + + +def options_help_str (opts): + '''Convert a list of options into a neatly formatted string''' + w = 0 + strs =[] + helps = [] + + for o in opts: + s = option_help_str (o) + strs.append ((s, o[3])) + if len (s) > w: + w = len (s) + + str = '' + for s in strs: + str = str + '%s%s%s\n' % (s[0], ' ' * (w - len(s[0]) + 3), s[1]) + return str + +def help (): + ls = [(_ ("Usage: %s [OPTION]... FILE") % program_name), + ('\n\n'), + (help_summary), + ('\n\n'), + (_ ("Options:")), + ('\n'), + (options_help_str (option_definitions)), + ('\n\n'), + (_ ("Report bugs to %s") % 'bug-lilypond@gnu.org'), + ('\n')] + map (sys.stdout.write, ls) + +def setup_temp (): + """ + Create a temporary directory, and return its name. + """ + global temp_dir + if not keep_temp_dir_p: + temp_dir = tempfile.mktemp (program_name) + try: + os.mkdir (temp_dir, 0777) + except OSError: + pass + + return temp_dir + + +def system (cmd, ignore_error = 0): + """Run CMD. If IGNORE_ERROR is set, don't complain when CMD returns non zero. + + RETURN VALUE + + Exit status of CMD + """ + + if verbose_p: + progress (_ ("Invoking `%s\'") % cmd) + st = os.system (cmd) + if st: + name = re.match ('[ \t]*([^ \t]*)', cmd).group (1) + msg = name + ': ' + _ ("command exited with value %d") % st + if ignore_error: + warning (msg + ' ' + _ ("(ignored)") + ' ') + else: + error (msg) + + return st + + +def cleanup_temp (): + if not keep_temp_dir_p: + if verbose_p: + progress (_ ("Cleaning %s...") % temp_dir) + shutil.rmtree (temp_dir) + + +def strip_extension (f, ext): + (p, e) = os.path.splitext (f) + if e == ext: + e = '' + return p + e + +# END Library + diff --git a/python/midi.c b/python/midi.c new file mode 100644 index 0000000000..a5fab33c30 --- /dev/null +++ b/python/midi.c @@ -0,0 +1,427 @@ +/* + midi.c -- implement Python midi parser module + + source file of the GNU LilyPond music typesetter + + (c) 2001 Han-Wen Nienhuys + Jan Nieuwenhuizen + +*/ + +/* + +python2 +import midi +s = open ("s.midi").read () +midi.parse_track (s) +midi.parse (s) + +*/ + +#include "config.h" + +/* urg */ +#if HAVE_PYTHON2_PYTHON_H +#include +#elif HAVE_PYTHON2_1_PYTHON_H +#include +#elif HAVE_PYTHON2_0_PYTHON_H +#include +#elif HAVE_PYTHON1_5_PYTHON_H +#include +#elif HAVE_PYTHON_PYTHON_H +#define assert(x) +#include +#elif HAVE_PYTHON_H +#define assert(x) +#include +#else +#error Need Python.h +#endif + +#if 0 +int x = 0; +int *track = &x; +#define debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p :" f, __FUNCTION__, __LINE__, *track, ##args) +#else +#define debug_print(f, args...) +#endif + +static PyObject *Midi_error; +static PyObject *Midi_warning; + +static PyObject * +midi_error (char *s) +{ + PyErr_SetString (Midi_error, s); + return 0; +} + +static PyObject * +midi_warning (char *s) +{ + PyErr_SetString (Midi_warning, s); + return 0; +} + + +typedef struct message { + unsigned char msg; + char * description; +} message_t; + +message_t channelVoiceMessages[] = { + 0x80, "NOTE_OFF", + 0x90, "NOTE_ON", + 0xA0, "POLYPHONIC_KEY_PRESSURE", + 0xB0, "CONTROLLER_CHANGE", + 0xC0, "PROGRAM_CHANGE", + 0xD0, "CHANNEL_KEY_PRESSURE", + 0xE0, "PITCH_BEND", + 0,0 +}; + +message_t channelModeMessages[] = { + 0x78, "ALL_SOUND_OFF", + 0x79, "RESET_ALL_CONTROLLERS", + 0x7A, "LOCAL_CONTROL", + 0x7B, "ALL_NOTES_OFF", + 0x7C, "OMNI_MODE_OFF", + 0x7D, "OMNI_MODE_ON", + 0x7E, "MONO_MODE_ON", + 0x7F, "POLY_MODE_ON", + 0,0 +}; + +message_t metaEvents[] = { + 0x00, "SEQUENCE_NUMBER", + 0x01, "TEXT_EVENT", + 0x02, "COPYRIGHT_NOTICE", + 0x03, "SEQUENCE_TRACK_NAME", + 0x04, "INSTRUMENT_NAME", + 0x05, "LYRIC", + 0x06, "MARKER", + 0x07, "CUE_POINT", + 0x20, "MIDI_CHANNEL_PREFIX", + 0x21, "MIDI_PORT", + 0x2F, "END_OF_TRACK", + 0x51, "SET_TEMPO", + 0x54, "SMTPE_OFFSET", + 0x58, "TIME_SIGNATURE", + 0x59, "KEY_SIGNATURE", + 0x7F, "SEQUENCER_SPECIFIC_META_EVENT", + 0xFF, "META_EVENT", + 0,0 +}; + +void +add_constants (PyObject *dict) +{ + message_t * p[] = {metaEvents, channelModeMessages, channelVoiceMessages ,0}; + int i,j; + for ( j =0; p[j]; j++) + for ( i = 0; p[j][i].description; i++) + PyDict_SetItemString (dict, p[j][i].description, Py_BuildValue ("i", p[j][i].msg)); +} + +unsigned long int +get_number (unsigned char ** str, unsigned char * end_str, int length) +{ + /* # MIDI uses big-endian for everything */ + long sum = 0; + int i = 0; + + for (; i < length; i++) + sum = (sum << 8) + (unsigned char) (*str)[i]; + + *str += length; + debug_print ("%d:\n", sum); + return sum; +} + +unsigned long int +get_variable_length_number (unsigned char **str, unsigned char * end_str) +{ + long sum = 0; + int i = 0; + while (*str < end_str) + { + unsigned char x = **str; + (*str) ++; + sum = (sum << 7) + (x & 0x7F); + if (!(x & 0x80)) + break; + } + debug_print ("%d:\n", sum); + return sum; +} + +PyObject * +read_one_byte (unsigned char **track, unsigned char *end, + unsigned char x) +{ + PyObject *pyev = Py_BuildValue ("(i)", x); + debug_print ("%x:%s", x, "event\n"); + + return pyev; +} + +PyObject * +read_two_bytes (unsigned char **track, unsigned char *end, + unsigned char x) +{ + PyObject *pyev = Py_BuildValue ("(ii)", x, (*track)[0]); + *track += 1; + debug_print ("%x:%s", x, "event\n"); + return pyev; +} + +PyObject * +read_three_bytes (unsigned char **track, unsigned char *end, + unsigned char x) +{ + PyObject *pyev = Py_BuildValue ("(iii)", x, (*track)[0], + (*track)[1]); + + *track += 2; + debug_print ("%x:%s", x, "event\n"); + return pyev; +} + +PyObject * +read_string (unsigned char **track, unsigned char *end) +{ + unsigned long length = get_variable_length_number (track, end); + if (length > end - *track) + length = end - *track; + + *track += length; + return Py_BuildValue ("s#", ((*track) -length), length); +} + +typedef PyObject* (*Read_midi_event) + (unsigned char **track, unsigned char *end, + unsigned char x); + + +static PyObject * +read_f0_byte (unsigned char **track, unsigned char *end, + unsigned char x) + +{ + debug_print ("%x:%s", x, "event\n"); + if (x == 0xff) + { + unsigned char z = (*track)[0 ]; + *track += 1; + debug_print ("%x:%s", z, "f0-event\n"); + + return Py_BuildValue ("(iiO)", x, z, read_string (track, end)); + } + + return Py_BuildValue ("(iO)", x, read_string (track, end)); +} + +Read_midi_event read_midi_event [16] = +{ + read_one_byte, // 0 + read_one_byte, // 10 + read_one_byte, // 20 + read_one_byte, // 30 + read_one_byte, // 40 + read_one_byte, // 50 + read_one_byte, // 60 data entry. + read_two_bytes, // 70 all notes off + read_three_bytes, // 80 note off + read_three_bytes, // 90 note on + read_three_bytes, // a0 poly aftertouch + read_three_bytes, // b0 control + read_two_bytes, // c0 prog change + read_two_bytes, // d0 ch aftertouch + read_three_bytes, // e0 pitchwheel range + read_f0_byte, // f0 +}; + + +static PyObject * +read_event (unsigned char **track, unsigned char *end, PyObject *time, + unsigned char *running_status) +{ + int rsb_skip = ((**track & 0x80)) ? 1 :0; + + unsigned char x = (rsb_skip) ? (*track)[0]: *running_status; + + PyObject * bare_event = 0; + debug_print ("%x:%s", x, "event\n"); + *running_status = x; + *track += rsb_skip; + + // printf ("%x %x %d next %x\n", x, (*track)[0], rsb_skip, (*track)[1]); + bare_event = (*read_midi_event[x >> 4]) (track, end, x); + if (bare_event) + return Py_BuildValue ("(OO)", time, bare_event); + else + return NULL; +} + +static PyObject * +midi_parse_track (unsigned char **track, unsigned char *track_end) +{ + unsigned int time = 0; + unsigned char running_status; + unsigned long track_len, track_size; + PyObject *pytrack = 0; + + debug_print ("%s", "\n"); + + track_size = track_end - *track; + + debug_print ("%s", "\n"); + if (strcmp (*track, "MTrk")) + return midi_error (__FUNCTION__ ": MTrk expected"); + + *track += 4; + + track_len = get_number (track, *track + 4, 4); + + + debug_print ("track_len: %u\n", track_len); + debug_print ("track_size: %u\n", track_size); + debug_print ("track begin: %p\n", track); + debug_print ("track end: %p\n", track + track_len); + + if (track_len > track_size) + return midi_error (__FUNCTION__ ": track size corrupt"); + + pytrack = PyList_New (0); + + track_end = *track + track_len; + + { + PyObject *pytime = PyInt_FromLong (0L); + while (*track < track_end) + { + long dt = get_variable_length_number(track, track_end); + PyObject *pyev = 0; + + time += dt; + if (dt) + pytime = PyInt_FromLong (time); + + pyev = read_event (track, track_end, pytime, + &running_status); + if (pyev) + PyList_Append (pytrack, pyev); + } + } + + *track = track_end; + return pytrack; +} + + +static PyObject * +pymidi_parse_track (PyObject *self, PyObject *args) +{ + unsigned char *track, *track_end; + unsigned long track_size, track_len; + + PyObject * sobj = PyTuple_GetItem (args, 0); + + debug_print ("%s", "\n"); + if (!PyArg_ParseTuple (args, "s#", &track, &track_size)) + return 0; + + if (track_size < 0) + return midi_error (__FUNCTION__ ": negative track size"); + + track_end = track + track_size; + + return midi_parse_track (&track, track_end); +} + +static PyObject * +midi_parse (unsigned char **midi,unsigned char *midi_end) +{ + PyObject *pymidi = 0; + unsigned long header_len; + unsigned format, tracks; + int division; + int i; + + debug_print ("%s", "\n"); + + /* Header */ + header_len = get_number (midi, *midi + 4, 4); + + + if (header_len < 6) + return midi_error (__FUNCTION__ ": header too short"); + + format = get_number (midi, *midi + 2, 2); + tracks = get_number (midi, *midi + 2, 2); + + if (tracks > 32) + return midi_error (__FUNCTION__ ": too many tracks"); + + division = get_number (midi, *midi + 2, 2) * 4; + + + if (division < 0) + /* return midi_error ("can't handle non-metrical time"); */ + ; + *midi += header_len - 6; + + pymidi = PyList_New (0); + + /* Tracks */ + for (i = 0; i < tracks; i++) + PyList_Append (pymidi, midi_parse_track (midi, midi_end)); + + pymidi = Py_BuildValue ("(OO)", Py_BuildValue ("(ii)", format, division), + pymidi); + return pymidi; +} + +static PyObject * +pymidi_parse (PyObject *self, PyObject *args) +{ + unsigned char *midi, *midi_end; + unsigned long midi_size, midi_len; + + PyObject *sobj = PyTuple_GetItem (args, 0); + + debug_print ("%s", "\n"); + if (!PyArg_ParseTuple (args, "s#", &midi, &midi_size)) + return 0; + + if (strcmp (midi, "MThd")) + return midi_error (__FUNCTION__ ": MThd expected"); + + midi += 4; + + midi_end = midi + midi_size; + + return midi_parse (&midi, midi_end); +} + + +static PyMethodDef MidiMethods[] = +{ + {"parse", pymidi_parse, 1}, + {"parse_track", pymidi_parse_track, 1}, + {0, 0} /* Sentinel */ +}; + +initmidi () +{ + PyObject *m, *d; + m = Py_InitModule ("midi", MidiMethods); + d = PyModule_GetDict (m); + + Midi_error = PyString_FromString ("midi.error"); + PyDict_SetItemString (d, "error", Midi_error); + add_constants (d); + Midi_warning = PyString_FromString ("midi.warning"); + PyDict_SetItemString (d, "warning", Midi_warning); +} diff --git a/scripts/GNUmakefile b/scripts/GNUmakefile index 1df3d26a3b..1039423e47 100644 --- a/scripts/GNUmakefile +++ b/scripts/GNUmakefile @@ -2,6 +2,7 @@ depth = .. SEXECUTABLES=convert-ly lilypond-book ly2dvi abc2ly as2text etf2ly musedata2ly pmx2ly mup2ly midi2ly STEPMAKE_TEMPLATES=script help2man po +LOCALSTEPMAKE_TEMPLATES = lilypond HELP2MAN_EXECS = $(SEXECUTABLES) include $(depth)/make/stepmake.make diff --git a/scripts/mup2ly.py b/scripts/mup2ly.py index f7b7da1eff..81279de3f8 100644 --- a/scripts/mup2ly.py +++ b/scripts/mup2ly.py @@ -34,9 +34,26 @@ import __main__ import operator import tempfile -sys.path.append ('@datadir@/python') -sys.path.append ('@datadir@/buildscripts/out') -sys.path.append ('@datadir@/modules/out') + +# if set, LILYPONDPREFIX must take prevalence +# if datadir is not set, we're doing a build and LILYPONDPREFIX +datadir = '@datadir@' +if os.environ.has_key ('LILYPONDPREFIX') \ + or '@datadir@' == '@' + 'datadir' + '@': + datadir = os.environ['LILYPONDPREFIX'] +else: + datadir = '@datadir@' + +sys.path.append (os.path.join (datadir, 'python')) +sys.path.append (os.path.join (datadir, 'python/out')) + +program_name = 'ly2dvi' +program_version = '@TOPLEVEL_VERSION@' +original_dir = os.getcwd () +temp_dir = os.path.join (original_dir, '%s.dir' % program_name) +errorport = sys.stderr +keep_temp_dir_p = 0 +verbose_p = 0 try: import gettext @@ -47,17 +64,8 @@ except: def _ (s): return s -# Attempt to fix problems with limited stack size set by Python! -# Sets unlimited stack size. Note that the resource module only -# is available on UNIX. -try: - import resource - resource.setrlimit (resource.RLIMIT_STACK, (-1, -1)) -except: - pass program_name = 'mup2ly' -package_name = 'lilypond' help_summary = _ ("Convert mup to LilyPond source") option_definitions = [ diff --git a/scripts/update-lily.py b/scripts/update-lily.py index e60de66dba..76d9068fe5 100644 --- a/scripts/update-lily.py +++ b/scripts/update-lily.py @@ -32,15 +32,38 @@ import sys import __main__ +# if set, LILYPONDPREFIX must take prevalence +# if datadir is not set, we're doing a build and LILYPONDPREFIX +datadir = '@datadir@' +if os.environ.has_key ('LILYPONDPREFIX') \ + or '@datadir@' == '@' + 'datadir' + '@': + datadir = os.environ['LILYPONDPREFIX'] +else: + datadir = '@datadir@' + +sys.path.append (os.path.join (datadir, 'python')) +sys.path.append (os.path.join (datadir, 'python/out')) + +program_name = 'build-lily' +program_version = '@TOPLEVEL_VERSION@' + +original_dir = os.getcwd () +temp_dir = os.path.join (original_dir, '%s.dir' % program_name) +errorport = sys.stderr +keep_temp_dir_p = 0 +verbose_p = 0 +remove_previous_p = 0 + url = 'file:/home/ftp/pub/gnu/LilyPond/development/lilypond-*.tar.gz' url = 'ftp://appel.lilypond.org/pub/gnu/LilyPond/development/lilypond-*.tar.gz' url = 'ftp://ftp.cs.uu.nl/pub/GNU/LilyPond/development/lilypond-*.tar.gz' -remove_previous_p = 0 + +build_root = os.path.join (os.environ ['HOME'], 'usr', 'src') +release_dir = build_root + '/releases' +patch_dir = build_root + '/patches' -sys.path.append ('@datadir@/python') -sys.path.append ('@datadir@/buildscripts/out') try: import gettext @@ -61,17 +84,8 @@ except: pass -program_name = 'build-lily' -package_name = 'lilypond' help_summary = _ ("Fetch and rebuild from latest source package") -build_root = os.path.join (os.environ ['HOME'], 'usr', 'src') -release_dir = build_root + '/releases' -patch_dir = build_root + '/patches' -original_dir = os.getcwd () -temp_dir = os.path.join (original_dir, '%s.dir' % program_name) - - option_definitions = [ ('DIR', 'b', 'build-root', _ ("unpack and build in DIR [%s]") % build_root), ('COMMAND', 'c', 'command', _ ("execute COMMAND, subtitute:") \ diff --git a/stepmake/stepmake/python-module-rules.make b/stepmake/stepmake/python-module-rules.make index b37eb61110..e8087596eb 100644 --- a/stepmake/stepmake/python-module-rules.make +++ b/stepmake/stepmake/python-module-rules.make @@ -1,3 +1,3 @@ -$(PYTHON_MODULE): $(outdir)/config.h $(LO_FILES) - $(LD) $(SHARED_FLAGS) -o $@ $(LO_FILES) $(LDFLAGS) +$(outdir)/%$(SHARED_LIB_SUFFIX): $(outdir)/%.lo + $(LD) $(SHARED_FLAGS) -o $@ $< $(LDFLAGS) diff --git a/stepmake/stepmake/python-module-targets.make b/stepmake/stepmake/python-module-targets.make index 6d4f607785..8b47ce0a46 100644 --- a/stepmake/stepmake/python-module-targets.make +++ b/stepmake/stepmake/python-module-targets.make @@ -1 +1 @@ -default: $(PYTHON_MODULE) \ No newline at end of file +default: $(OUT_PY_MODULES) $(OUT_SO_MODULES) \ No newline at end of file diff --git a/stepmake/stepmake/python-module-vars.make b/stepmake/stepmake/python-module-vars.make index 372264046c..59eb76153d 100644 --- a/stepmake/stepmake/python-module-vars.make +++ b/stepmake/stepmake/python-module-vars.make @@ -1,7 +1,6 @@ +PY_MODULES = $(wildcard *.py) +PY_IN_FILES = $(wildcard *.py.in) +OUT_PY_MODULES = $($(addprefix $(outdir)/, $(PY_IN_FILES:.in=) SHARED_LIB_SUFFIX = .so - -PYTHON_MODULE = $(outdir)/$(NAME)$(SHARED_LIB_SUFFIX) -INSTALL_SHARED_LIBRARY = $(SHARED_LIB_PREFIX)$(NAME)$(SHARED_LIB_SUFFIX) - -LO_FILES += $(addprefix $(outdir)/, $(Y_FILES:.y=.lo) $(C_FILES:.c=.lo) $(L_FILES:.l=.lo)) +OUT_SO_MODULES = $(addprefix $(outdir)/, $(C_FILES:.c=$(SHARED_LIB_SUFFIX)))