Sheet Music Displays

I recently had an inquiry about creating an app to transpose and then display a MusicXML file on a mobile. The client was interested in it using the Open Sheet Music Display library which is a JavaScript library created using TypeScript.
http://opensheetmusicdisplay.org

Since I have a background in music composition and arranging the music part was trivial. I found MusicXML fairly straightforward too so the transposition part was easy.

What was a headache was getting the part XML to display once it had been transposed. Since the interest was in a mobile version I decided to develop with Xamarin and C# which I am very familiar with. The application uses the Xamarin FilePicker plugin to select a file from an Android folder, iCloud on iOS and the Documents folder on Windows 10 UWP. Though the picker is set for .xml and .musicxml file types for Android and UWP I could not find proper iOS UTType for those types so it just displays all the files available.

Once the file is selected it is read into memory as a string.

1
2
3
var stream = pickedFile.GetStream();
StreamReader streamReader = new StreamReader(stream);
string xml = await streamReader.ReadToEndAsync();

Then the XML is loaded into a new JavaScript XmlDocument:

1
2
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

Next the HTML file used for displaying the sheet music part is loaded into a Xamarin Forms Webview:

1
2
var src = LoadHTMLFileFromResource();
webview.Source = src;

The HTML file contains the short piece of JavaScript which will render the music:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<script src="opensheetmusicdisplay.min.js"></script>
<div id="osmdCanvas"></div>
<script type="text/javascript">
function render_osmd() {
var ret = "yes";
var osmd = new opensheetmusicdisplay.OpenSheetMusicDisplay("osmdCanvas");
if (osmd == null)
ret = "no";
else {
osmd.load(str).then(
function () {
osmd.render();
}
)
}
return ret;
}
</script>
</body>

When the HTML is loaded we must wait for it to be displayed. Unfortunately the Xamarin Webview does not let us know (to my knowledge) that the HTML has been loaded so the JavaScript can be invoked. So I added a 3 second thread delay which takes care of that problem:

1
2
3
4
5
6
7
8
9
10
await Task.Delay(3000); // let the page load -- needed longer for the x64
try
{
var js = "var str = '" + outerxml + "'; render_osmd(); ";
string result = await webview.EvaluateJavaScriptAsync(js);
if (result.Contains("yes"))
Debug.WriteLine("score rendered.");
else
Debug.WriteLine("score not rendered.");
} catch(Exception e)

Hopefully the part is then displayed in the webview. Much of this technique is described in the Xamarin Tutorial “Working With Webviews”:
http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/webview

Currently the Open Sheet Music Library is still beta. There were also two other open source sheet music display libraries, one in C++ and one in C# that was not complete for use in Xamarin.

Example source code:
https://github.com/brianjtools/xamosmd