Skip to content
Snippets Groups Projects
Commit d4cddf25 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

First version of my script to generate empty score sheets

parents
No related branches found
No related tags found
No related merge requests found
order deny,allow
deny from all
allow from 127.0.0.1
#!/bin/bash
# default values
user=lily
loopfile=/home/lily/loopfile
size=200000
jaildir=/home/lily/lilymnt
# Usage information
function USAGE ()
{
echo ""
echo "USAGE: "
echo " create_lily_jail.sh [-s SIZE] [-p LILYPREFIX] [USER [LOOPFILE [MOUNTPOINT]]]"
echo ""
echo "Create a proper chroot jail for lilypond, using a loop device with "
echo "the LOOPFILE of SIZE, mounted on MOUNTPOINT. Everything is created "
echo "in the USER's home directory and set up for use by USER."
echo ""
echo "ARGUMENTS:"
echo " USER The user for which the jail is set up ($user)"
echo " LOOPFILE The loopfile for the raw data ($loopfile)"
echo " MOUNTPOINT Where LOOPFILE will be mounted for use ($jaildir)"
echo ""
echo "OPTIONS:"
echo " -h This usage information"
echo " -p LILYPREFIX Where lilypond was manually installed to (empty)"
echo " If not given, lilypond will not be installed."
echo " Can be given multiple times."
echo " -s SIZE size of the loopfile in bytes ($size)"
echo ""
echo "EXAMPLE:"
echo " create_lily_jail.sh -s 100000 lily /home/lily/lilyloopfile"
echo ""
exit $E_OPTERROR # Exit and explain usage, if no argument(s) given.
}
lilyprefixes=()
#process options
while getopts ":p:s:h" Option
do
case $Option in
s ) size=$OPTARG;;
p ) # Remove / from the front/tail of prefix, because we will use it also as relative dir!
a=${OPTARG#/};
lilyprefixes+=(${a%/});;
h ) USAGE
exit 0;;
* ) echo ""
echo "Unimplemented option chosen."
USAGE
esac
done
shift $((OPTIND-1))
if [ "$#" -ge "1" ]; then user=$1; fi
loopfile=/home/$user/loopfile
jaildir=/home/$user/lilymnt
if [ "$#" -ge "2" ]; then loopfile=$2; fi
if [ "$#" -ge "3" ]; then jaildir=$3; fi
lilyhome=$jaildir/lilyhome
echo "user=$user, loopfile=$loopfile, jaildir=$jaildir, size=$size, lilyprefix=${lilyprefixes[@]}"
# check if user exists. If not, add it.
home=`cut -d: -f1,6 /etc/passwd | grep -e "^$user:" | sed "s/^$user://"`
echo "HOME: $home"
if [ -d "$home" ]; then
echo "User $user already exists";
else
home=/home/$user/
echo "Adding user $user with homedir $home";
adduser --gecos "LilyPond Jail user" $user;
fi
# check if the loopfile is already used. If so, get the loop device and unmount
# just in case it is mounted
loop=`losetup -j $loopfile 2> /dev/null | cut -d: -f1 `
if [ -e "$loop" ]; then
echo "Loop file already used on $loop, reusing it..."
umount $loop 2> /dev/null
losetup -d $loop
else
loop=`losetup --find`
echo "Finding next free loop device: $loop";
fi
# Create a loop file of the appropriate size. If it exists, ask for overwriting.
if [ -f $loopfile ]; then
echo "Loopfile $loopfile already exists. Do you want to overwrite it? [y/N]"
read answer
if [ "$answer" != "y" ]; then
echo "NOT overwriting the loopfile $loopfile. Exiting..."
exit 1
fi
fi
echo "Writing loopfile $loopfile of size $size"
dd if=/dev/zero of=$loopfile bs=1k count=$size
# Set up the proper loop devices
echo "Setting up $loop for file $loopfile, to be mounted at $jaildir"
mkdir -p $jaildir
losetup $loop $loopfile
mkfs -t ext3 $loop $size
mount -t ext3 $loop $jaildir
mkdir $lilyhome
# /lilyhome gets owned by the user, gets read/write permissions for the whole
# group, and read permissions for everyone.
chown $user.$user -R $lilyhome
chmod g+w -R $lilyhome
chmod o+r -R $lilyhome
# copy all files required for lilypond
echo "Setting up all files needed to run lilypond"
cd $jaildir
mkdir -p bin usr/bin usr/share usr/lib usr/share/fonts/truetype ${lilyprefixes[@]} tmp
chmod a+w tmp
# build an array of the lilypond and guile binaries in all prefixes
lily_use_binaries=();
for i in ${lilyprefixes[@]}; do
echo " Copying lilypond distribution from $i";
cp -rL /$i/lilypond $i;
lily_use_binaries+=(/$i/lilypond/usr/bin/lilypond /$i/lilypond/usr/bin/guile)
done
cp -L `which sh rm` bin
cp -L `which convert gs` usr/bin
# cp -L /usr/share/fonts/truetype/{msttcorefonts,ttf-liberation,ubuntu-font-family} usr/share/fonts/truetype
cp -L /usr/share/fonts/truetype usr/share/fonts
# Now the library copying magic
for i in ${lily_use_binaries[@]} `which sh rm gs convert`; do
echo " Finding dependencies for binary $i";
# ldd returns all dependencies, so extract the file name and then copy it
# with the same directory path
deps=`ldd $i | \
sed 's:.*=> /\(.*/[^(]*\).*:/\1:' | \
sed 's:\t/\(.*/.*\) (.*)$:/\1:' | \
sed '/.*=>.*/d'; `
for i in $deps; do
cp -rL --parents "$i" .
done
done
# The shared files for ghostscript and ImageMagick
cp -rL /usr/share/ghostscript usr/share
cp -rL /usr/lib/ImageMagick* usr/lib
umount -d $jaildir
mount -o auto,loop,noexec,nosuid,nodev $loopfile $jaildir
# Finally, print out some information for the user how to set up sudo and fstab:
echo "
/========================================================================\
| Setup of the lilypond chroot jail on $jaildir finished.
| Installed LilyPond binaries from prefixes:"
for i in ${lilyprefixes[@]}; do
echo "\
| $i"
done
echo "\
|
| Please add the following line to /etc/fstab to automatically mount
| the loop device:
| $loopfile $jaildir ext3 auto,loop,noexec,nosuid,nodev 0 0
|
| To enable a user USER to run 'sudo lilypond -j...' for any of these
| lilypond installations, please add the following lines to /etc/sudoers:"
for i in ${lilyprefixes[@]}; do
echo "\
| USER ALL=NOPASSWD: /$i/bin/lilypond -j$user\,$user\,$jaildir\,/lilyhome *"
done
echo \
"|
| To run jailed lilypond, copy the .ly file to $lilyhome (writable for all
| users of the group `$user') and run lilypond as:
| sudo /$i/bin/lilypond -j$user,$user,$jaildir,/lilyhome lilyfile_relative_to_lilyhome.ly
|
| If you want user `a' to be able to copy files to $lilyhome, then
| simply add him to the $user group:
| adduser a $user
|
\========================================================================/
"
<?php
umask (0644)
$basedir=dirname(__FILE__);
$user = "lilyjail";
$lilymnt = "/home/lilyjail/lilymnt";
$lilyhome = "/lilyhome";
$lilyworkdir = "$lilyhome/empty_sheet";
$ly_cmd = "/usr/bin/sudo /opt/lily2.14/bin/lilypond -j$user,$user,$lilymnt,$lilyhome ";
// print "<p>basedir: $basedir</p>";
// print "<p>ly_cmd: $ly_cmd</p>";
include('smarty3/Smarty.class.php');
$smarty = new Smarty();
$smarty->setTemplateDir($basedir.'/smarty/templates');
$smarty->setCompileDir($basedir.'/smarty/templates_c');
$smarty->setCacheDir($basedir.'/smarty/cache');
$smarty->setConfigDir($basedir.'/smarty/configs');
$smarty->left_delimiter = '{{';
$smarty->right_delimiter = '}}';
//////// Sanity checks for the URL parameters:
// TODO: Escape all values (i.e. make sure they are within the range, don't contain ", etc.
$paper_size = $_REQUEST["paper_size"];
$staff_size = $_REQUEST["staff_size"];
$systems = $_REQUEST["systems"];
$pages = $_REQUEST["pages"];
$title = $_REQUEST["title"];
$subtitle = $_REQUEST["subtitle"];
$composer = $_REQUEST["composer"];
$instrument = $_REQUEST["instrument"];
$metainfo = $title . $subtitle . $composer . $instrument;
$metahash = md5( $metainfo );
$score_type=$_REQUEST["score_type"];
//////// Use cache file name composed from the arguments
$out_file_basename = "Score_${score_type}_${paper_size}_${staff_size}pt_${systems}Systems_${pages}Pages";
if ($metainfo != "")
$out_file_basename .= "_${metahash}";
/////// Output variables for the template
$smarty->assign('paper_size', $paper_size);
$smarty->assign('staff_size', $staff_size);
$smarty->assign('systems', $systems);
$smarty->assign('pages', $pages);
if ($_REQUEST["title_check"])
$smarty->assign('title', $title);
if ($_REQUEST["subtitle_check"])
$smarty->assign('subtitle', $subtitle) ;
if ($_REQUEST["composer_check"])
$smarty->assign('composer', $composer);
if ($_REQUEST["instrument_check"])
$smarty->assign('instrument', $instrument);
//////// Check for the pdf file, create it if needed and return it:
$lycode = $smarty->fetch('empty_sheet.tpl.ly');
$base_file = $lilyworkdir . "/" . $out_file_basename;
$ly_file = $base_file . ".ly";
$pdf_file = $base_file . ".pdf";
if (!file_exists ($pdf_file)) {
// Create the lilypond file
$fh = fopen($lilymnt.$ly_file, 'w') or die("can't open file $lilymnt$ly_file for writing");
fwrite($fh, $lycode);
fclose($fh);
// Make sure jailed lilypond running as user lilyjail can read it:
chmod ($lilymnt.$ly_file, 0644);
// run it through lilypond to create the pdf
// As we are running inside the jail, we don't include $lilymnt in the pathes!
$cmd = "$ly_cmd -o $base_file $ly_file";
$lily_result = exec($cmd, $output, $retval);
}
if (file_exists ($lilymnt.$pdf_file)) {
header('Content-type: application/pdf');
header('Content-Description: Empty Music Score Sheets - provided by Edition Kainhofer');
header('Content-Type: application/pdf');
header('Content-Length: ' . filesize($lilymnt.$pdf_file));
header('Content-Disposition: inline; filename=' . basename($lilymnt.$pdf_file));
readfile($lilymnt.$pdf_file);
} else {
die ("Unable to create the score file. Wrong input or server error encountered.");
}
?>
\version "2.12.3"
#(set-global-staff-size {{$staff_size}})
#(set-default-paper-size "{{$paper_size}}")
\header {
{{if $title}} title="{{$title}}"
{{/if}}
{{if $subtitle}} subtitle="{{$subtitle}}"
{{/if}}
{{if $composer}} composer="{{$composer}}"
{{/if}}
{{if $instrument}} instrument="{{$instrument}}"
{{/if}}
copyright="Created by Edition Kainhofer, http://www.edition-kainhofer.com/, using LilyPond 2.14"
}
\paper {
pages={{$pages}}
systems-per-page={{$systems}}
ragged-bottom=##f
ragged-last-bottom=##f
ragged-last=##f
ragged-right=##f
}
emptymusic = {
\repeat unfold {{$systems*$pages}} { s1\break }
}
\new Score \with {
\override TimeSignature #'transparent = ##t
defaultBarType = #""
\remove Bar_number_engraver
} <<
\context ChoirStaff <<
\context Staff = women <<
\context Voice = sopranos { \emptymusic }
\context Voice = altos { \emptymusic }
>>
\context Staff = men <<
\clef bass
\context Voice = tenors { \voiceOne <<\emptymusic >> }
\context Voice = basses { \voiceTwo <<\emptymusic >> }
>>
>>
>>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<style>
.vsep {
background: darkgray;
}
</style>
</head>
<body>
<FORM action="empty_sheet.php" name="score_form">
<table>
<TR>
<td><label for="paper_size">Paper size:</label></td>
<td><select name="paper_size" id="paper_size">
<option value="a4" selected="selected">A4</option>
<option value="a5">A5</option>
<option value="a6">A6</option>
<option value="letter">US letter</option>
<option value="legal">Legal</option>
<option value="11x17">Ledger</option>
</select></td>
<td rowspan=4 class="vsep"></td>
<td><INPUT type="checkbox" name="title_check" size="15" accesskey="t" onchange="document.score_form.title.disabled = !this.checked" id="title_check"><label for="title_check" >Title: </label></td>
<td><INPUT type="text" checked name="title" size="25" maxlength="100" id="title" disabled="true"></td>
</tr>
<tr>
<td><label for="staff_size">Staff size:</label></td>
<td><select name="staff_size" id="staff_size">
<option value="11">11pt (Pocket scores)</option>
<option value="12.5">12.5pt</option>
<option value="14">14pt</option>
<option value="15">15pt</option>
<option value="16">16pt</option>
<option value="17">17pt</option>
<option value="18">18t</option>
<option value="19">19pt</option>
<option value="20" selected="selected">20pt (default)</option>
<option value="22">22</option>
<option></option>
</select></td>
<td><INPUT type="checkbox" name="subtitle_check" size="15" accesskey="c" onchange="document.score_form.subtitle.disabled = !this.checked" id="subtitle_check"><label for="subtitle_check" >Subtitle: </label></td>
<td><INPUT type="text" checked name="subtitle" size="25" maxlength="100" id="subtitle" disabled="true"></td>
</tr>
<tr>
<td><label for="systems">Systems/page:</label></td>
<td><select name="systems" id="systems">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10" selected="selected">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
</select></td>
<td><INPUT type="checkbox" name="composer_check" size="15" accesskey="c" onchange="document.score_form.composer.disabled = !this.checked" id="composer_check"><label for="composer_check" >Composer: </label></td>
<td><INPUT type="text" checked name="composer" size="25" maxlength="100" id="composer" disabled="true"></td>
</tr>
<tr>
<td><label for="pages">Pages:</label></td>
<td><select name="pages" id="pages">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
</select></td>
<td><INPUT type="checkbox" name="instrument_check" size="15" accesskey="i" onchange="document.score_form.instrument.disabled = !this.checked" id="instrument_check"><label for="instrument_check" >Instrument: </label></td>
<td><INPUT type="text" checked name="instrument" size="25" maxlength="100" id="instrument" disabled="true"></td>
</tr>
<tr><TD colspan=5><hr></TD></tr>
<tr>
<td valign=top><label for="score_type">Score type:</label></td>
<td colspan=4>
<SELECT name="score_type" id="score_type" style='width: 100%' size="20">
<option value="1" selected="selected">Single staff, no clef</option>
<option value="2">Single staff, treble clef</option>
<option value="3">Single staff, bass clef</option>
<option value="4">Single staff, tenor clef</option>
<option value="5">Single staff, alto clef</option>
<option disabled="disabled">---------</option>
<option value="6">Piano staff</option>
<option value="7">Organ staff</option>
<option disabled="disabled">---------</option>
<option value="8">Choir, 2 staves (SA + TB)</option>
<option value="9">Choir, 4 staves (S, A, T, B)</option>
<option disabled="disabled">---------</option>
<option value="10">Piano reduction for choir</option>
<option value="11">Piano reduction for single soloist</option>
<option disabled="disabled">---------</option>
<option value="12">String Trio</option>
<option value="13">String Quartett</option>
<option value="14">Piano Trio</option>
<option value="15">Piano Quartett</option>
<option disabled="disabled">---------</option>
<option value="16">Full Score, Chamber Orchestra</option>
<option value="17">Full Score, Symphonic Orchestra</option>
<option value="18">Full Score, Chamber Orchestra + Choir</option>
<option value="19">Full Score, Symphonic Orchestra + Choir</option>
</SELECT>
</td>
</tr>
<tr><TD colspan=5 align=center>
<INPUT type="submit" name="create_score" value="Create Score"><INPUT type="reset" value="Reset Values">
</TD></tr>
</table>
</FORM>
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment