Attachment 'AbcMusic.py'

Download

   1 """
   2     MoinMoin - Processor for abc format music syntax using abc2ps
   3 
   4     Copyright (c) 2004 by Nathan Whitehead <nwhitehe@cs.ucsc.edu>
   5     All rights reserved, see COPYING for details.
   6 """
   7 
   8 import string, sys, os, re, sha
   9 from MoinMoin import config
  10 
  11 # Set these according to local environment
  12 config_cache_dir='/cse/grads/nwhitehe/.html/wiki/abcps'
  13 config_cache_url=config.url_prefix+'abcps'
  14 config_tmp_dir='/tmp'
  15 config_external_abc2ps='/cse/grads/nwhitehe/bin/abcm2ps'
  16 config_external_pstopnm='/usr/local/bin/pstopnm'
  17 config_external_gs='/usr/local/gnu/bin/gs'
  18 config_external_pnmcat='/usr/local/bin/pnmcat'
  19 config_external_pnmcrop='/usr/local/bin/pnmcrop'
  20 config_external_abc2midi='/cse/grads/nwhitehe/bin/abc2midi'
  21 
  22 # Use png or gif?
  23 config_use_gif=1
  24 config_external_rasterize='/usr/local/bin/ppmtogif'
  25 config_external_gzip='/usr/local/gnu/bin/gzip'
  26 config_score_orientation='-tb' # or -lr for horizontal
  27 # Serve and store scores gzipped to save space?
  28 config_zip_scores=0
  29 
  30 # Cut off hash to this many characters for user friendliness
  31 hash_length = 6
  32 # Show code in HTML page by default?
  33 show_code = 1
  34 # Generate PNG graphics of each page? (slow and memory intensive for server)
  35 show_score = 1
  36 # Show an embedded MIDI controller for playing the song?
  37 show_midi = 1
  38 # Syntax highlighting colors for ABC code
  39 header_color = '#6000a0'
  40 info_color = '#006000'
  41 note_color = '#000000'
  42 bar_color = '#ff0000'
  43 continues_color = '#ff00ff'
  44 comment_color = '#ff5050'
  45 chord_color = '#808080'
  46 
  47 def quote_apply(f, txt):
  48     """Apply a given function on text to all quotations in a string"""
  49     # This is harder than it sounds because replacement text may have quotes
  50     qi = txt.find('"')
  51     while not qi == -1:
  52         qi2 = txt.find('"', qi + 1)
  53         if not qi2 == -1:
  54             newtext = f(txt[qi:qi2 + 1])
  55             txt = txt[:qi] + newtext + txt[qi2 + 1:]
  56             lenincr = len(newtext) - (qi2 - qi)
  57             qi = txt.find('"', qi2 + lenincr)
  58         else:
  59             qi = -1
  60     return txt
  61 
  62 def color_txt(c, txt):
  63     """Make text appear the given ascii color"""
  64     return '<font color="' + c + '">' + txt + '</font>'
  65 
  66 def colorize_line(txt):
  67     # If it is header, color it and we're done
  68     if len(txt) >= 2 and txt[1] == ':':
  69         return color_txt(header_color, txt[:2]) + color_txt(info_color, txt[2:])
  70     # If it is comment, color and we're done
  71     if len(txt) >= 1 and txt[0] == '%':
  72         return color_txt(comment_color, txt)
  73     # Color quotations (chords) first, otherwise
  74     # we will get more quotes from font tags later.
  75     def give_chord_color(txt):
  76         return color_txt(chord_color, txt)
  77     txt = quote_apply(give_chord_color, txt)
  78     txt = txt.replace('|', color_txt(bar_color, '|'))
  79     txt = txt.replace('\\', color_txt(continues_color, '\\'))
  80     return color_txt(note_color, txt)
  81 
  82 def colorize(lines):
  83     """Do rudimentary syntax highlighting of ABC music in HTML"""
  84     # Do it line by line
  85     clines = map(colorize_line, lines)
  86     return string.join(clines, '\n')
  87 
  88 def get_title(lines):
  89     """Return the title string, if it exists"""
  90     for l in lines:
  91         if len(l) >= 2 and l[0] == 'T' and l[1] == ':':
  92             return l[2:]
  93     return "(Untitled)"
  94 
  95 def cleanup(txt):
  96     """Scrub a title so it may be used in a filename"""
  97     # Old way, txt.replace(' ', '_').replace('(', '').replace(')', '')
  98     res = ""
  99     for x in txt:
 100         if x.isalnum():
 101             res = res + x
 102         if x == ' ':
 103             res = res + '_'
 104     return res
 105 
 106 def process_arguments(lines):
 107     global show_code
 108     global show_score
 109     if len(lines) > 0:
 110         stripline0 = string.strip(lines[0])
 111         if stripline0 == "#!AbcMusic":
 112             del lines[0]
 113             process_arguments(lines)
 114         if stripline0 == "#show-code-off":
 115             del lines[0]
 116             show_code = 0
 117             process_arguments(lines)
 118         if stripline0 == "#show-code-on":
 119             del lines[0]
 120             show_code = 1
 121             process_arguments(lines)
 122         if stripline0 == "#show-score-off":
 123             del lines[0]
 124             show_score = 0
 125             process_arguments(lines)
 126         if stripline0 == "#show-score-on":
 127             del lines[0]
 128             show_score = 1
 129             process_arguments(lines)
 130     return
 131 
 132 def process(request, formatter, lines):
 133     global show_code
 134     # Preprocessing stage
 135     process_arguments(lines)
 136     title = get_title(lines)
 137     texstr = string.join(lines, '\n')
 138     texstr = string.strip(texstr)
 139     hash = sha.new(texstr).hexdigest()[:hash_length]
 140     name = cleanup(title) + '_' + hash
 141 
 142     filepath = "%s/%s" % (config_cache_dir, name)
 143     urlpath = "%s/%s" % (config_cache_url, name)
 144 
 145     if config_use_gif:
 146         suffix = ".gif"
 147     else:
 148         suffix = ".png"
 149     abcpath = filepath + ".abc"
 150     pspath = filepath + ".ps"
 151     psgzpath = filepath + ".ps.gz"
 152     pngpath = filepath + suffix
 153     logpath = filepath + ".log"
 154     midipath = filepath + ".mid"
 155     abcurl = urlpath + ".abc"
 156     if config_zip_scores:
 157         psurl = urlpath + ".ps.gz"
 158     else:
 159         psurl = urlpath + ".ps"
 160     pngurl = urlpath + suffix
 161     logurl = urlpath + ".log"
 162     midiurl = urlpath + ".mid"
 163 
 164     # Delete logfile
 165     os.system("rm -f %s" % logpath)
 166 
 167     # Generate PS
 168     if not os.path.exists(pspath):
 169         data = open(abcpath, "w")
 170         data.write('%s' % texstr)
 171         data.close()
 172         
 173         options = "-e 1"
 174         cmd = "cd %(workingdir)s ; %(abc2ps)s %(options)s -O %(outfile)s %(infile)s >> %(logfile)s 2>&1" % {
 175             "workingdir" : config_tmp_dir,
 176             "abc2ps": config_external_abc2ps,
 177             "options": options,
 178             "outfile" : pspath,
 179             "infile": abcpath,
 180             "logfile": logpath
 181             }
 182         os.system(cmd)
 183         os.system("chmod 644 " + pspath)
 184         os.system("chmod 644 " + abcpath)
 185         if config_zip_scores:
 186             cmd = "%(gzip)s %(file)s 2> /dev/null" % {
 187                 "gzip" : config_external_gzip,
 188                 "file" : pspath
 189                 }
 190             os.system(cmd)
 191             os.system("chmod 644 " + psgzpath)
 192         os.system("chmod 644 " + logpath)
 193 
 194     # Generate PNG
 195     if (not os.path.exists(pngpath)) and show_score:
 196         # delete any old stuff
 197         cmd = 'rm -f %s/%s*.ppm' % (config_tmp_dir, name)
 198         os.system(cmd)
 199 
 200         # Use ghostscript to convert ps to pnm files
 201         options = "-dNOPAUSE -q -dBATCH -sPAPERSIZE=letter -sDEVICE=ppmraw -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r120x120 -sOutputFile=%s%%003d.ppm" % name
 202         cmd = 'cd %(workingdir)s ; %(gs)s %(options)s %(infile)s > /dev/null 2>&1' % {
 203             "workingdir" : config_tmp_dir,
 204             "gs" : config_external_gs,
 205             "options" : options,
 206             "infile" : pspath
 207             }
 208         os.system(cmd)
 209         
 210         # Concatenate pnm files into one file
 211         cmd = 'cd %(workingdir)s ; %(pnmcat)s %(orientation)s %(name)s*.ppm 2> /dev/null | %(pnmcrop)s 2> /dev/null | %(rasterize)s > %(outfile)s 2> /dev/null' % {
 212             "workingdir" : config_tmp_dir,
 213             "pnmcat" : config_external_pnmcat,
 214             "orientation" : config_score_orientation,
 215             "name" : name,
 216             "pnmcrop" : config_external_pnmcrop,
 217             "rasterize" : config_external_rasterize,
 218             "outfile" : pngpath
 219             }
 220         os.system(cmd)
 221         os.system("chmod 644 " + pngpath)
 222 
 223     # Generate MIDI file
 224     if not os.path.exists(midipath):
 225         data = open(abcpath, "w")
 226         data.write('%s' % texstr)
 227         data.close()
 228         
 229         options = ""
 230         cmd = "cd %(workingdir)s ; %(abc2midi)s %(infile)s %(options)s -o %(outfile)s >> %(logfile)s 2>&1" % {
 231             "workingdir" : config_tmp_dir,
 232             "abc2midi": config_external_abc2midi,
 233             "options": options,
 234             "outfile" : midipath,
 235             "infile": abcpath,
 236             "logfile": logpath
 237             }
 238         os.system(cmd)
 239         os.system("chmod 644 " + midipath)
 240         os.system("chmod 644 " + abcpath)
 241         os.system("chmod 644 " + logpath)
 242 
 243     
 244 
 245     # Clean up junk (unzipped score if using zipped scores)
 246     if config_zip_scores:
 247         os.system("rm -f " + pspath)
 248 
 249     # Generate page
 250     #    if show_code or show_score:
 251     request.write(formatter.paragraph(1))
 252     request.write(formatter.table(1))
 253     
 254     request.write(formatter.table_row(1))
 255     request.write(formatter.table_cell(1))
 256     request.write(formatter.paragraph(1))
 257     request.write(formatter.strong(1))
 258     request.write(formatter.emphasis(1))
 259     request.write(formatter.text(title))
 260     request.write(formatter.emphasis(0))
 261     request.write(formatter.strong(0))
 262     request.write(formatter.linebreak(preformatted=0))
 263     request.write(formatter.url(abcurl, text="ABC source file"))
 264     request.write(formatter.linebreak(preformatted=0))
 265     request.write(formatter.url(psurl, text="PostScript score"))
 266     request.write(formatter.linebreak(preformatted=0))
 267     request.write(formatter.url(midiurl, text="MIDI rendition"))
 268     request.write(formatter.linebreak(preformatted=0))
 269     request.write(formatter.url(logurl, text="Compilation log"))
 270     request.write(formatter.paragraph(0))
 271     request.write(formatter.table_cell(0))
 272     request.write(formatter.table_row(0))
 273     
 274     if 0:#show_midi:
 275         request.write(formatter.table_row(1))
 276         request.write(formatter.table_cell(1))
 277         request.write(formatter.preformatted(1))
 278         request.write(formatter.rawHTML("<embed src=%s width=120 height=40 align=center>" % midiurl))
 279         request.write(formatter.preformatted(0))
 280         request.write(formatter.table_cell(0))
 281         request.write(formatter.table_row(0))
 282 
 283     if show_score:
 284         request.write(formatter.table_row(1))
 285         request.write(formatter.table_cell(1))
 286         request.write(formatter.url(pngurl))
 287         request.write(formatter.table_cell(0))
 288         request.write(formatter.table_row(0))
 289         
 290     if show_code:
 291         request.write(formatter.table_row(1))
 292         request.write(formatter.table_cell(1))
 293         request.write(formatter.preformatted(1))
 294         request.write(formatter.rawHTML(colorize(lines)))
 295         request.write(formatter.preformatted(0))
 296         request.write(formatter.table_cell(0))
 297         request.write(formatter.table_row(0))
 298 
 299     request.write(formatter.table(0))
 300     request.write(formatter.paragraph(0))
 301 
 302     # Old way with just one link
 303     #request.write(formatter.url(psurl, text=title))

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2004-05-05 21:34:20, 10.3 KB) [[attachment:AbcMusic.py]]
  • [get | view] (2004-04-15 07:19:38, 3.4 KB) [[attachment:DataLanguage.py]]
  • [get | view] (2004-04-15 20:23:33, 2.5 KB) [[attachment:GANTT-1.2.1.py]]
  • [get | view] (2003-12-07 18:15:55, 2.4 KB) [[attachment:GANTT.py]]
  • [get | view] (2004-07-29 15:04:28, 12.1 KB) [[attachment:IndentTable.py]]
  • [get | view] (2004-10-05 13:12:16, 10.6 KB) [[attachment:MySQL.py]]
  • [get | view] (2004-03-27 18:55:57, 3.7 KB) [[attachment:SimpleTable.py]]
  • [get | view] (2003-12-07 18:15:55, 1.5 KB) [[attachment:TextOnRight.py]]
  • [get | view] (2004-09-17 06:53:46, 3.0 KB) [[attachment:awktable-1.2.3.py]]
  • [get | view] (2004-10-28 13:55:04, 1.0 KB) [[attachment:colorer.py]]
  • [get | view] (2004-11-04 00:26:37, 1.4 KB) [[attachment:csv_python_module.diff]]
  • [get | view] (2004-04-21 18:29:38, 0.2 KB) [[attachment:html.py]]
  • [get | view] (2004-08-16 10:59:24, 4.8 KB) [[attachment:latex-1.2.3.py]]
  • [get | view] (2004-08-07 07:36:59, 3.9 KB) [[attachment:latex-cygwin.py]]
  • [get | view] (2004-04-09 17:05:33, 2.9 KB) [[attachment:latex.1.2.1.py]]
  • [get | view] (2004-02-29 16:50:13, 2.1 KB) [[attachment:latex.py]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.