Extension talk:LilyPond

From MediaWiki.org
Jump to navigation Jump to search

LilyPond at Wikimedia projects[edit]

What do we need to get this extension installed in wiki projects??Johann 13:06, 16 September 2007 (UTC)

Hello Johann,
as you can see here, Spanish Wikiversity has Mediawiki 1.12alpha (r26409) and for LilyPond you need version 1.6+ So I guess a bureaucrat or steward needs to install it there. So asking them would yield better results fro the moment. --Erkan Yilmaz 07:21, 6 October 2007 (UTC)
There has to be a request at bugzilla: (examples you can find there when you search) and before that your chances of realization increases when there is an election about this extension in the wiki where you can link to from the bugzilla report. And then the process at bugzilla will start (someone must have time, the stability of the extension will be checked, is it in teh interest of the wiki/foundation, ...), --Erkan Yilmaz 17:02, 16 December 2008 (UTC)
Also, there were a long discussion about the stability/security at bugzilla:189. I think we need to get in touch with Tim Starling and the LilyPond developers in order to get something. I'm talking with the LilyPond community right now, to know what can be done, but if somebody else wants this tool, all help to work in it are welcome! ;-) Helder 14:45, 23 April 2009 (UTC)
I'm also interested in a means of putting editable music into Wikipedia. At present, only those with music publishing software can edit the music samples that Wikipedia contains, and then laboriously, which defeats one of the principles of Wikipedia. Andrewa 10:54, 9 May 2009 (UTC)

scm_i_freelist' has different size in shared object[edit]

Hello,

I have a problem with Lilypond extension. I use Debian Etch (Lilypond 2.8.7). I had an error "Fontconfig file not found", so I upgraded Lilypond to Lenny (2.10.29-1).

Now I have the following error:

/usr/bin/lilypond: Symbol `scm_i_freelist' has different size in shared object, consider re-linking

What should I do? Thanks, Yann 01:08, 4 November 2007 (UTC)

Examples:

Solution[edit]

On Debian, guile 1.8.2 (unstable) and Lilypond 2.10.29 (testing) are needed. Yann 13:41, 4 November 2007 (UTC)

You don't need tot install a newer version of lilypond, you should just give the installed version in parameter when you write your document.
for debian etch use :
\version "2.8.7"
And it should be ok. --130.79.37.50 10:27, 7 May 2008 (UTC)

...doesn't work in my case :([edit]

The repository "ftp.riken.go.jp sid/main" has these packages (guile 1.8.2 and Lilypond 2.10.29) but I get the same error:

$ apt-cache policy lilypond
lilypond:
  Installed: 2.10.29-1
  Candidate: 2.10.29-1
  Version table:
 *** 2.10.29-1 0
        500 http://ftp.riken.go.jp sid/main Packages
        100 /var/lib/dpkg/status

$ apt-cache policy guile-1.8
guile-1.8:
  Installed: 1.8.2+1-2
  Candidate: 1.8.2+1-2
  Version table:
 *** 1.8.2+1-2 0
        500 http://ftp.riken.go.jp sid/main Packages
        100 /var/lib/dpkg/status

$ lilypond
lilypond: Symbol `scm_i_freelist' has different size in shared object, consider re-linking
GNU LilyPond 2.10.29
Segmentation fault 

Any other idea? Dietrich, 2007/11/30


Hello,

I tried to install it on 1.12 and get the error:

Fatal error: Call to undefined function wfEscapeHTML() in W:\www\test\extensions\LilyPond.php on line 77

	# if short_code is supplied, this is a fragment
	if( $short_code ) {
		$link = "<img src=\"".$wgMathPath."/".$md5.".png\" alt=\""
	Line 77 ->		.wfEscapeHTML( $short_code )."\">";

Any Ideas? Hajo 24.03.08

I get a complete Page instead of excerpts[edit]

Hi, I am using the code like its shown here, but I get a complete page (mostly blank) instead of just one line when I write this: lilypond>f, d f a d f e d cis a cis e a g f e </lilypond> I use MediaWiki 1.14.0 with PHP 5.2.6-3 (apache2handler). I don't know exactly what lilypond-version is installed on my (remote) host, but it should be the one in Debian Edge.

20. April 2009 - Nils

Trimming image size for multiple pages[edit]

Hello,

if I use the trimming function, it doesn't work with multiple pages. So, I have modified the source code to fix that.

A second change is that I add a pdf link for lilybook-tag.

2009/05/18 - Manni

The changed source code:

<?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>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.10.29.
 
*/
 
# User Settings
 
# Add a text link to prompt user to listen to midi, remember line breaks
$wgLilypondPreMidi  = "";   # eg " Listen<br>"
$wgLilypondPostMidi = "";   # eg  " <br>Listen"  
 
# You can set the global variable $wgLilypond if you want to override the
# path to the Lilypond executable.
 
# $wgLilypond = "/home/username/bin/lilypond";
 
# End User Settings
 
$wgExtensionFunctions[] = "wfLilyPondExtension";
 
function wfLilyPondExtension() {
	global $wgParser;
	$wgParser->setHook( "lilypond", "renderLilyPondFragment" );
	$wgParser->setHook( "lilymidi", "renderLilyPondMidiFragment" );
	$wgParser->setHook( "lilybook", "renderLilyPond" );
}
 
if( !isset( $wgLilypond ) )
	$wgLilypond = "PATH=\$PATH:/usr/local/bin /usr/local/bin/lilypond";
 
function renderLilyPondMidiFragment( $lilypond_code )
{
	return renderLilyPondFragment( $lilypond_code, true );
}

function renderLilyPondFragment( $lilypond_code, $midi=false )
{
	return renderLilyPond("\\header {\n"
			. "\ttagline = \"\"\n"
			. "}\n"
			. "\\paper {\n"
			. "\traggedright = ##t\n"
			. "\traggedbottom = ##t\n"
			. "\tindent = 0\mm\n"
			. "}\n"
			. "\\score {\n"
			. "\t\\relative c'' {\n"
			. $lilypond_code
			. "\t}\n"
			. "\t\\layout { }\n"
			. ($midi?"\t\\midi { }\n":"")
			. "}\n", $lilypond_code );
}

function isAlreadyConverted($md5) 
{
	global $wgMathPath, $wgMathDirectory, $wgTmpDirectory, $wgLilypond, $wgLilypondPreMidi, $wgLilypondPostMidi;

	return file_exists( "$wgMathDirectory/$md5.png") 
	    || file_exists( "$wgMathDirectory/$md5-1.png" );
}

function getHtmlContent($md5, $short_code) 
{
	global $wgMathPath, $wgMathDirectory, $wgTmpDirectory, $wgLilypond, $wgLilypondPreMidi, $wgLilypondPostMidi;


	if( file_exists( $wgMathDirectory."/".$md5.".midi" ) ) {
                $pre = "<a href=\"".$wgMathPath."/".$md5.".midi\"> " . $wgLilypondPreMidi;
                $post = $wgLilypondPostMidi . " </a>";
	} else {
		$pre = "";
		$post = "";
	}

	if( file_exists( $wgMathDirectory."/".$md5.".pdf" ) ) {
                $post .= "<br><a href=\"".$wgMathPath."/".$md5.".pdf\">pdf</a>";
	}


	# 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;
		}
	}
}

function renderLilyPond( $lilypond_code, $short_code=false )
{
	global $wgMathPath, $wgMathDirectory, $wgTmpDirectory, $wgLilypond, $wgLilypondPreMidi, $wgLilypondPostMidi;
 
	$createPDF = $short_code == false;
	$mf   = wfMsg( "math_failure" );
	$munk = wfMsg( "math_unknown_error" );
 
	$fname = "renderMusic";

	$md5 = md5($lilypond_code);
 
	if (isAlreadyConverted($md5)) {
		return getHtmlContent($md5, $short_code);
	}


	# 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 .
		" -dno-point-and-click -dsafe='#t' -dbackend=eps --png"
		. ($createPDF ? " --pdf" : "") 
		. " --header=texidoc "
		. escapeshellarg($lyFile) . " 2>&1";

	wfDebug( "Lilypond: $cmd" );
	$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>";
	}
 
	

	# move 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];
			trimImage($file_absolute, "png", $file_absolute, 20, 20);
			rename( $file_absolute, $wgMathDirectory . "/" .
					$md5 . "-" . $matches[1] . ".png" );
			continue;
		}
 
                if( preg_match( '/.pdf$/', $file ) ) {
			rename( $file_absolute, $wgMathDirectory."/".$md5.".pdf" );
			continue;
                }

                if( preg_match( '/.png$/', $file ) ) {
			trimImage($file_absolute, "png", $file_absolute, 20, 20);
			rename( $file_absolute, $wgMathDirectory."/".$md5.".png" );
			continue;
                }
 
		if( preg_match( '/.midi$/', $file ) ) {
			rename( $file_absolute, $wgMathDirectory . "/" .
					$md5 . ".midi" );
			continue;
		}
 
		if( !is_file( $file_absolute ) )
			continue;
		unlink( $file_absolute );
	}
	closedir( $files );
 
	return getHtmlContent($md5, $short_code);
}


function trimImage($source, $stype, $dest, $border_x, $border_y) 
{
  $size = getimagesize($source);
  $w = $size[0];
  $h = $size[1];
  $simg = imagecreatefrompng($source);
 
  $min_color_found = 100000000;
  $max_color_found = 0;
  for ( $qi = 0; $qi < $w; $qi++){
    for ( $qj = 0; $qj < $h; $qj++){
      $rgb = imagecolorat($simg, $qi , $qj);
 
      if ($rgb < $min_color_found) {
	$min_color_found = $rgb;
      }
 
      if ($rgb > $max_color_found) {
	$max_color_found = $rgb;
      }
    }
  }
 
  $min_x = $w + 1;
  $max_x = -1;
  $min_y = $h + 1;
  $max_y = -1;
  for ( $qi = 0; $qi < $w; $qi++){
    for ( $qj = 0; $qj < $h; $qj++){
      $rgb = imagecolorat($simg, $qi , $qj);
 
      if ($rgb == $min_color_found) {
	if ($qi < $min_x) { $min_x = $qi; }
	if ($qi > $max_x) { $max_x = $qi; }
	if ($qj < $min_y) { $min_y = $qj; }
	if ($qj > $max_y) { $max_y = $qj; }
      }
    }
  }
 
  $dimg = imagecreatetruecolor($max_x - $min_x + 2 * $border_x, $max_y - $min_y + 2 * $border_y);
  imagefill($dimg, 0, 0, $max_color_found);
  imagecopy($dimg, $simg, $border_x, $border_y, $min_x, $min_y, $max_x - $min_x + 1, $max_y - $min_y + 1);
  imagepng($dimg, $dest);
}

Replace exec function[edit]

Hello,

My web host doesn't allow the use of the exec function (line 157) and it seems to be very common so I was wondering if it was possible to replace it by the shell_exec (which is allowed) I tried to understand how I could modify the code by I don't know anything about php so the function isn't rejected but it doesn't work anyway.

Thanks for your cool extension.

PS : Is there any dependencies required to have this extension working? (I thing about the math extension)

Matthieu

New version[edit]

Hi there, I have uploaded a new version, here's the changelist.

  1. Rewrote and integrated the trimming functionality. The intention was good, but the original implementation was trimming too much and it was inefficient for the average use case.
  2. Made the border optional. The same effect can be achieved by wrapping the image with text anyway.
  3. Rearranged/added user-configurable variables and defaults.
  4. Removed the overly restrictive
    \relative c''
    from the template, which prevents users from using many useful LilyPond constructs.

I would also like to add support for languages other than the default "netherland". This is currently impossible unfortunately, unless we don't use Lilypond's "safe mode", which is not an option.

There is currently a bug open in Lilypond to implement better support for note languages, which will make it possible. Feel free to weigh in if you are interested.

Thanks. Hopefully acceptable username 06:57, 22 November 2009 (UTC)

Example...[edit]

Are you sure the example is right? "a" means both "a" at the beginning and an octave above that at the end? --Grin 13:48, 28 March 2011 (UTC)

LiliPond uses relative definition of notes. If the distance is less than a fifth (I'm not absolutely sure about the exact rules), you don't have to indicate an octave change (for example a' or a,). Best regards --Uncopy 14:07, 28 March 2011 (UTC)
Lilypond can run in both modes, so a b c' d' e' e is the same as \relative c' {a b c d e e,} -- Sloyment 09:38, 12 September 2011 (UTC)

Bug report[edit]

The current version (2009/11/15) does not work with scores that go over multiple pages, while the old version (2007/08/29) was able to handle that. The error message is: “Failed to parse (PNG conversion failed; check for correct installation of latex, dvips, gs, and convert)” (e.g. on this page) -- Sloyment 09:35, 12 September 2011 (UTC)

Fails with MediaWiki 1.18[edit]

After upgrading MediaWiki to 1.18 the LilyPond extension has stopped working. After discovering the problem, I installed the newest version with the three files LilyPond.php, LilyPond.class.php and LilyPond.i18n.php with no better success.
Setting $wgShowExceptionDetails = true; returns this error:
Detected bug in an extension! Hook wfLilyPondExtension failed to return a value; should return true to continue hook processing or false to abort.
--Even Thorbergsen 21:44, 5 December 2011 (UTC)

It seems like you can get it running by simply adding return true; at the end of the function wfLilyPondExtension in File LilyPond.php. I'm not absolutely sure, but I would try exactly that. Best

--Uncopy 09:55, 6 December 2011 (UTC)

I tried that to make this work with MEdiaWiki 1.18 by using 'return true;' where mentioned above. I does not result that 'Detected bug in an extesion!' phrase anymore, but Lilypond code fails to render, and results '<math_failure> (<math_bad_output>)'. So I guess LilyPond extension is not yet compatible with MediaWiki 1.18

--mamatuu 8 December 2011 (UTC)