http://www.mediawiki.org/wiki/Special:Code/MediaWiki/98414

Revision: 98414
Author:   mah
Date:     2011-09-29 16:17:40 +0000 (Thu, 29 Sep 2011)
Log Message:
-----------
Add LilyPond module

Added Paths:
-----------
    trunk/extensions/LilyPond/
    trunk/extensions/LilyPond/LilyPond.php

Added: trunk/extensions/LilyPond/LilyPond.php
===================================================================
--- trunk/extensions/LilyPond/LilyPond.php                              (rev 0)
+++ trunk/extensions/LilyPond/LilyPond.php      2011-09-29 16:17:40 UTC (rev 
98414)
@@ -0,0 +1,335 @@
+<?php
+/**
+ * MediaWiki extension: LilyPond
+ * =============================
+ *
+ * To activate, edit your LocalSettings.php, add
+ * require_once("$IP/extensions/LilyPond.php");
+ * and make sure that the images/ directory is writable.
+ *
+ * Example wiki code: <lilypond>\relative c' { c d e f g }</lilypond>
+ * If you want to typeset a fragment with clickable midi, use
+ * <lilymidi>...</lilymidi>
+ * If you want write a complete lilypond file, use
+ * <lilybook>...</lilybook>
+ *
+ * Tested with Lilypond version 2.12.2.
+ *
+ * @file
+ * @ingroup Extensions
+ * @version 0.01
+ * @author Johannes E. Schindelin
+ * @link http://www.mediawiki.org/wiki/Extension:LilyPond
+ */
+
+# User Settings
+
+# The following variables can be set in LocalSettings.php
+# before the line:
+# require_once("$IP/extensions/LilyPond.php");
+
+# You can set the variable $wgLilypond if you want/need to override the
+# path to the Lilypond executable. For example:
+# $wgLilypond = "/home/username/bin/lilypond";
+
+# Add a text link to prompt user to listen to midi, before and/or after
+# the image. Remember line breaks
+# $wgLilypondPreMidi  = "Listen<br>";
+# $wgLilypondPostMidi = "<br>Listen";
+
+# If you want to avoid trimming the resulting image, set $wgLilypondTrim
+# to false.
+# $wgLilypondTrim = false;
+
+# You can put a white border around the image if you like.
+# $wgLilypondBorderX = 10;
+# $wgLilypondBorderY = 0;
+
+# End User Settings
+
+# Defaulting of user settings
+if( !isset( $wgLilypond ) )
+               $wgLilypond = "PATH=\$PATH:/usr/local/bin 
/usr/local/bin/lilypond";
+
+if( !isset( $wgLilypondPreMidi ) )
+               $wgLilypondPreMidi = "";
+
+if( !isset( $wgLilypondPostMidi ) )
+               $wgLilypondPostMidi = "";
+
+if( !isset( $wgLilypondTrim ) ) {
+               $wgLilypondTrim = true;
+}
+
+if( !isset( $wgLilypondBorderX ) ) {
+               $wgLilypondBorderX = 0;
+}
+
+if( !isset( $wgLilypondBorderY ) ) {
+               $wgLilypondBorderY = 0;
+}
+
+$wgExtensionFunctions[] = "wfLilyPondExtension";
+
+function wfLilyPondExtension() {
+               global $wgParser;
+               $wgParser->setHook( "lilypond", "renderLilyPondFragment" );
+               $wgParser->setHook( "lilymidi", "renderLilyPondMidiFragment" );
+               $wgParser->setHook( "lilybook", "renderLilyPond" );
+}
+
+function renderLilyPondMidiFragment( $lilypond_code )
+{
+               return renderLilyPondFragment( $lilypond_code, true );
+}
+
+function renderLilyPondFragment( $lilypond_code, $midi=false )
+{
+               return renderLilyPond( "\\header {\n"
+                                               . "\ttagline = ##f\n"
+                                               . "}\n"
+                                               . "\\paper {\n"
+                                               . "\traggedright = ##t\n"
+                                               . "\traggedbottom = ##t\n"
+                                               . "\tindent = 0\mm\n"
+                                               . "}\n"
+                                               . "\\score {\n"
+                                               . $lilypond_code
+                                               . "\t\\layout { }\n"
+                                               . ($midi?"\t\\midi { }\n":"")
+                                               . "}\n", $lilypond_code );
+}
+
+function renderLilyPond( $lilypond_code, $short_code=false )
+{
+               global $wgMathPath, $wgMathDirectory, $wgTmpDirectory, 
$wgLilypond, $wgLilypondPreMidi, $wgLilypondPostMidii, $wgLilypondTrim, 
$wgLilypondBorderX, $wgLilypondBorderY;
+
+               $mf   = wfMsg( "math_failure" );
+               $munk = wfMsg( "math_unknown_error" );
+
+               $fname = "renderMusic";
+
+               $md5 = md5($lilypond_code);
+
+               if( file_exists( $wgMathDirectory."/".$md5.".midi" ) ) {
+                               $pre = "<a 
href=\"".$wgMathPath."/".$md5.".midi\"> " . $wgLilypondPreMidi;
+                               $post = $wgLilypondPostMidi . " </a>";
+               } else {
+                               $pre = "";
+                               $post = "";
+               }
+
+               # if short_code is supplied, this is a fragment
+ if( $short_code ) {
+                               $link = "<img 
src=\"".$wgMathPath."/".$md5.".png\" alt=\""
+                                               .htmlspecialchars( $short_code 
)."\">";
+
+                               if( file_exists( "$wgMathDirectory/$md5.png" ) 
) {
+                                               return $pre.$link.$post;
+                               }
+               } else {
+                               if(  file_exists( "$wgMathDirectory/$md5-1.png" 
) ) {
+                                               $link="";
+                                               for($i=1; file_exists( 
$wgMathDirectory . "/" .
+                                                                               
                $md5 . "-" . $i . ".png" );
+                                                                               
$i++) {
+
+                                                               $link .= "<img 
src=\"" . $wgMathPath . "/" .
+                                                                               
$md5 . "-" . $i . ".png\" alt=\"" .
+                                                                               
htmlspecialchars( "page ".$i )."\">";
+                                               }
+                                               return $pre.$link.$post;
+                               }
+               }
+
+               # Ensure that the temp and output dirs are available before 
continuing.
+ if( !file_exists( $wgMathDirectory ) ) {
+                               if( !@mkdir( $wgMathDirectory ) ) {
+                                               return "<b>$mf (" . wfMsg( 
"math_bad_output" ) .
+                                                               
$wgMathDirectory . ")</b>";
+                               }
+               } elseif( !is_dir( $wgMathDirectory ) ||
+                                               !is_writable( $wgMathDirectory 
) ) {
+                               return "<b>$mf (" . wfMsg( "math_bad_output" ) 
. ")</b>";
+               }
+               if( !file_exists( $wgTmpDirectory ) ) {
+                               if( !@mkdir( $wgTmpDirectory ) ) {
+                                               return "<b>$mf (" . wfMsg( 
"math_bad_tmpdir" )
+                                                               . ")</b>";
+                               }
+               } elseif( !is_dir( $wgTmpDirectory ) ||
+                                               !is_writable( $wgTmpDirectory ) 
) {
+                               return "<b>$mf (" . wfMsg( "math_bad_tmpdir" ) 
. ")</b>";
+               }
+
+               $lyFile = $md5.".ly";
+               $out = fopen( $wgTmpDirectory."/".$lyFile, "w" );
+               if( $out === false ) {
+                               return "<b>$mf (" . wfMsg( "math_bad_tmpdir" ) 
. ")</b>";
+               }
+               fwrite( $out, $lilypond_code );
+               fclose( $out );
+
+               $cmd = $wgLilypond .
+                               " -dsafe='#t' -dbackend=eps --png 
--header=texidoc " .
+                               escapeshellarg($lyFile) . " 2>&1";
+
+               wfDebug( "Lilypond: $cmd\n" );
+               $oldcwd = getcwd();
+               chdir( $wgTmpDirectory );
+               $contents = exec( $cmd, $output, $ret );
+               chdir( $oldcwd );
+
+               if( $ret != 0 ) {
+                               return "<br><b>LilyPond error:</b><br><i>"
+                               . str_replace( array( $md5, " " ),
+                                               array( "<b>your code</b>", 
"&nbsp;" ),
+                                               nl2br( htmlentities( join( 
"\n", $output ) ) ) )
+                               . "</i><br>";
+               }
+
+               if($short_code) {
+                               $outputFile = $wgTmpDirectory."/".$md5.".png";
+
+                               if( !file_exists( $outputFile ) ) {
+                                               return "<b>$mf (" . wfMsg( 
"math_image_error" )
+                                                               . ")</b>";
+                               }
+
+                               rename( $outputFile, 
$wgMathDirectory."/".$md5.".png");
+               }
+
+               # remove all temporary files
+ $files = opendir( $wgTmpDirectory );
+               $last_page = 0;
+
+               while( false !== ($file = readdir( $files ))) {
+                               if( substr( $file, 0, 32 ) != $md5 )
+                                               continue;
+
+                               $file_absolute = $wgTmpDirectory . "/" . $file;
+                               if( !$short_code && preg_match( 
'/-page(\d+)\.png$/',
+                                                                               
$file, $matches ) ) {
+                                               if($matches[1]>$last_page)
+                                                               $last_page = 
$matches[1];
+                                               rename( $file_absolute, 
$wgMathDirectory . "/" .
+                                                                               
$md5 . "-" . $matches[1] . ".png" );
+                                               continue;
+                               }
+
+                               if( preg_match( '/.png$/', $file ) ) {
+                                               rename( $file_absolute, 
$wgMathDirectory."/".$md5.".png" );
+                                               continue;
+                               }
+
+                               if( preg_match( '/.midi$/', $file ) ) {
+                                               rename( $file_absolute, 
$wgMathDirectory . "/" .
+                                                                               
$md5 . ".midi" );
+                                               $pre = "<a 
href=\"".$wgMathPath."/".$md5.".midi\"> " . $wgLilypondPreMidi;
+                                               $post = $wgLilypondPostMidi . " 
</a>";
+                                               continue;
+                               }
+
+                               if( !is_file( $file_absolute ) )
+                                               continue;
+                               unlink( $file_absolute );
+               }
+               closedir( $files );
+
+               if( $short_code ) {
+                               if( !file_exists( 
$wgMathDirectory."/".$md5.".png" ) ) {
+                                               $errmsg = wfMsg( 
"math_image_error" );
+                                               return "<h3>$mf ($errmsg): " .
+                                                               
htmlspecialchars($lilypond_code) . "</h3>";
+                               }
+               } else {
+                               $link .= "<img 
src=\"".$wgMathPath."/".$md5.".png\" alt=\""
+                               . htmlspecialchars( "page " )."\">";
+               }
+
+               if( $wgLilypondTrim ) {
+                               $imgFile = $wgMathDirectory ."/" .$md5 . ".png";
+                               trimImage( $imgFile, $imgFile, 0xFFFFFF );
+               };
+
+               if( $wgLilypondBorderX > 0 || $wgLilypondBorderY > 0 ) {
+                               $imgFile = $wgMathDirectory ."/" .$md5 . ".png";
+                               frameImage( $imgFile, $imgFile, 0xFFFFFF, 
$wgLilypondBorderX, $wgLilypondBorderY );
+               };
+
+               return $pre . $link . $post;
+}
+
+function trimImage( $source, $dest, $bgColour )
+{
+  $srcImage = imagecreatefrompng( $source );
+  $width = imagesx( $srcImage );
+  $height = imagesy( $srcImage );
+
+  $xmin = 0;
+  $found = false;
+  for( $x = 0; $x < $width && !$found; $x++ ) {
+       for( $y = 0; $y < $height && !$found; $y++ ) {
+         $rgb = imagecolorat( $srcImage, $x, $y );
+         if( $rgb != $bgColour ) {
+               $xmin = $x;
+               $found = true;
+         }
+       }
+  }
+
+  $xmax = $xmin;
+  $found = false;
+  for( $x = $width-1; $x > $xmin && !$found; $x-- ) {
+       for( $y = 0; $y < $height && !$found; $y++ ) {
+         $rgb = imagecolorat( $srcImage, $x, $y );
+         if( $rgb != $bgColour ) {
+               $xmax = $x;
+               $found = true;
+         }
+       }
+  }
+
+  $ymin = 0;
+  $found = false;
+  for( $y = 0; $y < $height && !$found; $y++ ) {
+       for( $x = 0; $x < $width && !$found; $x++ ) {
+         $rgb = imagecolorat( $srcImage, $x, $y );
+         if( $rgb != $bgColour ) {
+               $ymin = $y;
+               $found = true;
+         }
+       }
+  }
+
+  $ymax = $ymin;
+  $found = false;
+  for( $y = $height-1; $y > $ymin && !$found; $y-- ) {
+       for( $x = 0; $x < $width && !$found; $x++ ) {
+         $rgb = imagecolorat( $srcImage, $x, $y );
+         if( $rgb != $bgColour ) {
+               $ymax = $y;
+               $found = true;
+         }
+       }
+  }
+
+  $newWidth  = $xmax - $xmin + 1;
+  $newHeight = $ymax - $ymin + 1;
+
+  $dstImage = imagecreatetruecolor( $newWidth, $newHeight );
+  imagecopy( $dstImage, $srcImage, 0, 0, $xmin, $ymin, $newWidth, $newHeight );
+  imagepng( $dstImage, $dest );
+}
+
+function frameImage( $source, $dest, $bgColour, $borderWidth, $borderHeight )
+{
+  $srcImage = imagecreatefrompng( $source );
+  $width = imagesx( $srcImage );
+  $height = imagesy( $srcImage );
+  $dstImage = imagecreatetruecolor( $width + 2*$borderWidth, $height + 
2*$borderHeight );
+  $allocatedBgColour = imagecolorallocate( $dstImage, ($bgColour >> 16) & 
0xFF, ($bgColour >> 8) & 0xFF, $bgColour & 0xFF);
+  imagefill( $dstImage, 0, 0, $allocatedBgColour );
+  imagecopy( $dstImage, $srcImage, $borderWidth, $borderHeight, 0, 0, $width, 
$height );
+  imagepng( $dstImage, $dest );
+}


Property changes on: trunk/extensions/LilyPond/LilyPond.php
___________________________________________________________________
Added: svn:eol-syle
   + native


_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to