diff --git a/.gitignore b/.gitignore index f87924609be4c18d591c480fcd1396a538200efc..fae40de0b0f293823d552b19b1ca3c3ac7369fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -smarty/templates_c/* +smarty *~ \ No newline at end of file diff --git a/empty_sheet.php b/empty_sheet.php index 0d2c35f17ce01e0eae01e0fa20af0f3efff06939..4433dc4747b6c2ef24efb57ba4a005b7d40d9880 100644 --- a/empty_sheet.php +++ b/empty_sheet.php @@ -35,7 +35,9 @@ function robust_request_string ($parm, $default) { } function robust_request_number ($parm, $default, $min, $max) { if (isset ($_REQUEST[$parm]) && is_numeric ($_REQUEST[$parm])) { - $val = $_REQUEST[$parm]; + // Extract the numeric value, discard everything else, so we prevent + // code insertion security problems! + $val = floatval($_REQUEST[$parm]); // Ensure the value is inside the given range: return min (max ($val, $min), $max); } else { @@ -62,7 +64,7 @@ function robust_request_bool ($parm, $default) { // {...} ... GrandStaff // (...) ... <<..>> -$known_staff_types = array ("S0", "S", "S8", "Sa", "St", "Sb", "O", "P", "Ch2", "Ch4", "Rh", "Tab", "Dr"); +$known_staff_types = array ("S0", "S", "S8", "Sa", "St", "Sb", "O", "P", "Ch2", "Ch4", "Rh", "Tab4", "Tab5", "Tab", "Dr"); $known_group_types = array ("{" => "GrandStaff", "(" => "", "[" => "StaffGroup"); $known_group_endings = array ("{" => "}", "(" => ")", "[" => "]"); @@ -133,17 +135,20 @@ if ($psz) { $staff_size = robust_request_number ("staff_size", 20, 3, 100); $systems = robust_request_number ("systems", 10, 1, 30); $pages = robust_request_number ("pages", 2, 1, 20); +$no_indent = robust_request_bool ("no_indent", false); $title = robust_request_string ("title", NULL); $subtitle = robust_request_string ("subtitle", NULL); $composer = robust_request_string ("composer", NULL); $arranger = robust_request_string ("arranger", NULL); $instrument = robust_request_string ("instrument", NULL); $header_space = robust_request_bool ("header_space", false); -$metainfo = $title . $subtitle . $composer . $instrument.$header_space; +$metainfo = $title . $subtitle . $composer . $instrument; $metahash = md5( $metainfo ); //////// Use cache file name composed from the arguments $out_file_basename = "Score_${type}_${paper_size}${orientation}_${staff_size}pt_${systems}Systems_${pages}Pages"; +if ($no_indent) + $out_file_basename .= "_NoIndent"; if ($header_space) $out_file_basename .= "_Header"; if ($metainfo != "") @@ -159,7 +164,15 @@ if ($pages > 1) { $png_file = $base_file . ".png"; } -function send_file_if_exists () +function write_log ($format, $filename, $created) +{ + global $lilyworkdir, $lilymnt; + file_put_contents ( "$lilymnt/$lilyworkdir/log-$format.log", + date(DATE_ISO8601) . + ", " . $_SERVER['REMOTE_ADDR'] . ", $filename, referrer: " . (isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:"-") . ", $created\n", FILE_APPEND); +} + +function send_file_if_exists ($status) { global $format, $lilymnt, $png_file, $ly_file, $pdf_file; if ($format == "png") { @@ -168,6 +181,7 @@ function send_file_if_exists () header('Content-Description: Empty Music Score Preview'); header('Content-Length: ' . filesize($lilymnt.$png_file)); readfile($lilymnt.$png_file); + write_log ($format, $png_file, $status); return TRUE; } } elseif ($format == "ly") { @@ -177,6 +191,7 @@ function send_file_if_exists () header('Content-Length: ' . filesize($lilymnt.$ly_file)); header('Content-Disposition: attachment; filename=' . basename($lilymnt.$ly_file)); readfile($lilymnt.$ly_file); + write_log ($format, $ly_file, $status); return TRUE; } } elseif ($format == "pdf") { @@ -186,13 +201,14 @@ function send_file_if_exists () header('Content-Length: ' . filesize($lilymnt.$pdf_file)); header('Content-Disposition: attachment; filename=' . basename($lilymnt.$pdf_file)); readfile($lilymnt.$pdf_file); + write_log ($format, $pdf_file, $status); return TRUE; } } } // If the file already exists, simply send it -if (send_file_if_exists ()) { +if (send_file_if_exists ("Cached")) { exit (0); } @@ -213,6 +229,7 @@ if (isset ($_REQUEST["score_type"])) { /////// Smarty setup include('smarty3/Smarty.class.php'); $smarty = new Smarty(); +$smarty_security = new Smarty_Security($smarty); $smarty->setCompileDir($basedir.'/smarty/templates_c'); $smarty->setCacheDir($basedir.'/smarty/cache'); $smarty->setConfigDir($basedir.'/smarty/configs'); @@ -232,11 +249,12 @@ $smarty->assign('composer', $composer); $smarty->assign('arranger', $arranger); $smarty->assign('instrument', $instrument); $smarty->assign('header_space', $header_space); +$smarty->assign('no_indent', $no_indent); $smarty->assign('indent', ''); $smarty->assign('contents', $score_type); -$smarty->allow_php_tag = true; +$smarty_security->allow_php_tag = true; ///// Create the lilypond file $lycode = $smarty->fetch('empty_sheet.tpl.ly'); @@ -247,11 +265,10 @@ fclose($fh); chmod ($lilymnt.$ly_file, 0644); // If .ly file was requested, send it without running lilypond -if ($format == "ly" && send_file_if_exists ()) { +if ($format == "ly" && send_file_if_exists ("Created")) { exit (0); } - /////////////////////////////////////////////////////////////////////////// // Run LilyPond on the .ly and return the result /////////////////////////////////////////////////////////////////////////// @@ -261,7 +278,7 @@ if ($format == "ly" && send_file_if_exists ()) { $cmd = "$ly_cmd -o $base_file $ly_file 2>&1"; $lily_result = exec($cmd, $output, $retval); -if (!send_file_if_exists ()) { +if (!send_file_if_exists ("Created")) { print ("Unable to create the score file. Wrong input or server error encountered."); if ($output) { print ("The output from running lilypond is:\n<pre>"); diff --git a/empty_sheet_form.php b/empty_sheet_form.php index 8455ebef45102868921476f14acae64193727d62..d12c9089e1b1c8a3d3d712f4b316179b959ef062 100644 --- a/empty_sheet_form.php +++ b/empty_sheet_form.php @@ -1,16 +1,121 @@ <?php $full = array_key_exists ("full", $_REQUEST); $debug = array_key_exists ("debug", $_REQUEST); - if ($debug) { - echo "<p id=debug></p>"; - } ?> <?php // The absolute URL to the current script, needed for all references // to scripts in this directoty! $abs_path = substr (dirname(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); ?> +<?php + // Definition of all the controls, including page size, staff size, score + // type, etc... All form fields will be generated from these arrays. + $paper_sizes = array( + "a4" => "A4", + "a5" => "A5", + "a6" => "A6", + "a4 landscape" => "A4 (landscape)", + "a5 landscape" => "A5 (landscape)", + "a6 landscape" => "A6 (landscape)", + "letter" => "US letter", + "legal" => "Legal", + "11x17" => "Ledger", + "letter landscape" => "US letter (landscape)", + "legal landscape" => "Legal (landscape)", + "11x17 landscape" => "Ledger (landscape)"); + $paper_sizes_default = "a4"; + + $staff_sizes = array ( + "10" => "3.5mm (10pt)", + "11" => "4mm (11pt, pocket score)", + "12.5" => "4.5mm (12.5pt)", + "14" => "5mm (14pt)", + "15" => "5.3mm (15pt, vocal score)", + "16" => "5.6mm (16pt)", + "17" => "6mm (17pt)", + "18" => "6.3mm (18pt)", + "19" => "6.7mm (19pt)", + "20" => "7mm (20pt, default)", + "23" => "8mm (23pt)", + "26" => "9mm (26pt)", + "28.5" => "10mm (28.5pt, HUGE)", + "45" => "16mm (45pt)"); + $staff_sizes_default = "20"; + + $systems_max = 15; + $systems_default = 10; + + $pages_max = 15; + $pages_default = 2; + + $score_header_fields = array ( + "title" => "Title", + "subtitle" => "Subtitle", + "composer" => "Composer", + "arranger" => "Arranger", + "instrument" => "Instrument"); + + $score_types = array ( + "S0" => "Single staff, no clef", + "S" => "Single staff, treble clef", + "Sb" => "Single staff, bass clef", + "St" => "Single staff, tenor clef", + "Sa" => "Single staff, alto clef", + "sep1" => Null, + "P" => "Piano staff", + "O" => "Organ staff", + "sep2" => Null, + "Ch2" => "Choir, 2 staves (SA + TB)", + "Ch4" => "Choir, 4 staves (S, A, T, B)", + "sep3" => Null, + "Ch4P" => "Piano reduction for choir (4 staves)", + "Ch2P" => "Piano reduction for choir (2 staves)", + "S0P" => "Piano reduction for single soloist", + "S0S0P" => "Piano reduction for two soloists", + "sep4" => Null, + "[SSSb]" => "String Trio (2 V, Vc)", + "[SSaSb]" => "String Trio (V, Va, Vc)", + "[SSSaSb]" => "String Quartet", + "SSbP" => "Piano Trio", + "SSaSbP" => "Piano Quartet", + "sep5" => Null, + "[S0S0]" => "Group of 2 staves, no clefs", + "[S0S0S0]" => "Group of 3 staves, no clefs", + "[S0S0S0S0]" => "Group of 4 staves, no clefs", + "[S0S0S0S0S0]" => "Group of 5 staves, no clefs", + "[S0S0S0S0S0S0]" => "Group of 6 staves, no clefs", + "[S0S0S0S0S0S0S0]" => "Group of 7 staves, no clefs", + "[S0S0S0S0S0S0S0S0]" => "Group of 8 staves, no clefs", + "sep6" => Null, +// "" => "Full Score, Chamber Orchestra", + "[SSSb][SS][Sb][{SS}SaSb]" => "Full Score, large Orchestra", +// "" => "Full Score, Chamber Orchestra + Choir", + "[SSb][SS][Sb][{SS}Sa]Ch4[Sb]" => "Full Score, large Orchestra + Choir", + "sep7" => Null, + "Rh" => "Single rhythmic staff (one line)", + "Dr" => "Single staff, drum clef", + "sep8" => Null, + "Tab4" => "Single tab staff, 4 strings", + "Tab5" => "Single tab staff, 5 strings", + "Tab" => "Single tab staff, 6 strings", + "[S0Tab4]" => "Staff + Tab staff, 4 strings", + "[S0Tab5]" => "Staff + Tab staff, 5 strings", + "[S0Tab]" => "Staff + Tab staff, 6 strings", + ); + $score_types_default = "S0"; + + $headercount = $full ? count($score_header_fields) : 1; +?> + <div id="music_score_form"> +<?php + if ($debug) { ?> + <div id=debug_box style="background:orange; border: 2pt red dashed;"> + <p id=debug style="background:lightorange;"></p> + <INPUT type="checkbox" name="debug_check" value="1" id="debug_check"> + <label for="debug_check">Show debug alerts (very annoying, but sometimes useful!)</label> + </div> +<?php } ?> <style type="text/css" > table.music_score_settings_table td.submit_button_cell { @@ -57,10 +162,11 @@ $abs_path = substr (dirname(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); <?php } ?> } - var staff_numbers = {"S0":1, "S":1, "S8":1, "Sa":1, "St":1, "Sb":1, "O":3, "P":2, "Ch2":2, "Ch4":4, "Rh":0.5, "Tab":1.35, "Dr":1}; + var staff_numbers = {"S0":1, "S":1, "S8":1, "Sa":1, "St":1, "Sb":1, "O":3, "P":2, "Ch2":2, "Ch4":4, "Rh":0.5, "Tab4":1, "Tab5":1.1, "Tab":1.35, "Dr":1}; var page_height = {"a4":297, "a5":210, "a6":148, "a4 landscape":210, "a5 landscape":148, "a6 landscape":105, "letter":279, "legal":356, "11x17":432, "letter landscape":216, "legal landscape":216, "11x17 landscape":279} + var previous_optimal_system_count = 10; function checkStaffCount () { // Staff type, without group structure var type = document.getElementById("score_type").value.replace(/[{}\(\)\[\]]/g, ""); @@ -79,18 +185,29 @@ $abs_path = substr (dirname(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); if (document.getElementById("header_space") && document.getElementById("header_space").checked) { available_space -= 35; // minus 30mm for header + padding } - var max_staves = Math.floor (available_space / min_space_per_system); - max_staves = Math.max (1, max_staves); // Show at least one staff + // minimum and optimal # of staves, at least 1 + var max_systems = Math.max (1, Math.floor (available_space / min_space_per_system)); + var opt_systems = Math.max (1, Math.floor (available_space / (1.5 * min_space_per_system))); // only allow max_staves in the combobox, disable all higher values: var sys_page_opt = document.getElementById("systems").options; for (var i = 0; i< sys_page_opt.length; ++i) { - sys_page_opt[i].disabled = (i>=max_staves); + sys_page_opt[i].disabled = (i>=max_systems); } - if (document.getElementById("systems").selectedIndex >= max_staves) { - document.getElementById("systems").selectedIndex = max_staves-1; + var selected_systems = document.getElementById("systems").selectedIndex + 1; + if (selected_systems > max_systems) { + document.getElementById("systems").selectedIndex = Math.min (<?php echo $systems_max?>, max_systems-1); + } else if (selected_systems == 0) { + // Nothing was selected, i.e. selectedIndex==-1, use optimal value + document.getElementById("systems").selectedIndex = Math.min (<?php echo $systems_max?>, opt_systems-1); + } else if (2*previous_optimal_system_count < opt_systems) { + // if we are too far from the optimal value, choose the optimal value + document.getElementById("systems").selectedIndex = Math.min (<?php echo $systems_max?>, opt_systems-1); } + previous_optimal_system_count = opt_systems; <?php if ($debug) { ?> - alert ("We have " + count + " staves in score with structure " + staves.join("/")+ ", max_staves: " + max_staves); + if (document.getElementById("debug_check").checked) { + alert ("We have " + count + " staves in score with structure " + staves.join("/")+ ", max_staves: " + max_systems); + } <?php } ?> } @@ -99,90 +216,8 @@ $abs_path = substr (dirname(__FILE__), strlen($_SERVER["DOCUMENT_ROOT"])); loadPreview (); } </script> -<?php - $paper_sizes = array( - "a4" => "A4", - "a5" => "A5", - "a6" => "A6", - "a4 landscape" => "A4 (landscape)", - "a5 landscape" => "A5 (landscape)", - "a6 landscape" => "A6 (landscape)", - "letter" => "US letter", - "legal" => "Legal", - "11x17" => "Ledger", - "letter landscape" => "US letter (landscape)", - "legal landscape" => "Legal (landscape)", - "11x17 landscape" => "Ledger (landscape)"); - $paper_sizes_default = "a4"; - - $staff_sizes = array ( - "10" => "3.5mm (10pt)", - "11" => "4mm (11pt, pocket score)", - "12.5" => "4.5mm (12.5pt)", - "14" => "5mm (14pt)", - "15" => "5.3mm (15pt, vocal score)", - "16" => "5.6mm (16pt)", - "17" => "6mm (17pt)", - "18" => "6.3mm (18pt)", - "19" => "6.7mm (19pt)", - "20" => "7mm (20pt, default)", - "23" => "8mm (23pt)", - "26" => "9mm (26pt)", - "28.5" => "10mm (28.5pt, HUGE)" -); - $staff_sizes_default = "20"; - - $systems_max = 15; - $systems_default = 10; - - $pages_max = 15; - $pages_default = 2; - - $score_header_fields = array ( - "title" => "Title", - "subtitle" => "Subtitle", - "composer" => "Composer", - "arranger" => "Arranger", - "instrument" => "Instrument"); - - $score_types = array ( - "S0" => "Single staff, no clef", - "S" => "Single staff, treble clef", - "Sb" => "Single staff, bass clef", - "St" => "Single staff, tenor clef", - "Sa" => "Single staff, alto clef", - "sep1" => Null, - "P" => "Piano staff", - "O" => "Organ staff", - "sep2" => Null, - "Ch2" => "Choir, 2 staves (SA + TB)", - "Ch4" => "Choir, 4 staves (S, A, T, B)", - "sep3" => Null, - "Ch4P" => "Piano reduction for choir (4 staves)", - "Ch2P" => "Piano reduction for choir (2 staves)", - "S0P" => "Piano reduction for single soloist", - "sep4" => Null, - "[SSSb]" => "String Trio (2 V, Vc)", - "[SSaSb]" => "String Trio (V, Va, Vc)", - "[SSSaSb]" => "String Quartet", - "[SSbP]" => "Piano Trio", - "[SSaSbP]" => "Piano Quartet", - "sep5" => Null, -// "" => "Full Score, Chamber Orchestra", - "[SSSb][SS][Sb][{SS}SaSb]" => "Full Score, large Orchestra", -// "" => "Full Score, Chamber Orchestra + Choir", - "[SSb][SS][Sb][{SS}Sa]Ch4[Sb]" => "Full Score, large Orchestra + Choir", - "sep6" => Null, - "Rh" => "Single staff (one line)", - "Dr" => "Single staff, drum clef", - "Tab" => "Single tab staff", - "[S0Tab]" => "Staff + Tab staff", - - ); - $score_types_default = "S0"; - - $headercount = $full ? count($score_header_fields) : 1; +<?php function write_option ($optkey, $optlabel, $optdefault) { $sel = ($optkey == $optdefault) ? ' selected="selected"' : ''; if ($optlabel) { @@ -213,7 +248,7 @@ function write_headerfield ($field, $label) { } ?> </select></td> - <td rowspan="<?php echo 4+$headercount?>" colspan=2 align=center class="previewcell"> + <td rowspan="<?php echo 5+$headercount?>" colspan=2 align=center class="previewcell"> <div id=previewdiv class="foo"> <div id="loadingOverlay"></div> <img id=preview src="<?php echo $abs_path; ?>/preview.png" onLoad="document.getElementById('loadingOverlay').style.visibility = 'hidden';" alt="PREVIEW"> @@ -255,6 +290,11 @@ function write_headerfield ($field, $label) { <?php } ?> </td> </tr> + <tr> + <td colspan="2"> + <INPUT type="checkbox" value="1" name="no_indent" id="no_indent" onchange="controlChanged();"><label for="no_indent" >No indent for first sytem</label> + </td> + </tr> <?php if ($full) { @@ -282,6 +322,27 @@ if ($full) { </SELECT> </td> </tr> +<?php if ($full) { ?> + <tr> + <td><INPUT type="checkbox" name="type_check" value="1" onchange="document.score_form.score_type_custom.disabled = !this.checked; document.score_form.score_type.disabled = this.checked; controlChanged();" id="type_check"><label for="type_check" >Custom type:</label></td> + <td><INPUT type="text" name="score_type" size="25" maxlength="200" id="score_type_custom" disabled="disabled" onchange="controlChanged();"></td> + </tr> + <tr> + <td colspan="4"> Syntax:<ul> + <li>Each staff type is identified by one or more letters, beginning with a capital letter. Multiple staves are simply written one after the other + <li>Available staff types: + <ul> + <li>S0, S, S8, Sa, St, Sb: normal staff with no, treble, treble_8, alto, tenor and bass clef + <li>P, O: Piano (group with staff for left + right hand, <tt>[SSb]<tt>) and Organ staff (like piano, but additional bass staff for pedal, <tt>([SSb]Sb)</tt>) + <li>Ch2, Ch4: Bracketed choir staff group with 2 and 4 staves + <li>Rh, Dr: Rhythmic staff (1 line), drum staff (5 lines, drum clef) + <li>Tab4, Tab5, Tab: Tab staff with 4, 5, and 6 lines + </ul> + <li>Groups and brackets are created by enclosing the staves with (...), [...] or {...}. These create no visible grouping, a square bracket or a brace. + </ul> + </td> + </tr> +<?php } ?> <tr><TD colspan=5 class="submit_button_cell"> <INPUT type="submit" name="create_score" value="Download PDF"><INPUT type="submit" name="create_lily" value="Download LilyPond"><INPUT type="reset" value="Reset Values"> </TD></tr> @@ -293,4 +354,4 @@ if ($full) { controlChanged (); </script> -</div> \ No newline at end of file +</div> diff --git a/templates/Group.tpl.ly b/templates/Group.tpl.ly index cda959998a052dc82de29b173b194b760c65ce4c..c8aecbb5dc3f0d27cc442b1ad67e3cc3502af31a 100644 --- a/templates/Group.tpl.ly +++ b/templates/Group.tpl.ly @@ -1,4 +1,4 @@ -{{$indent}}{{if $type}}\new {{$type}} {{/if}}<< +{{$indent}}{{if isset($type)}}\new {{$type}} {{/if}}<< {{foreach $contents as $c}} {{if is_array($c)}} {{include file='Group.tpl.ly' indent="$indent " type=$c.type contents=$c.contents}} diff --git a/templates/Tab4.tpl.ly b/templates/Tab4.tpl.ly new file mode 100644 index 0000000000000000000000000000000000000000..b0c0a98ae228ecdf8671472fc47ca8fd796cf153 --- /dev/null +++ b/templates/Tab4.tpl.ly @@ -0,0 +1 @@ +{{$indent}}\new TabStaff \with { stringTunings = #bass-tuning } \new TabVoice { \emptymusic } \ No newline at end of file diff --git a/templates/Tab5.tpl.ly b/templates/Tab5.tpl.ly new file mode 100644 index 0000000000000000000000000000000000000000..ee2e76c9e55819f3aed7093aad66b0f6fcc55bc6 --- /dev/null +++ b/templates/Tab5.tpl.ly @@ -0,0 +1 @@ +{{$indent}}\new TabStaff \with { stringTunings = #bass-five-string-tuning } \new TabVoice { \emptymusic } \ No newline at end of file diff --git a/templates/empty_sheet.tpl.ly b/templates/empty_sheet.tpl.ly index 4feef057dee6d762ae8406a6f01c6fe12ac9acea..154e49e9b27c0123114fc78471b867e30471f646 100644 --- a/templates/empty_sheet.tpl.ly +++ b/templates/empty_sheet.tpl.ly @@ -1,4 +1,4 @@ -\version "2.12.3" +\version "2.14.2" #(set-global-staff-size {{$staff_size}}) #(set-default-paper-size "{{$paper_size}}"{{if $orientation}} '{{$orientation}}{{/if}}) @@ -13,11 +13,17 @@ tagline = ##f } \paper { +{{if $header_space}} + % Remove the following line (defining bookTitleMarkup to just take some + % space, but not print any header fields) if you want to add a real + % title using the header fields above + bookTitleMarkup = \markup { \vspace #5 } +{{/if}} oddHeaderMarkup = ##f evenHeaderMarkup = ##f oddFooterMarkup = \markup \abs-fontsize #8 \with-color #(x11-color 'gray65) \fill-line { \with-url #"http://www.edition-kainhofer.com/" {"Edition Kainhofer"} - \with-url #"http://www.lilypond.org/" {"LilyPond - Music typesetting for everyone"} + \with-url #"http://www.lilypond.org/" {"LilyPond - Music notation for everyone"} } pages={{$pages}} systems-per-page={{$systems}} @@ -25,6 +31,9 @@ ragged-last-bottom=##f ragged-last=##f ragged-right=##f +{{if $no_indent}} + indent = 0 +{{/if}} #(set-paper-size "{{$paper_size}}"{{if $orientation}} '{{$orientation}}{{/if}}) top-system-spacing #'basic-distance = #7 top-markup-spacing #'basic-distance = #5 @@ -37,8 +46,6 @@ markup-system-spacing #'stretchability = #60 system-system-spacing #'stretchability = #40 -{{if $header_space}} bookTitleMarkup = \markup { \vspace #5 } -{{/if}} } \layout { diff --git a/create_lily_jail.sh b/utilities/create_lily_jail.sh similarity index 100% rename from create_lily_jail.sh rename to utilities/create_lily_jail.sh