Skip to main content
Headliner II
January 4, 2013

Fully managed C# library

Hi, I have been working on a simplified UPnP library which is aimed at Sonos that I want to make available to others.

You can find the source-code here:

https://github.com/jishi/Jishi.Intel.SonosUPnP

This is based upon Intels UPnP framework, which is opposed to the COM object that other attempts that I have found, based completely on managed code (no unmanaged code). This makes a huge difference if you are building anything multithreaded (WinForms, WPF etc).

I will try to put up some example code for people to look at.

Right now some of the features are pretty hacky since I'm still learning best practices, but hopefully it simplifies it a bit for someone.

This is built for .NET 4 Client Profile. The requirements is only .NET 4, previous versions doesn't need to exist.

Basic usage is this:

code:

// Create the main object
var discovery = new SonosDiscovery();

// Attach an event handler for topologychanged, this will be triggered as soon as it has found players (and when topology change)
discovery.TopologyChanged += TopologyChanged;

// This will start the UPnP-scanning, this is a manual call so that you are able to setup all event handlers first
discovery.StartScan();


If you want a more descriptive example, you can check out my Dashboard project:

https://github.com/jishi/Panagora.Sonos.Dashboard/blob/master/Panagora.Sonos.Dashboard/MainWindow.xaml.cs

Is a really simple fullscreen app that shows currently playing song for the most relevant player (Biggest group, longest queue).

Any suggestions and feedback is appreciated. As of today it only supports the following features:

Zone discovery
Player status notifications
Play/Pause
Enqueue
Seek (to queue position)
SetAVTransportURI
    This topic has been closed for further comments. You can use the search bar to find a similar topic, or create a new one by clicking Create Topic at the top of the page.

    26 replies

    Lyricist II
    July 16, 2014
    Hi JISHI,

    I have just bought my first Sonos device, and I'm planning to use your library with my Netduino to display the current track info on a small screen/LCD.

    My issue is I really just need the current track playing in each zone, but that does not seem to be implemented in your library.

    SonosPlayer.cs (line 190):
    code:
            public SonosTrack CurrentTrack
    {
    get { throw new NotImplementedException(); }
    }


    I would like to be able to get the info from the queue, but just for the current track.

    Info from queue:
    code:
    sonosZone.Coordinator.GetQueue().FirstOrDefault().DIDL.Title;


    Can you hint me in the right direction?
    As I'm a hobby programmer with no UPnP experience, I'm in a bit over my head 🙂
    jishiAuthor
    Headliner II
    July 16, 2014
    Hi JISHI,

    I have just bought my first Sonos device, and I'm planning to use your library with my Netduino to display the current track info on a small screen/LCD.

    My issue is I really just need the current track playing in each zone, but that does not seem to be implemented in your library.

    SonosPlayer.cs (line 190):
    code:
            public SonosTrack CurrentTrack
    {
    get { throw new NotImplementedException(); }
    }


    I would like to be able to get the info from the queue, but just for the current track.

    Info from queue:
    code:
    sonosZone.Coordinator.GetQueue().FirstOrDefault().DIDL.Title;


    Can you hint me in the right direction?
    As I'm a hobby programmer with no UPnP experience, I'm in a bit over my head :)


    Hi, interesting hardware. Are you saying that this code actually runs on netmf? That's a bit surprising.

    I do actually have support for the CurrentTrack, you are just looking in the wrong place. Check the CurrentState property, which is of the type PlayerState, that object will hold info regarding CurrentTrack.

    In order to update your display, you can also subscribe to the StateChanged event of the player.

    I have been planning on breaking out the barebone UPnP-project from StreamToSonos into a separate project, but just haven't gotten around to it. It would be a lot more lightweight. However, netmf doesn't have the regular SOAP libraries available, so it would need to be rewritten for netmf. Are you up for that? 🙂
    Lyricist II
    July 16, 2014
    Hi, interesting hardware. Are you saying that this code actually runs on netmf? That's a bit surprising.
    I haven't tried it yet, I'm just testing it in a console application. My Netduino is currently occupied elsewhere 🙂 But I will test it soon.


    I do actually have support for the CurrentTrack, you are just looking in the wrong place. Check the CurrentState property, which is of the type PlayerState, that object will hold info regarding CurrentTrack.

    When I do that it is always "null". Am I missing something?

    My Program.cs:
    code:
    using Jishi.Intel.SonosUPnP;
    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace SonosTest
    {
    class Program
    {
    static void Main(string[] args)
    {
    SonosDiscovery disc = new SonosDiscovery();

    disc.StartScan();
    Thread.Sleep(5000);

    Debug.Print("*** PLAYERS ***");

    foreach (SonosPlayer sp in disc.Players)
    {
    Debug.Print("Name: " + sp.Name);
    Debug.Print("Track: " + sp.CurrentState.CurrentTrack);
    }

    Console.ReadKey();
    }
    }
    }


    Output every time I run it:
    code:
    *** PLAYERS ***
    Name: Køkken
    Track:



    In order to update your display, you can also subscribe to the StateChanged event of the player.

    Great input!
    I think I will update the play time every second or so in my final application. For now everything is just proof of concept.


    I have been planning on breaking out the barebone UPnP-project from StreamToSonos into a separate project, but just haven't gotten around to it. It would be a lot more lightweight. However, netmf doesn't have the regular SOAP libraries available, so it would need to be rewritten for netmf. Are you up for that? :)

    I would love to have that barebone project to fiddle with :)
    As you might have seen from my questions so far I'm not that experienced, and I'm not sure I'm the right person for a rewrite.
    But I will most certainly give it a try, and if I'm lucky someone more experienced over at the Netduino forums will see the need for this to happen 🙂
    jishiAuthor
    Headliner II
    July 16, 2014
    I haven't tried it yet, I'm just testing it in a console application. My Netduino is currently occupied elsewhere 🙂 But I will test it soon.


    When I do that it is always "null". Am I missing something?

    My Program.cs:
    code:
    using Jishi.Intel.SonosUPnP;
    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace SonosTest
    {
    class Program
    {
    static void Main(string[] args)
    {
    SonosDiscovery disc = new SonosDiscovery();

    disc.StartScan();
    Thread.Sleep(5000);

    Debug.Print("*** PLAYERS ***");

    foreach (SonosPlayer sp in disc.Players)
    {
    Debug.Print("Name: " + sp.Name);
    Debug.Print("Track: " + sp.CurrentState.CurrentTrack);
    }

    Console.ReadKey();
    }
    }
    }


    Output every time I run it:
    code:
    *** PLAYERS ***
    Name: Køkken
    Track:



    Great input!
    I think I will update the play time every second or so in my final application. For now everything is just proof of concept.


    I would love to have that barebone project to fiddle with :)
    As you might have seen from my questions so far I'm not that experienced, and I'm not sure I'm the right person for a rewrite.
    But I will most certainly give it a try, and if I'm lucky someone more experienced over at the Netduino forums will see the need for this to happen :)


    Sorry, my bad. Was a long time ago since I used this. I looked at my old Dashboard code, and apparently, I did this:

    code:

    var state = player.CurrentState;
    if (state == null || state.CurrentTrackMetaData == null) return;
    SonosDIDL didlData = SonosDIDL.Parse(state.CurrentTrackMetaData).First();


    didlData will have .Artist, .Title and stuff like that. Hopefully that helps.
    Lyricist II
    July 16, 2014
    Sorry, my bad. Was a long time ago since I used this. I looked at my old Dashboard code, and apparently, I did this:

    code:

    var state = player.CurrentState;
    if (state == null || state.CurrentTrackMetaData == null) return;
    SonosDIDL didlData = SonosDIDL.Parse(state.CurrentTrackMetaData).First();


    didlData will have .Artist, .Title and stuff like that. Hopefully that helps.

    It works great now!
    Thank you for all the help :)

    Please let me know when you have taken the bare bones out of your project, and I will dig into it.
    Lyricist I
    October 3, 2017
    I know it has been a while, but the UPNP lib is an old dll. Is it opensource? or is there an updated version or even better; a nuget package? To make it .net standard compat or to be able to use it in an uwp project.