Showing posts with label silverlight. Show all posts
Showing posts with label silverlight. Show all posts

Friday, 9 January 2015

Musical Symbols in WPF/Silverlight

I had some interest over this week looking at being able to show some musical symbols in a Silverlight / WPF application and had expected this to be a relatively simple thing but ended up chasing down quite a lot of little dark alleys until I found a couple of good answers. So, with my New Year's resolution of posting a lot more of these little thoughts, I'll see how far I can get describing the journey.

For starters I thought this would be simple. Everything is now unicode, right, they have Japanese, Korean, Maths notation and other symbols, there must be a code-page for musical notation. Yes! and well, no! If you go to the Unicode specification, there's a whole set of musical symbols defined. http://www.unicode.org/charts/PDF/U1D100.pdf Next bit of searching was to find a suitable font that had these symbols included. I finally found 'Symbola.ttf' which included it, but probably not my final font. Enough to try though. I dutifully installed this and then wanted to have a look at what symbols were there. The big problem is that these are in UTF-32. Take a look at charmap (on Windows), this only extends up to UTF-16. So I couldn't see them. Undeterred and still expecting this not to be a problem I had a long fight with Silverlight to try to get it to show this unicode encoding, finally giving up when I realised it only extended to UTF-16 (basically this means you can only go as far as \UFFFF or  as otherwise written. This is a problem, as the musical notation is all above that, with the treble-clef at U+1d120. Hmmpf.

So, where could I go then? I did have a poke around in some other fonts, and hoped that they would have musical notation in the private areas. More of which later, but at this point I didn't find quite what I was looking for and so, I'll continue my journey as it uncovered some other interesting things on the way to what I got to solve my problem.

Next step, I took a look at EasyABC, as I had posted previously I've been using this on my Mac and am really liking it, so I took a look at the package and the python scripts. First thing to note that the actual musical rendering is made by abc2ps, an excellent little project written in C. The musical format in this case was not quite what I was looking for (need to come back and detail a bit more when I get a chance).

After that, as I've been playing with it as well, I took a look at VexFlow. Now, this was interesting, digging down in the source on github, they have the file gonville.js  that appears to have some interesting path-like font descriptions. In trying to understand this I uncovered quite a long and interesting thread on pluggable fonts for VexFlow that I must go back and read in more detail.

The thread lead me on to SMuFL - Standard Music Font Layout (http://www.smufl.org/) - now I was getting somewhere! I had an interesting read around this and found the Bravura.otf OpenText format font. This revealed a number of interesting things - firstly it is available under the SIL Open Font license and secondly it implements all of the specified unicode musical symbol range U+1d100 - U+1d1dd, however these are mapped into the unicode Basic Multilingual Plane in the standard private area at U+e000 so fall within the scope of UTF-16 and hopefully usable by Silverlight! Now we're sucking diesel!

Next step I returned to the previous bashing of my head against a Silverlight wall and with a bit more googling, finally got the font in and showing a treble-clef. There's a quite a few false trails out there and the Silverlight route throws up some slightly different challenges to a standard WPF app, but the best advice was from Apres Pro Silverlight 5 in C# here on Font Embedding  It's important to follow the note on using the # to show the name of the font, not just the file containing the font.

My code directly in WPF finally looked like this...

<TextBlock Name="trebleclef" FontSize="52" FontFamily="/AgScore;component/Fonts/Bravura.otf#Bravura">&#xf472;</TextBlock>

In this case I have the Bravura.otf font file in a sub-directory called Fonts and the properties have Build Action set to Resource and Copy to Output set to Copy if newer. The name of my application is 'AgScore'. Nice!

Now, there's an interesting little note in the Apres book that says if you can't get this working for you in your app, then turn the fonts into graphics and use the Path notation. Nice! To backtrack a little. I had tried this unsuccessfully earlier when I took one of the lines of the gonville.js file path-like notation and had converted that into the path mini-language. It sort of worked, but I didn't have the energy to follow that through when I thought there should be a simpler answer and fond the SMuFL links. The little note in the book points to a link hich details how to get the text into a path string from code. I didn't want to fight this from Silverlight itself and the approach shown in the link uses a backend service by the looks of it, so I decided to bash at this directly in a C# application and get the path information to see how it worked. Here's how it looks:


    // Set up the Culture
    string strCulture = "en-us";

    System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo(strCulture);

    // Set up the flow direction
    System.Windows.FlowDirection fd = FlowDirection.LeftToRight;

    // Set up the font family from the parameter
    FontFamily ff = new FontFamily("D:\\Users\\gbcollia\\Documents\\Visual Studio 2010\\Projects\\AgScore\\AgScore\\Fonts\\Bravura.otf#Bravura");

    // Create the new typeface
    System.Windows.Media.Typeface tf = new System.Windows.Media.Typeface(ff,  
                                                                        FontStyles.Normal, 
                                                                        FontWeights.Normal 
                                                                        FontStretches.Normal);

    // Create a formatted text object from the text,

    // culture, flowdirection, typeface, size and black

    FormattedText t = new FormattedText("\uf472", ci, fd, tf, 20, System.Windows.Media.Brushes.Black);

    // Build a Geometry out of this
    Geometry g = t.BuildGeometry(new Point(0, 0));

    // Get the Path info from the geometry
    PathGeometry p = g.GetFlattenedPathGeometry();

    // Get the path data info
    string pathdata = p.ToString();

  
I then unashamedly  pasted this path data into a path in SIlverlight to see how that looked as follows:

<Path  Stroke="Black" Fill="Black" StrokeThickness="0.1" Height="80" Width="30" Margin="0" Data="F1M8.81999969482422,38.7800025939941L9.28749942779541,41.7350006103516 9.67999935150146,44.3600006103516 11.2150001525879,43.2925033569336 11.6999998092651,41.6400032043457 11.6999998092651,41.4200019836426 11.4496870040894,40.2987518310547 10.852499961853,39.4700012207031 8.81999969482422,38.7800025939941z M6.83999967575073,33.4400024414063L4.96499967575073,34.8790626525879 3.37499976158142,36.4025001525879 2.27250003814697,38.1846885681152 1.85999989509583,40.4000015258789 1.85999989509583,40.560001373291 2.47249984741211,42.6812515258789 3.86499977111816,43.9550018310547 5.6399998664856,44.5762519836426 7.39999961853027,44.7400016784668 8.69999980926514,44.5800018310547 7.67999982833862,38.8800010681152 6.2024998664856,39.4775009155273 5.70843744277954,40.080940246582 5.51999998092651,40.9600028991699 5.51999998092651,41.1599998474121 5.94499969482422,42.2800025939941 6.6399998664856,42.9200019836426 6.94000005722046,43.2800025939941 6.69999980926514,43.4400024414063 6.27999973297119,43.3600006103516 4.96999979019165,42.4300003051758 4.1399998664856,40.7200012207031 4.01999998092651,39.8400001525879 4.26656246185303,38.5371894836426 4.94250011444092,37.3675003051758 5.95218753814697,36.4340629577637 7.19999980926514,35.8400001525879 6.83999967575073,33.4400024414063z M9.17999935150146,22.7200012207031L8.14781188964844,23.1481266021729 7.41749954223633,24.1650009155273 6.83999967575073,27.0800018310547 6.87999963760376,27.8000030517578 6.92999982833862,28.1550025939941 7.03999996185303,28.7800025939941 8.40062522888184,27.6990642547607 9.34500026702881,26.7775020599365 10.2399997711182,24.7600021362305 10.2799997329712,24.3200016021729 9.97749996185303,23.1150016784668 9.17999935150146,22.7200012207031z M9.03999996185303,18.8200016021729L9.49499988555908,19.1025009155273 9.96812534332275,19.6721897125244 10.5199995040894,20.7200012207031 11.1599998474121,22.6350021362305 11.3800001144409,24.5200023651123 11.188437461853,26.9756278991699 10.5675001144409,29.1500015258789 9.4478120803833,31.1293754577637 7.75999975204468,33 8.01000022888184,34.2675018310547 8.26000022888184,35.7000007629395 8.51999950408936,35.6600036621094 8.73999977111816,35.6600036621094 10.5046873092651,36.0125045776367 11.9224996566772,36.9800033569336 12.8940620422363,38.4275016784668 13.3199996948242,40.2200012207031 13.3199996948242,40.5 13.0853118896484,42.0806274414063 12.4025001525879,43.4550018310547 11.3034372329712,44.5668754577637 9.81999969482422,45.3600006103516 10.1674995422363,47.5149993896484 10.2784376144409,48.1106262207031 10.3199996948242,48.3199996948242 10.4399995803833,49.7000007629395 10.071249961853,51.6768760681152 9.15499973297119,52.9900016784668 7.97624969482422,53.7331275939941 6.81999969482422,54 6.35999965667725,54.0200004577637 4.38562488555908,53.6465644836426 3.23999977111816,52.7425003051758 2.70937490463257,51.6321868896484 2.57999968528748,50.6399993896484 2.61249971389771,50.1400032043457 2.65999960899353,49.9400024414063 3.48749995231628,48.3775024414063 5.07999992370605,47.7600021362305 5.98000001907349,47.9600028991699 6.86999988555908,48.7550010681152 7.15999984741211,49.9400024414063 7.15999984741211,50.0800018310547 6.97531223297119,50.8746910095215 6.50749969482422,51.4725036621094 5.23999977111816,52.1600036621094 4.73999977111816,52.2800025939941 4.55999994277954,52.4400024414063 4.73999977111816,52.6600036621094 6.39999961853027,53.060001373291 6.77999973297119,53.060001373291 7.296875,53.0031280517578 8.19999980926514,52.6350021362305 9.05812454223633,51.6593780517578 9.4399995803833,49.7800025939941 9.31999969482422,48.4200019836426 8.85999965667725,45.6400032043457 8.76000022888184,45.6400032043457 7.39999961853027,45.7200012207031 4.93343734741211,45.4071884155273 2.63749980926514,44.3575019836426 0.877812504768372,42.4040641784668 0.0200001019984484,39.3800010681152 1.21159985155828E-07,38.7800025939941 0.558125019073486,36.0762519836426 2.00499987602234,33.6650009155273 3.9993748664856,31.5012512207031 6.19999980926514,29.5400009155273 5.96000003814697,28.2800025939941 5.81999969482422,26.2600021362305 6.05593729019165,23.6968765258789 6.71749973297119,21.5050010681152 7.73531246185303,19.8306274414063 9.03999996185303,18.8200016021729z"/>


Very nice. I had a treble-clef, although not quite how I wanted it. So, after a quick, lazy google, I scaled using this suggestion (http://stackoverflow.com/questions/5109058/wpf-the-right-way-to-scale-a-path). Omitting the path data for clarity:

        <Path  Stroke="Black" Fill="Black" StrokeThickness="0.1" Data="..."
               Height="80" Width="30" Margin="0" RenderTransformOrigin="0, 0">
            <Path.RenderTransform>
                <ScaleTransform ScaleX="4.2" ScaleY="4.2"/>
            </Path.RenderTransform>
        </Path>

This pretty much gets me what I wanted. Now, I just need to do a simple routine to export all of the fonts I need into paths, put them into a separate XML file (or similar) and I can use them in Silverlight programmatically to render some nice graphics.


Hope this is of use to someone else struggling with the same questions. 

Wednesday, 29 October 2014

Simpler Silverlight/C# syntax for async web service calls using delegates

So, I've been using Web-Service calls in Silverlight for a number of years now in a bunch of different applications with the cumbersome async BeginGetResponse, callback, EndGetResponse syntax. It's all been working great, I happily have a template for this and can bash any new service integrations pretty quickly and has not been getting in the way.

For a simple Get request they look something like this:


public string server = "123.123.123.123";


public void GetExample()
{
    String url = "http://" + server + "/getexample";

    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

        IAsyncResult result = null;

        result = request.BeginGetResponse(GetExampleCallback, request);
    }
    catch (Exception)
    {
    }
}

void GetExampleCallback(IAsyncResult ar)
{ 
    var request = ar.AsyncState as HttpWebRequest;
    var response = request.EndGetResponse(ar) as HttpWebResponse;

    using (var reader = new StreamReader(response.GetResponseStream()))
    {
        string result = reader.ReadToEnd();

        // now do something with this
    }
}

Which is all good and I usually have some additional code here to callback to a delegate which can then do something, such as display the result asynchronously with the usual fun and games of getting this back onto the GUI thread using a BeginInvoke Dispatch.

Great. It then gets a little more complicated when you want to make a post request and have to push the XML parameters in another asynch BeginGetRequestStream function which means you're getting callback after callback. Easy enough, these can be bundled into a class for each WebService function and can use some templating to reduce the effort, but it's still pretty tedious. I've stuck with it because it works, I have a pattern and usually it's not too much trouble and once done means I can focus on the other interesting bits of the application.

Just this week though I needed to make a new little application and having some brain-space to look at this again and thinking Swift closures I thought I'd explore a bit how to get rid of the callbacks explicitly in the calls and see if this could be made into a single function. Sort-of and there are pros and cons.

What I came up with looks like this:

using System.Threading.Tasks;

public string server = "123.123.123.123";


public void GetExample2()
{
    String url = "http://" + server + "/getexample2";


    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

        IAsyncResult result = null;
        ManualResetEvent mre = new ManualResetEvent(false);

        result = request.BeginGetResponse((cb) =>
        {
            // Callback
            using (var response = request.EndGetResponse(cb) as HttpWebResponse)
            {
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                }
            }

            mre.Set();

        }, request);


        mre.WaitOne();
    }
    catch (Exception)
    {
    }
}


In this case the callback has been put in as an anonymous delegate so the code can be written in the same function. Now what is all the ManualResetEvent stuff about? Basically this is to handle the aynchronous nature. If you run this in the debugger you can see the BeginGetResponse call being made and then jumping down to mre.WaitOne() which is the normal thread flow of the operation. You can then see the debugger jump back up to the callback. The mre.Set then sets the flow to continue in the main thread once the callback has finished.

So, pros and cons.

The big pro is that the whole operation is now contained in a single function statement and local variables can be used to return the result. You can either make this synchronous now (as the synchronicity has been put into the call with the ManualResetEvent) or callback via a delegate (recommended) with the result.

The con is that there are seemingly multiple code execution entries in a single statement. Remember all those gotos and horrible code years ago. Well, lots of coding best practice is to make code more readable and the execution paths clearer and more understandable. [See also later note on calling from the GUI thread]

The nub of the question is if this is easier to read and understand and means there will be fewer problems. I kind of think so as once the template/pattern is established it's much easier to put together and therefore for me less prone to errors.

The big advantage now is if you need to do a Post, it looks sort of like this:


public void PostExample()
{
    String url = "http://" + server + "/postexample";


    try
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.AllowReadStreamBuffering = false;
        request.Method = "POST";
        request.ContentType = "text/xml";


        IAsyncResult result = null;
        ManualResetEvent mre = new ManualResetEvent(false);


        result = request.BeginGetRequestStream((ac) =>
        {
            // post request callback
            using (Stream stream = request.EndGetRequestStream(ac))
            {

                StreamWriter writer = new StreamWriter(stream);


                string post = "";

                post += "<?xml version='1.0' encoding='UTF-8'?>";
                post += "<somexml/>";

                writer.Write(post);

                writer.Flush();
                writer.Close();
            }

            mre.Set();

        }, null);

        mre.WaitOne();
        mre = new ManualResetEvent(false);

        string reply = "";

        result = request.BeginGetResponse((cb) =>
        {
            // callback response
            var response = request.EndGetResponse(cb) as HttpWebResponse;

            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                reply = reader.ReadToEnd();
            }

            mre.Set();

        }, request);

        // this needs to stay in for some strange reason
        Thread.Sleep(100);

        mre.WaitOne();
    }
    catch (Exception)
    {
    }
}

Which is pretty great.

Now, the additional funny. I don't like the Sleep at the end, but however I tried to work this out, I could not get things to work and the last wait just waited on for ever, so pragmatically it is working for me but is an ugly little hack.

Second thing to note with this method is that these functions cannot be called from the GUI thread directly as the callback in BeginGetResponse never comes back. That caused me a lot of headaches until I found the result. In the case of my application this is not a problem as all the service calls are running from a separate thread and updating the GUI. Still, it's messy. There are ways around this similar to the Dispatch back the other way, but it's not completely clean.

I did mess around with the new C# async keyword and using the task framework but the code really looked ugly to my eyes. Maybe a little more work on that and another post in the future.

Friday, 17 October 2014

Silverlight Multi-Select User Control

So back to some Silverlight fun. I had a requirement for some applications I was putting together to have a multi-select drop-down that allowed typing in and selection from a list of available values. I'm sure there was some code around but I took a quick look and this didn't jump out at me immediately so I had a bit of an evening code. Here's the results. Please do take yourself and improve, please drop me a comment on this blog if you find it useful or use it for anything.

There's a demo below... try typing into the box. The version used below does not allow duplicates. This is an option in the user control.


The code files are available below:
The code is a little klunky in places and could certainly be improved. I'll try to get round to that when I have some spare time. However, it met the need that I had at the time. 

There are a number of areas for improvement, putting in disable functionality and allowing different colours for the selected items. 

There are a couple of little tricks that are worth calling out...

In a couple of places I needed to send a message to a control to get it to have a visual interaction. The easiest way I found for doing this was to use a lambda to drop it onto the dispatcher:

Dispatcher.BeginInvoke(() => options.Visibility = Visibility.Collapsed);

These are paths for the right and down arrow:

<Path x:Name="arrowright" VerticalAlignment="Center" Margin="0" Stroke="Gray" 
      Data="M2,8 L6,4 L2,0"  StrokeThickness="2"/>
<Path x:Name="arrowdown" VerticalAlignment="Center" Margin="0" Stroke="Gray" 
      Data="M8,0 L4,4 L0,0"  StrokeThickness="2" Visibility="Collapsed"/>

And this is the path for the cross symbol used in the buttons:

<Path VerticalAlignment="Center" Margin="3" Stroke="Gray" Data="M0,0 L8,8 M8,0 L0,8"  StrokeThickness="2"/>