Merge branch 'master' of defaria.com:/opt/git/clearscm
authorandrew <Andrew@DeFaria.com>
Tue, 13 May 2014 04:20:20 +0000 (21:20 -0700)
committerandrew <Andrew@DeFaria.com>
Tue, 13 May 2014 04:20:20 +0000 (21:20 -0700)
songbook/background.jpg [new file with mode: 0644]
songbook/displayartist.php [new file with mode: 0644]
songbook/index.php [new file with mode: 0644]
songbook/news.html [new file with mode: 0644]
songbook/search.php [new file with mode: 0644]
songbook/songbook.html [new file with mode: 0644]
songbook/songbook.jpg [new file with mode: 0644]
songbook/songbook.php [new file with mode: 0644]
songbook/webchord.cgi [new file with mode: 0755]

diff --git a/songbook/background.jpg b/songbook/background.jpg
new file mode 100644 (file)
index 0000000..2d289dc
Binary files /dev/null and b/songbook/background.jpg differ
diff --git a/songbook/displayartist.php b/songbook/displayartist.php
new file mode 100644 (file)
index 0000000..627aa16
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <meta name="GENERATOR" content="Mozilla/4.61 [en] (Win98; U) [Netscape]">
+  <title>Songbook" Artist</title>
+  <link rel="stylesheet" type="text/css" media="screen" href="/css/Music.css">
+  <link rel="stylesheet" type="text/css" media="print" href="/css/Print.css">
+  <link rel="SHORTCUT ICON" href="http://defaria.com/favicon.ico" type="image/png">
+
+<?php
+include_once "songbook.php";
+$artist = $_REQUEST ["artist"];
+?>
+
+<div class="heading">
+<a href="/songbook"><img src="/Icons/Home.png" alt="Home"></a>
+  <h1 class="centered">Andrew DeFaria's Songbook</h1>
+
+  <h2 class="centered"><?php echo $artist?></h2>
+</div>
+
+<div id="content">
+
+<?php
+$artistsSongs = array();
+
+foreach ($songs as $song) {
+  $songArtist = getArtist ($song);
+
+  if ($songArtist == $artist) {
+    array_push ($artistsSongs, $song);
+  } // if
+} // foreach
+
+print "<ol>";
+
+foreach ($artistsSongs as $artistSong) {
+  print "<li><a href=\"/bin/webchord.cgi?chordpro=$artistSong\">";
+  print basename ($artistSong, ".pro");
+  print "</a></li>";
+} // foreach
+?>
+
+</body>
+</html>
diff --git a/songbook/index.php b/songbook/index.php
new file mode 100644 (file)
index 0000000..8b32bbd
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <meta name="GENERATOR" content="Mozilla/4.61 [en] (Win98; U) [Netscape]">
+  <title>Songbook</title>
+  <link rel="stylesheet" type="text/css" media="screen" href="/css/Music.css">
+  <link rel="stylesheet" type="text/css" media="print" href="/css/Print.css">
+  <link rel="SHORTCUT ICON" href="http://defaria.com/favicon.ico" type="image/png">
+
+<?php
+include_once "songbook.php";
+?>
+
+</head>
+
+<body>
+
+<?php
+  if (file_exists ("news.html")) {
+    print "<a href=\"news.html\"><img src=\"/Icons/news.png\"></a>";
+  }
+?>
+
+<div class="heading">
+  <h1 class="centered">Andrew DeFaria's Songbook</h1>
+</div>
+
+<div id="content">
+
+<p>As a professional musician do yourself a favor and invest in a tablet or if
+you must an iPad and get either SongBook (for Android) or OnSong (for iPad) then
+send me a request to sign up for Dropbox which integrates with these apps and
+your "songbook" will be automated. Note that Songbook is also available for
+Windows. More info on this is available <a href="songbook.html">here</a>. For
+people who must remain with paper...</p>
+
+<p>The following songs are available here. Select an artist or a song and then
+Go or type in a lyric or song title into the search box. You can print the 
+result if you wish to have a paper copy. If new songs are added by me or others
+this page will automatically update so you can come back here and get your 
+copy.</p>
+
+<?php
+artistsDropdown();
+songsDropdown();
+?>
+
+<form method="post" action="search.php" name="search">
+Search:&nbsp;&nbsp;<input type="text" name="searchterm"><input type="submit" value="Search">
+
+</form>
+</body>
+</html>
diff --git a/songbook/news.html b/songbook/news.html
new file mode 100644 (file)
index 0000000..7c6f562
--- /dev/null
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <meta name="GENERATOR" content="Mozilla/4.61 [en] (Win98; U) [Netscape]">
+  <title>Songbook</title>
+  <link rel="stylesheet" type="text/css" media="screen" href="/css/Plain.css">
+  <link rel="stylesheet" type="text/css" media="print" href="/css/Print.css">
+  <link rel="SHORTCUT ICON" href="http://defaria.com/favicon.ico" type="image/png">
+</head>
+
+<body>
+
+<img src="/Icons/news.png">
+
+<div class="heading">
+  <h1 class="centered">Songbook News</h1>
+</div>
+
+<div id="content">
+
+<h2>Recent Changes</h2>
+
+<p>I've made some more changes:</p>
+
+<ul>
+
+<li>Removed the list of songs from the front page. There were getting to be just
+too many songs listed to be helpful. Instead I now have a drop down list of 
+artists and songs as well as a search box. Select an artist or a song and then
+select go to go to an artist page or a song page. Or search for a term. The search
+will search for a word or phrase in the title, artist or in the song itself. The
+search is not that bright but works fairly well.</li>
+
+<li>There's a new artist's page which shows you all of the artists songs in one
+page. Many artists have only one or a few songs. Some artists have quite a few
+songs.</li>
+
+<li>The song pages now are on auto play. If they have music assoicated with them
+then their music will start playing automatically.</li>
+</ul>
+
+<h2>Past Changes</h2>
+
+<ul>
+  <li>Changed the home icon to something much bigger. Clicking on this gets you
+  back to the <a href="/songbook">Songbook home page</a>.</li>
+  
+  <li>Now if the song has an associated .mp3 file in the Media folder that
+  <b>exactly</b> matches the song's title then a little HTML5 MP3 player will 
+  appear. You can play the song while you read the words and follow the 
+  chords! <b>Note:</b> You can right click and save the song's mp3 file to
+  your computer. If the song does not have a corresponding .mp3 file then
+  no .mp3 player is displayed. For example, <a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Amie.pro">Amie</a>.</li>
+  
+  <li>Again, if the song has a corresponding .mp3 file I now re-write the .pro
+  file to include {musicpath:/sdcard/SongBook/Medai/&lt<i>title</i>&gt;.mp3}. 
+  This string "links" the ChordPro file with music such that (in SongBook, the
+  app I use on my Android Tablet) you can play the song's mp3 file on your 
+  tablet! I'm not sure if OnSong (the iPad equivalent of SongBook) does the same
+  thing. If you sign up for sharing my songbook via DropBox (<a href="mailto:adefaria@gmail.com?subject=Please share your SongBook with me">send me email</a> if
+  you want an invite) you should be all set.</li>
+</ul>
+
+<p><b>Note:</b> Currently my code is very picky. The file name for the .pro file
+and the .mp3 file must match <b>exactly</b> - is case sensitive, etc. If you 
+have access to my songbook in DropBox and wish to add a .pro file and it's 
+corresponding .mp3 file then be sure to match the names up correctly and put the
+.mp3 file in the Media folder.</p>
+
+<h2>Future Changes</h2>
+
+<p>Here are some of the things I'm thinking of implementing:</p>
+
+<ul>
+  <li><strike>I'm thinking of re-vamping the main page. Instead of listing all the 
+  songs, which are getting to be a bit much, I would like to possibly make a 
+  little search facility that would scan the .pro files for text matching in the
+  song titles and lyrics themselves.</strike></li>
+
+  <li>Another change I'm thinking of making is making it so that when you hover 
+  over a chord a little popup happens that shows the chord's fingering. Sorta 
+  like it's done over on tabs-ulitimate-guitar.com (For example: 
+  <a href="http://tabs.ultimate-guitar.com/s/steve_miller/serenade_crd.htm">here</a>).
+  Anybody know how to do that?</li>
+  
+  <li>Maybe a simple editor so people can edit songs directly.</li>
+  
+  <li>Maybe interfacing with Dropbox to display information about the last 
+  person to update the songfile...</li>
+</ul> 
+
+</div>
+
+</body>
+</html>
diff --git a/songbook/search.php b/songbook/search.php
new file mode 100644 (file)
index 0000000..edd23f2
--- /dev/null
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <meta name="GENERATOR" content="Mozilla/4.61 [en] (Win98; U) [Netscape]">
+  <title>Songbook" Artist</title>
+  <link rel="stylesheet" type="text/css" media="screen" href="/css/Music.css">
+  <link rel="stylesheet" type="text/css" media="print" href="/css/Print.css">
+  <link rel="SHORTCUT ICON" href="http://defaria.com/favicon.ico" type="image/png">
+
+<?php
+include_once "songbook.php";
+$searchterm = $_REQUEST ["searchterm"];
+$songmatches = array();
+
+function getSongText ($song) {
+  return join ("\n", file ($song));
+} // getSongText
+
+function search ($searchterm) {
+  global $songs;
+  global $songmatches;
+
+  $tokens = preg_split ("/\s+/", $searchterm);
+  $searchfor = join (".*", $tokens);
+
+       foreach ($songs as $song) {
+    $text = getSongText ($song);
+
+    preg_match ("/$searchfor/i", $text, $matches);
+
+    if ($matches) {
+      array_push ($songmatches, $song);
+    } // if
+  } // foreach
+
+  return $songmatches;
+} // search
+
+$songmatches = search ($searchterm);
+?>
+</head>
+
+<body>
+
+<div class="heading">
+<a href="/songbook"><img src="/Icons/Home.png" alt="Home"></a>
+  <h1 class="centered">Andrew DeFaria's Songbook</h1>
+
+  <h2><?php
+if (count ($songmatches) == 0) {
+  print "No songs matched \"$searchterm\"";
+} elseif (count ($songmatches) == 1) {
+  print "One song matched \"$searchterm\"";
+} else {
+  print count ($songmatches) . " songs matched \"$searchterm\"";
+} // if
+?></h2>
+</div>
+
+<div id="content">
+
+<?php
+if (count ($songmatches) > 0) {
+  print "<ol>";
+} // if
+
+foreach ($songmatches as $songmatch) {
+  $artist = getArtist ($songmatch);
+  $title  = basename ($songmatch, ".pro");
+  print "<li><a href=\"/bin/webchord.cgi?chordpro=$songmatch\">$title</a>";
+  print "&nbsp;(<a href=\"displayartist.php?artist=$artist\">$artist</a>)</li>";
+} // foreach
+
+if (count ($songmatches) > 0) {
+  print "</ol>";
+} // if
+?>
+
+</div>
+</body>
+</html>
+
diff --git a/songbook/songbook.html b/songbook/songbook.html
new file mode 100644 (file)
index 0000000..fd3faf8
--- /dev/null
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+  <meta name="GENERATOR" content="Mozilla/4.61 [en] (Win98; U) [Netscape]">
+  <title>Songbook</title>
+  <link rel="stylesheet" type="text/css" media="screen" href="/css/Plain.css">
+  <link rel="stylesheet" type="text/css" media="print" href="/css/Print.css">
+  <link rel="SHORTCUT ICON" href="http://defaria.com/favicon.ico" type="image/png">
+</head>
+
+<body>
+
+<div class="heading">
+  <h1 class="centered">Songbook/OnSong and chordpro (.pro) files</h1>
+</div>
+
+<div id="content">
+
+<p>Rather than carry around sheets of paper for everybody, fumbling
+and trying to find the right song sheet etc., you can use your
+computer to help automate this process.</p>
+
+<p>A chordpro file (signified by a .pro extension) is not a fancy file
+format, but it gets the job done and is easy to edit with any editor
+like notepad. You can google "chordpro" and read all about the format
+if you like.</p>
+
+<p>If you have a iPad or a Android tablet you can have all of your
+songs with you wherever you go. Linked
+with <a href="https://www.dropbox.com/">DropBox</a> and everybody can
+be on the same page. Worst case you have all of the music you know at
+your fingertips. There are two apps, one for iPads
+(<a href="https://itunes.apple.com/us/app/onsong/id502344938?mt=8">OnSong</a>)
+and the other for Android and PCs
+(<a href="http://linkesoft.com/songbook/windows.html">Songbook</a>)
+that will work with .pro file to render them nicely on your iPad or
+Android tablet. And Songbook also works on your Windows PC where
+you can print out copies of the songs if you inist on dealing with
+paper.</p>
+
+<p>Finally, you could go to my website and render any of the songs in
+my Songbook using the web (described below).</p>
+
+<h2>Chordpro file format</h2>
+
+<p>You can go
+to <a href="http://defaria.com/songbook/Songs">http://defaria.com/songbook/Songs</a>
+and you'll see a list of all the files in that directory, the .pro
+files of the songs I have. You can click on any of them but what you
+will get is an unrendered version of the .pro file. For example: If
+you click on Brown Eyed Girl.pro you'll see:</p>
+
+<blockquote><pre>
+    {t:Brown Eyed Girl}
+    {st:Van Morrison}
+    {key:G}
+
+    [G]Hey, where did [C]we go, da[G]ys when the ra[D]ins came
+    [G]Down in the holl[C]ow, [G]playin' a ne[D]w game
+    [G]Laughin' and a-s[C]ingin' hey-hey, [G]skippin' and a-j[D]umpin'
+    [G]In the misty mor[C]ning fog, with o[G]ur he[D]arts thumpin and yo[C]u[D]
+    My Brown-eyed gi[G]rl[Em], yo[C]u my[D] brown eyed [G]girl [D]
+
+    [G]Hey whatever [C]happened, [G]Tuesday went [D]so slow
+    [G]Goin down the [C]old mine with a [G]transistor [D]radio
+    [G]Standin' in the [C]sunlight laughin', [G]hide behind the [D]rainbow's wall
+    [G]Slippin' and a-[C]slidin', [G]all along the [D]waterfall with [G]you
+    My Brown-eyed gi[G]rl[Em], yo[C]u my[D] brown eyed [G]girl [D]
+
+    {soc}
+    [D]Do you remember when we used to [G]sing
+    Sha-la-la [C]la-la la-la [G]la-la la-la [D]de-da
+    [G]Sha-la-la [C]la-la la-la [G]la-la la-la [D]de-da
+    La-de-[G]da[D]
+    {eoc}
+
+    [G][Em][C][D][G][D]
+
+    So hard to find my way, now that I'm all on my own
+    Saw you just the other day, my how you have grown
+    Cast my memory back there lord, sometimes I'm overcome, thinkin'bout
+    Making love in the green grass, behind the stadium with you
+    My brown eyed girl, you my brown eyed girl
+
+    {soc}
+    [D]Do you remember when we used to [G]sing
+    Sha-la-la [C]la-la la-la [G]la-la la-la [D]de-da
+    [G]Sha-la-la [C]la-la la-la [G]la-la la-la [D]de-da
+    La-de-[G]da
+    {eoc}
+</pre></blockquote>
+
+<p>You see things like {t:Brown Eyed Girl} (title) and {key:G} as well
+as embedded tags for the chords ([G], [C], etc). Doesn't look as
+pretty right? But when you include the webchord.cgi portion you are
+running a script named webchord.cgi which reads the file from the
+parameter chordpro (that's why you need the chordpro=song.pro portion)
+and then reformats stuff into HTML that looks pretty, centering the
+title of the song, putting the chords over the words and bolding the
+text between {soc} and {eoc} (start of chorus, end of chorus). So
+given the above SongTitle="Brown Eyed Girl" we can formulate the URL
+to render it thusly:</p>
+
+<blockquote><a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Brown Eyed Girl.pro">http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Brown Eyed Girl.pro</a></blockquote>
+
+<p>You can do the same thing for the other songs there too.</p>
+
+<p>I should just write a quick script that gets all of the .pro files
+in the directory songbook/Songs and then formulates a page of links
+that have the webchord.cgi links to render them like:</p>
+
+<ul>
+  <li><a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Across the Universe.pro">Across the Universe</a></li>
+  <li><a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/American Pie.pro">American Pie</a></li>
+  <li><a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Amie.pro">Amie</a></li>
+  <li><a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Back in the USSR.pro">Back in the USSR</a></li>
+  <li>...</li>
+</ul>
+
+<p>You have to fill in the &lt;SongTitle&gt; portion of the link. So, for
+example, you take:</p>
+
+<blockquote>
+http://defaria.com/songbook/Songs/webchord.cgi?chordpro=&lt;SongTitle&gt;.pro
+</blockquote>
+
+<p>pop it into the address bar of your browser then change &lt;SongTitle&gt;
+to the title of the song you want to render:</p>
+
+<blockquote>
+<a href="http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Amie.pro">http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Amie.pro</a>
+</blockquote>
+
+<p><b>Note:</b></p>
+
+<ul>
+  <li>URLs are case sensitive! ...chordpro=amie.pro is not the same as ...chordpro=Amie.pro</li>
+  <li>Browsers tend to change spaces in a URL to %20. %20 is the octal representation for a space character. So if you see %20 in a URL like http://defaria.com/bin/webchord.cgi?chordpro=/web/songbook/Songs/Back%20in%20the%20USSR.pro. Don't fear - they're merely spaces.</li>
+</ul>
+
+<h2>Songbook for PC</h2>
+
+<p>You can get a Windows PC version of Songbook
+at <a href="http://linkesoft.com/songbook/windows.html">http://linkesoft.com/songbook/windows.html</a>. It
+will run on your PC and render songs like:</p>
+
+<img src="songbook.jpg">
+
+<p>It's $20 and you can even print out your stuff if you still use
+paper or need paper for other people.</p>
+
+</div>
+
+</body>
+</html>
diff --git a/songbook/songbook.jpg b/songbook/songbook.jpg
new file mode 100644 (file)
index 0000000..343a1c4
Binary files /dev/null and b/songbook/songbook.jpg differ
diff --git a/songbook/songbook.php b/songbook/songbook.php
new file mode 100644 (file)
index 0000000..f3893b8
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+$songs = glob ("/web/songbook/Songs/*.pro");
+
+function songsDropdown () {
+  global $songs;
+
+  print "<form method=\"post\" action=\"/bin/webchord.cgi\" name=\"song\">";
+  print "Songs:&nbsp;&nbsp;";
+  print "<select name=\"chordpro\">";
+
+  sort ($songs);
+  foreach ($songs as $song) {
+    $title = basename ($song, ".pro");
+    $artist = getArtist ($song);
+
+    if ($artist != "") {
+      $title .= "&nbsp;($artist)";
+    } // if
+
+    print "<option value=\"$song\">$title</option>";
+  } // foreach
+
+  print "<input type=\"submit\" value=\"Go\">";
+  print "</select>";
+  print "</form>";
+} // songsDropdown
+
+function artistsDropdown () {
+  global $songs;
+
+  $artists = getArtists ($songs);
+
+  print "<form method=\"post\" action=\"displayartist.php\" name=\"artist\">";
+  print "Artists:&nbsp;&nbsp;";
+  print "<select name=\"artist\">";
+
+  sort ($artists);
+  foreach ($artists as $artist) {
+    print "<option>$artist</option>";
+  } // foreach
+
+  print "<input type=\"submit\" value=\"Go\">";
+  print "</select>";
+  print "</form>";
+} // artistsDropdown
+
+function getArtist ($song) {
+  $lyrics = file_get_contents ($song);
+
+  if (preg_match ("/\{(st|subtitle):(.*)\}/", $lyrics, $matches)) {
+    return trim ($matches[2]);
+  } else {
+    return "";
+  } // if
+} // getArtist
+
+function getArtists ($songs) {
+  $artists = array();
+
+  foreach ($songs as $song) {
+    $artist = getArtist ($song);
+
+    if ($artist != '') {
+      $artists[$artist] = 1;
+    } // if
+  } // foreach
+
+  return array_keys ($artists);
+} // getArtists
+
+function formatTable ($songs) {
+  echo "<ol>";
+
+  foreach ($songs as $song) {
+    $artist = getArtist ($song);
+
+    $title = basename ($song, ".pro");
+
+    echo "<li><a href=\"/bin/webchord.cgi?chordpro=$song\">$title</a>";
+
+    if ($artist != "") {
+    echo "&nbsp;($artist)";
+    } // if
+  } // foreach
+
+  echo "</ol>";
+} // formatTable
\ No newline at end of file
diff --git a/songbook/webchord.cgi b/songbook/webchord.cgi
new file mode 100755 (executable)
index 0000000..28d0969
--- /dev/null
@@ -0,0 +1,311 @@
+#!/usr/bin/perl
+
+# Web Chord v1.1 - A CGI script        to convert a ChordPro file to HTML
+# Copyright 1998-2003 Martin Vilcans (martin@mamaviol.org)
+#
+# CGI parameters:
+#  chopro - This parameter can be submitted by a form  as a text field or file
+#           upload.
+#
+# History:
+# 1998-07-20 Version 1.0
+# 2003-08-03 Version 1.1 Uses stylesheets
+# 2014-02-05 Added things particular to my implementation of Songbook at
+#            http://defaria.com/songbook
+
+use strict;
+use warnings;
+
+use CGI qw(:standard);
+use CGI::Carp qw (fatalsToBrowser);
+use File::Basename;
+
+my ($chopro, $output, $i);
+
+my $documentRoot = "/web";
+my $debug        = param ('debug');
+my $infile       = param ('chordpro');
+
+
+sub debug ($) {
+  my ($msg) = @_;
+  
+  return unless $debug;
+  
+  print "<font color=red><b>Debug:</b></font> $msg<br>";  
+  
+  return;
+} # debug
+
+sub warning ($) {\r
+  my ($msg) = @_;
+
+  debug "warning";
+
+  print "<font color=orange><b>Warning</b></font> $msg<br>";
+
+  return;  
+} # warning
+
+sub error {
+  my ($msg) = @_;
+  
+  print "<html><head><title>Web Chord: Error</title></head>" .
+    "<body><h1>Error</h1><p>\n$msg\n</p>" .
+    "</body></html>";
+  
+  exit;
+} # error
+
+sub musicFileExists ($) {
+  my ($song) = @_;
+
+  debug "ENTER musicFileExists ($song)";
+  
+  my $title     = fileparse ($song, qr/\.pro/);
+  my $musicfile = "/songbook/Media/$title.mp3";
+
+  if (-r "$documentRoot$musicfile") {
+    debug "Exists!";
+    
+    return $title;
+  } else {
+    debug "Could not find $documentRoot$musicfile";
+    
+    return undef;
+  } # if
+} # musicFileExists
+
+sub updateMusicpath ($$) {
+  my ($chopro, $song) = @_;
+
+  my $title = musicFileExists $song;
+  
+  # If there's no corresponding music file then do nothing
+  return unless $title;
+  
+  # If the .pro file already has musicpath then do nothing
+  if ($chopro =~ /\{musicpath:.*\}/) {
+    debug "$song already has musicpath";
+  } # if
+  
+  return if $chopro =~ /\{musicpath:.*\}/;
+
+  # Otherwise append the musicpath
+  my $songfile;
+  
+  open $songfile, '>>', $song
+    or undef $songfile;
+  
+  unless (defined $songfile) {
+    my $msg  = "Unable to open $song for append - $!<br>";
+       $msg .= "<br>Please notify <a href=\"mailto:adefaria\@gmail.com?subject=Please chmod 666 $song\">Andrew DeFaria</a> so this can be corrected.<br>";
+       $msg .= "<br>Thanks"; 
+    warning $msg;
+    
+    return;
+  } # unless
+
+  my $songbase = '/sdcard';
+  $songbase = '/storage/emulated/0';
+  
+  print $songfile "{musicpath:$songbase/SongBook/Media/$title.mp3}\n";
+  
+  close $songfile;
+
+  return;  
+} # updateMusicPath
+
+# Outputs the HTML code of the chordpro file in the first parameter
+sub chopro2html ($$) {
+  my ($chopro, $song) = @_;
+
+  $chopro =~ s/\</\&lt;/g; # replace < with &lt;
+  $chopro =~ s/\>/\&gt;/g; # replace > with &gt;
+  $chopro =~ s/\&/\&amp;/g; # replace & with &amp;
+
+  my $title;
+  
+  if(($chopro =~ /^{title:(.*)}/mi) || ($chopro =~ /^{t:(.*)}/mi)) {
+    $title = $1;
+  } else {
+    $title = "ChordPro song";
+  }
+  print <<END;
+<html>
+<head>
+<title>$title</title>
+<style type="text/css">
+body {
+  background-image: url('/songbook/background.jpg');
+  padding-left: 100px;
+}
+h1 {
+  text-align: center;
+  font-family: Arial, Helvetica;
+  font-size: 32pt;
+}
+h2 {
+  text-align: center;
+  font-family: Arial, Helvetica;
+  font-size: 24pt;
+}
+.lyrics, .lyrics_chorus {
+  font-size: 18pt;
+}
+.lyrics_tab, .lyrics_chorus_tab {
+  font-family: "Courier New", Courier;
+  font-size: 18pt;
+}
+.lyrics_chorus, .lyrics_chorus_tab, .chords_chorus, .chords_chorus_tab {
+  font-weight: bold;
+}
+.chords, .chords_chorus, .chords_tab, .chords_chorus_tab {
+  font-size: 18pt;
+  color: blue;
+  padding-right:
+  4pt;
+}
+.comment, .comment_italic {
+  color: #999;
+  font-size: 18pt;
+}
+.comment_box {
+  background-color: #ffbbaa;
+  text-align: center;
+}
+.comment_italic {
+  font-style: italic;
+}
+.comment_box {
+  border: solid;
+}
+</style>
+</head>
+<body>
+END
+
+      $title = musicFileExists $song;
+      
+      if ($title) {
+        updateMusicpath $chopro, $song;
+      } # if
+      
+      print << "END";
+<table border="0" width="100%">
+  <tbody>
+    <tr>
+      <td align="left"><a href="/songbook"><img src="/Icons/Home.png" alt="Home"></a></td>
+END
+      
+      if ($title) {
+        print <<"END";
+<td align="right">
+<audio controls autoplay>
+ <source src="http://defaria.com/songbook/Media/$title.mp3" type='audio/mp3'>
+ <p>Your user agent does not support the HTML5 Audio element.</p>
+</audio>
+</td>
+END
+      } # if
+print <<"END";
+    </tr>
+  </tbody>
+</table>
+END
+  my $mode = 0; # mode defines which class to use
+
+  #mode =           0           1              2             3
+  #       normal      chorus         normal+tab    chorus+tab
+  my @lClasses = ('lyrics', 'lyrics_chorus', 'lyrics_tab', 'lyrics_chorus_tab'  );
+  my @cClasses = ('chords', 'chords_chorus', 'chords_tab', 'chords_chorus_tab'  );
+
+  while($chopro ne '') {
+    $chopro =~ s/(.*)\n?//; # extract and remove first line
+    $_ = $1;
+    chomp;
+
+    if(/^#(.*)/) {                                # a line starting with # is a comment
+      print "<!--$1-->\n";                        # insert as HTML comment
+    } elsif(/{(.*)}/) {                           # this is a command
+      $_ = $1;
+      if(/^title:/i || /^t:/i) {                  # title
+        print "<H1>$'</H1>\n";
+      } elsif(/^subtitle:/i || /^st:/i) {         # subtitle
+        print "<H2>$'</H2>\n";
+      } elsif(/^start_of_chorus/i || /^soc/i) {   # start_of_chorus
+        $mode |= 1;
+      } elsif(/^end_of_chorus/i || /^eoc/i) {     # end_of_chorus
+        $mode &= ~1;
+      } elsif(/^comment:/i || /^c:/i) {           # comment
+        print "<span class=\"comment\">($')</span>\n";
+      } elsif(/^comment_italic:/i || /^ci:/i) {   # comment_italic
+        print "<span class=\"comment_italic\">($')</span>\n";
+      } elsif(/^comment_box:/i || /^cb:/i) {      # comment_box
+        print "<P class=\"comment_box\">$'</P>\n";
+      } elsif(/^start_of_tab/i || /^sot/i) {      # start_of_tab
+        $mode |= 2;
+      } elsif(/^end_of_tab/i || /^eot/i) {        # end_of_tab
+        $mode &= ~2;
+      } else {
+        print "<!--Unsupported command: $_-->\n";
+      }
+    } else { # this is a line with chords and lyrics
+      my(@chords,@lyrics);
+      @chords=("");
+      @lyrics=();
+      s/\s/\&nbsp;/g;         # replace spaces with hard spaces
+      while(s/(.*?)\[(.*?)\]//) {
+        push(@lyrics,$1);
+        push(@chords,$2 eq '\'|' ? '|' : $2);
+      }
+      push(@lyrics,$_);       # rest of line (after last chord) into @lyrics
+
+      if($lyrics[0] eq "") {  # line began with a chord
+        shift(@chords);       # remove first item
+        shift(@lyrics);       # (they are both empty)
+      }
+
+      if(@lyrics==0) {  # empty line?
+        print "<BR>\n";
+      } elsif(@lyrics==1 && $chords[0] eq "") { # line without chords
+        print "<DIV class=\"$lClasses[$mode]\">$lyrics[0]</DIV>\n";
+      } else {
+        print "<TABLE cellpadding=0 cellspacing=0>";
+        print "<TR>\n";
+        my($i);
+        for($i = 0; $i < @chords; $i++) {
+          print "<TD class=\"$cClasses[$mode]\">$chords[$i]</TD>";
+        }
+        print "</TR>\n<TR>\n";
+        for($i = 0; $i < @lyrics; $i++) {
+          print "<TD class=\"$lClasses[$mode]\">$lyrics[$i]</TD>";
+        }
+        print "</TR></TABLE>\n";
+      } # if
+    } # if
+  } # while
+} # chordpro2html
+
+## Main
+print header;
+
+unless ($infile) {
+       error "No chordpro parameter";
+} # unless
+
+open my $file, '<', $infile
+  or error "Unable to open file $infile - $!";
+
+{
+  local $/;
+  $chopro = <$file>;
+}
+
+chopro2html ($chopro, $infile);
+
+print end_html();
+
+exit;
+
+