<?php if (!defined('PmWiki')) exit(); /* Copyright 2006 Patrick R. Michaud (pmichaud@pobox.com) This file is abcmusic.php; 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 script converts music files in "abc notation" into PostScript scores, gif images, and midi files. Once configured (see below), this script enables markup of the form: (:music:) ...abc notation here... (:musicend:) Configuration: Depending on the outputs you wish to produce, your system will also need some or all of the following external commands: abcm2ps - converts abc notation to postscript gs - Ghostscript ppmtogif - Convert .ppm files to .gif abc2midi - converts abc notation to .mid file The basic format for configuring this script is: $ABCProgs['abcm2ps'] = '/path/to/abcm2ps'; $ABCProgs['abc2midi'] = '/path/to/abc2midi'; include_once("cookbook/abcmusic.php"); If the "gs" and "ppmtogif" utilities aren't in PHP's executable path by default, you will also want to set appropriate values for $ABCProgs['gs'] and $ABCProgs['ppmtogif']. The options passed to each program are also controlled by the $ABCPSCmdFmt, $ABCGifCmdFmt, and $ABCMidiCmdFmt variables, so those can be set in addition to (or in lieu of) the $ABCProgs variables above. Lastly, the script uses the variables $PubCacheDir and $PubCacheUrl to determine where to place temporary files and how to reach them by url. */ SDV($RecipeInfo['AbcMusic']['Version'], '2006-04-03'); ## These are the external programs used for various aspects ## of converting .abc files. Many sites will need to configure ## these parameters with absolute paths to the external programs. SDVA($ABCProgs, array( 'abcm2ps' => 'abcm2ps', 'gs' => 'gs', 'ppmtogif' => 'pnmcrop | ppmtogif', 'abc2midi' => '')); SDV($PubCacheDir,"pub/cache"); SDV($PubCacheUrl,"$PubDirUrl/cache"); ## command to create .ps file if ($ABCProgs['abcm2ps']) SDV($ABCPSCmdFmt, "{$ABCProgs['abcm2ps']} -O\$ABCFile.ps \$ABCFile.abc"); ## command to create .gif file if ($ABCProgs['gs'] && $ABCProgs['ppmtogif']) { SDV($ABCGifCmdFmt, "{$ABCProgs['gs']} -sDEVICE=ppmraw -sOutputFile=- -q -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r96x96 \$ABCFile.ps | {$ABCProgs['ppmtogif']} >\$ABCFile.gif"); } ## command to create .mid file if ($ABCProgs['abc2midi']) SDV($ABCMidiCmdFmt, "{$ABCProgs['abc2midi']} \$ABCFile.abc -o \$ABCFile.mid"); ## (:music:) markup Markup('music', 'fulltext', '/\\(:music:\\)(.*?)\\(:musicend:\\)/eis', "Keep(AbcMusic(\$pagename, PSS('$1')))"); ## This is the function that does all of the work. :-) ## It just creates a suitable basename for the music files, ## calls each of the external programs to produce the corresponding ## output, and returns an HTML string with links to the ## appropriate files. function AbcMusic($pagename, $text) { global $FmtV, $PubCacheDir, $PubCacheUrl, $ABCProgs, $ABCPSCmdFmt, $ABCGifCmdFmt, $ABCMidiCmdFmt; $text = trim($text); $text = str_replace(array('<', '>', '&'), array('<', '>', '&'), $text); ## build a suitable filename from the music title (T:) if (preg_match('/^T:(.*)/m', $text, $match)) { $abctitle = $match[1]; $abcname = preg_replace('/\\s+/', '_', $abctitle); $abcname = preg_replace('/\\W+/', '', $abcname); $abcname .= '_' . substr(md5($text), 0, 6); } else $abcname = md5($text); $abcfile = "$PubCacheDir/$abcname"; $FmtV['$ABCName'] = $abcname; $FmtV['$ABCFile'] = $abcfile; ## Create the cache directory to hold the files mkdirp($PubCacheDir); fixperms($PubCacheDir); ## Create the "abc" file if (!file_exists("$abcfile.abc")) { $fp = fopen("$abcfile.abc", "w"); if ($fp) { fputs($fp, "$text\n"); fclose($fp); } else return "abcmusic failed to create $abcfile.abc\n"; } ## Create the "ps" file if (!file_exists("$abcfile.ps")) { $pscmd = FmtPageName($ABCPSCmdFmt, $pagename); if (system($pscmd) === false) return "abcmusic failed to create $abcfile.ps\n"; } ## Create the image file if (!file_exists("$abcfile.gif")) { $gifcmd = FmtPageName($ABCGifCmdFmt, $pagename); if (system($gifcmd) === false) return "abcmusic failed to create $abcfile.gif\n"; } ## Create the midi file if ($ABCMidiCmdFmt && !file_exists("$abcfile.mid")) { $midicmd = FmtPageName($ABCMidiCmdFmt, $pagename); system($midicmd); } ## Return the image and output $out = "<div class='abcmusic'>"; if (file_exists("$abcfile.gif")) $out .= "<img class='abcmusic' src='$PubCacheUrl/$abcname.gif' alt='$abctitle' /><br />"; if (file_exists("$abcfile.abc")) $out .= " <a href='$PubCacheUrl/$abcname.abc'>abc</a>"; if (file_exists("$abcfile.ps")) $out .= " <a href='$PubCacheUrl/$abcname.ps'>ps</a>"; if (file_exists("$abcfile.mid")) $out .= " <a href='$PubCacheUrl/$abcname.mid'>midi</a>"; $out .= "</div>"; return $out; }