Last.Fm Radio Stream Player Gadget 0.5 Released!

July 25, 2008 22:36 by Geert van der Cruijsen

Last week my mailbox was flooded by mails of people who were telling me my Windows Vista Sidebar gadget to play Last.fm radio was broken.

I tested it myself and concluded that this was indeed the case. Last.fm changed their website last week and my guess is that they also changed their streaming service.

After a full night of debugging I found out what was the problem and I fixed it in a new version which can be now downloaded from the download area.

If you are interested in what was changed read on. The change was fairly simple, the protocol uses 2 handshakes to connect to the service. The first handshake is to connect to the scrobbling service. The second handshake is used to connect to the streaming service. Before last week requesting the mp3 stream was done by sending the sessionid of the first handshake. Now... it seems you have to send the sessionid you get with the second handshake. It took some time to figure this out but now everything seems to work fine again.

Protocol example:

Handshake 1 request:

http://ws.audioscrobbler.com/radio/handshake.php?version=1.4.2.58376&platform=win32&platformversion=Windows%20Vista&username=geertvdcruijsen&passwordmd5=
4d9309866b98863c3c3336e50392831b&language=en&player=winamp

Handshake 1 response from last.fm:

session=bbe5e763d1e1deb988595cecf1c21e9d stream_url=http://87.117.229.85:80/last.mp3?Session=bbe5e763d1e1deb988595cecf1c21e9d subscriber=0 framehack=0base_url=ws.audioscrobbler.com base_path=/radio info_message= fingerprint_upload_url=http://ws.audioscrobbler.com/fingerprint/upload.php permit_bootstrap=0

Handshake 2 request:

http://post.audioscrobbler.com/?hs=true&p=1.2&c=tst&v=1.3.1.1&u=geertvdcruijsen
&t=1217017120&a=2a060e72c7aae132e8fad06b741be806

Handshake 2 response from last.fm:

OK 7e5b82460d2a45e382b81c437ae6a87a http://post.audioscrobbler.com:80/np_1.2 http://87.117.229.205:80/protocol_1.2

Tune to the right radio channel:

http://ws.audioscrobbler.com/radio/adjust.php?session=bbe5e763d1e1deb988595cecf1c21e9d&url=lastfm://artist/muse

Response to channel change request from last.fm:

response=OK url=lastfm://artist/muse stationname= Muse’s Similar Artists discovery=true

Request metadata of stream:

http://ws.audioscrobbler.com/radio/xspf.php?sk=bbe5e763d1e1deb988595cecf1c21e9d
&discovery=0&desktop=1.3.1.1&time=1217017120321

I was happy to receive the mails of complaints because this is proof people are actually using my gadget :) Hopefully all problems are fixed now so happy listening!

Geert van der Cruijsen


Comments (5)

DevDays 2008 Amsterdam

May 22, 2008 21:22 by Geert van der Cruijsen

I just came home from Amsterdam after a long day of listening to presentations on the DevDays 2008 in Amsterdam. It was a long day since I live "below the rivers" as people in Holland like to call it and its a pretty long drive to Amsterdam so I had to get up early.

 

I stepped into my car at 6:00 in the morning to be in Amsterdam at 9:00. In the Netherlands traffic is such a joke that it isn't possible for me to be in Amsterdam at 9:00 because when i leave at 6:00 i'm there at 8:00 and when i go a bit later i'm already late for the first session because of all the traffic jams. So around 8 o'clock I entered the Rai and helped a bit at the Avanade stand to help kill the time before the first session.

At 9:00 the keynote started and David Platt told us Why software sucks. To wrap his story up he told us that developers write software that doesn't function well because it doesn't do it's job like it is supposed to. We build to many "cool" features that nobody uses etc. His principle of software development is: KNOW THY USER FOR HE IS NOT THEE. All in all it was a interesting presentation about something everybody already knows or should know but still a lots of developers keep doing a bad job at it. If you want to know more about this subject check out David's website or read his book called "Why Software Sucks"

The Second session I visited was an "Introduction to Silverlight 2" by Daniel Moth. He gave us a good overview of what silverlight 2 is going to do at release and what it can already do know. Since I already played around with the silverlight 2 beta I already knew some stuff he told and showed us in the demo's but it was nice to see all aspects of what silverlight 2 is capable off. The demo's he showed us were a Hello World example, a XAML introduction, The bridge between html/javascript and Silverlight 2, Networking capabilities in Silverlight and at the end he showed us how to acces the local file system. On Daniel's blog is a nice summary of his presentation at DevDays so if you are interested in what Silverlight 2 can do check it out at http://www.danielmoth.com/Blog/2008/05/my-silverlight-session.html

After enjoying a nice lunch in the sun I visited a presentation about "Building Rich Internet Applications for WSS 3.0 and MOSS 2007". This presentation was done by Patrick Tisseghem. Patrick is a SharePoint MVP and showed us to possibilities of using Silverlight in SharePoint. Before I went to the presentation I thought that this could be very useful because in my daily work I have to code against/in SharePoint quite a bit. The Silverlight support Patrick showed us didn't came as anything new to me since Daniel Moth already showed us in his presentation that in Silverlight 2.0 you can acces webservices via the client side code. Patrick showed us how to use the standard webservices that SharePoint exposes and explained to us that we can build our own services to communicate with SharePoint. Since on my projects I already build several webservices on SharePoint this didn't feel like anything new to me and it was mostly more of an introduction to Silverlight 2.0 that that it had something to do with SharePoint. Patrick also showed us what it takes to use Silverlight in SharePoint  but the steps you should take were a bit to specific in my opinion and you'll have to look them up anyway as soon as you want to try it out yourself :)

The next session was by Ingo Rammer and was about "Combining WCF and WF in the 3.5 framework to build durable services". I really liked this presentation since I work with WCF quite a lot on my projects and it was nice to see how to build workflow services using WF and WCF. Ingo showed us that in the 3.0 framework it wasn't possible to build durable services and if you use duplex services things can go wrong when one of your services restart for some reason. He build a durable service that was serialized when the service shuts down and when it starts again it can be deserialized again so the service that is sending a response wont get any errors because the service has restarted.

The last session of the day was by Peter Himschoot and was about how to use REST and JSON in WCF. Peter showed us that it is really easy to use REST instead of soap to communicate to WCF services but I still don't think that I'm going to use this very often since REST is specially build to be reached by everyone and most services I build require security and that something that's lacking in REST. Rest isn't supposed to be used for those services and Peter had a nice line for this: REST = REACH. meaning that if you have to communicate with software that's build using older languages you probably use REST because most languages support the HTTP protocol.

All in all it was a nice day and I enjoyed myself and learned lots of new stuff. People who are going again tomorrow enjoy! I won't be going tomorrow since I have to work on my project half a day before I go away for the weekend to Terschelling with my colleagues of Avanade Netherlands to have fun and drink some beers.

Geert van der Cruijsen


Comments (0)

Display Picture Metadata in your Silverlight 2.0 Deepzoom Application

April 30, 2008 17:11 by Geert van der Cruijsen

As i promised 2 days ago here's my post about how to display metadata of sub images in your Silverlight Deepzoom Application. I already typed this post yesterday but because of a stupid mistake i lost my post and now I have to type it again :( (but I think I'll make it a bit shorter)

To start building your Silverlight 2.0 deepzoom application download Deepzoom Composer from Microsoft here. This tool works quite easy. just add some images in the "import" mode then drag them on your screen in the "compose" mode and then export your deepzoom Project.

If you want to be able to identify the different sub images in your Multiscaleimage object check the "Create Collection" checkbox.

deepzoomComposerCollection

After exporting this will be the result:

deepzoomexport

Now to load up this collection of pictures into your own project take a look at this weblog, there is a really good explanation on which steps to take and after you did all those steps i'll explain how to show metada of the different subimages in the deepzoom application.

So if you are at this point you should have your own working deepzoom application and you want to add picture metadata to your project. If not go back to this weblog or try one of these.

The only way of identifying the different sub images in the big multiscaleimage is by the Z-Order of the different images. So how do you know which image has what Z-Order you ask? thats where the generated SparseImageSceneGraph.xml comes in which was generated by the Deepzoom Composer.

<SceneNode

  <FileName> P1000558.JPG</FileName

  <x>0,235460826165879</x>

  <y>0,00108692916410255</y

  <Width>0,218281177677285</Width>

  <Height>0,144923888547009</Height

  <ZOrder>2</ZOrder>

  <Description>Uitzicht van hotelkamer</Description>

</SceneNode>

 

As you can see i added my own Description element to every SceneNode in the generated xml so we can use it in our project. We'll use this xml file to query the ZOrder of the subimage and get the description as a result with the use of Linq.

To do this we'll first have to open the xml file in our code behind page from the page.xaml.cs.

deepZoomObject.Loaded += delegate(object sender, RoutedEventArgs e)

{

    _xmlImageMetadata = XDocument.Load("SparseImageSceneGraph.xml");

};

 

After that we'll add code to display the metadata when the mouse moves over a sub image in the multiscaleimage.

deepZoomObject.MouseMove += delegate(object sender, MouseEventArgs e)

{

    if (mouseButtonPressed) 

    {

        mouseIsDragging = true

    }

    else 

    {

        ImageName.Text = GetMetadata(e.GetPosition(deepZoomObject)); 

    }

    lastMousePos = e.GetPosition(deepZoomObject);

};

 

Then we add the function GetMetadata which queries the xml file and gets the description from it.

private string GetMetadata(Point point)

{

    Point p = deepZoomObject.ElementToLogicalPoint(point); 

    int subImageIndex = SubImageHitTest(p);

    if (subImageIndex >= 0) 

    {

        var q = from c in _xmlImageMetadata.Elements("SceneGraph").Elements("SceneNode"

        where ((string)c.Element("ZOrder")) == (subImageIndex + 1).ToString()

        select (string)c.Element("Description"); 

        if (q != null)

       

            return q.Single();

       

        else

            return ""

    }

    else 

        return "";

}

 

This function uses the function SubImageHitTest which I copied from this weblog:

int SubImageHitTest(Point p)

{

    for (int i = 0; i < deepZoomObject.SubImages.Count; i++) 

    {

        Rect subImageRect = GetSubImageRect(i); 

        if (subImageRect.Contains(p))           

            return i; 

    } return -1;

}

 

Rect GetSubImageRect(int indexSubImage)

{

    if (indexSubImage < 0 || indexSubImage >= deepZoomObject.SubImages.Count)        

        return Rect.Empty;

    MultiScaleSubImage subImage = deepZoomObject.SubImages[indexSubImage]; 

    double scaleBy = 1 / subImage.ViewportWidth;

    return new Rect(-subImage.ViewportOrigin.X * scaleBy, -subImage.ViewportOrigin.Y * scaleBy, 1 * scaleBy, (1 / subImage.AspectRatio) * scaleBy);

}

 

if you build and start your application now you should be able to see your added metadata when you mouseover a sub image in the MultiscaleImage.

My working example can be found here: http://www.vdcruijsen.net/projects/SilverlightDeepzoom/test.html

sourcecode can be downloaded here:

(you'll have to add your own deepzoom object since i removed that from the zip file)

 

Happy Coding!

 

Geert van der Cruijsen

kick it on DotNetKicks.com


Comments (2)

Geert's Vista Sidebar Gadget: Last.fm stream player version 0.1 released

January 6, 2008 13:07 by Geert van der Cruijsen

I've been spending all my spare time this weekend to this project but now the player is ready for release 0.1 beta ;)

You can download the gadget here:

Last.fm Stream Player gadget Download

 

Information about how it's made 

I've used wireshark to learn how the official client was using the last.fm protocol to get a mp3 stream since this wasnt documentated on the last.fm development documentation.

The different states in the protocol are:

  • handshake 1 (for streaming)
  • handshake 2 (for scrobbling)
  • tuning into a channel
  • get metadata of current song
  • send "now playing" information
  • at the end of song submit the scrobbled song
  • go to step 1

Since vista sidebar gadgets are html/javascript only the gadget is using an windows media player activex object to play the actual stream. All the handshake and other http requests are done by ajax calls to the audioscrobbler server. You can download the source on the download page also.

Have fun!

Geert van der Cruijsen


Comments (11)

Creating a Microsoft Windows Vista Sidebar Gadget: Last.fm stream player - part 1

January 3, 2008 21:47 by Geert van der Cruijsen

I’ve been using Windows Vista for 1 year now and I never used the sidebar before. I turned it off in the first week and never turned it back on again. Last week I decided to give it a try again and after filling it with some handy gadgets I thought it was time to build my own.

I didn’t know how to build a gadget so I looked it up on MSDN. There are some samples there but basically sidebar gadgets are small “web parts” totally build in HTML and JavaScript.

My first gadget I’m going to build is a Last.FM music player that can play a music stream from the Last.fm site with peoples favorite artists or with music matching a tag. Like you can do on the Last.fm site yourself.I went searching how I could get this stream to run in my gadget and I found out that Last.fm is using a fairly simple http based protocol which is described at http://www.audioscrobbler.net/development/protocol/I first started out with the 1.1 protocol because I didn’t read that there already was a 1.2 version. The 1.2 protocol has 3 states (handshake, now playing and submission) at the moment I’m writing this the only thing I have made is the handshake part and other functions to get metadata from the track.

I didnt make a nice user interface for my gadget yet and i didnt make anything to save your settings in. This will all be done in the upcoming days. If someone is really good in making a nice little interface (max 60 pixels wide) and feel like helping me out at this give me a call!. I'm not that good at grapic design.

btw. Coding Javascript in Visual Studio 2008 is really really nice. The intellisense really works great and it helps you write code a lot quicker.

I didnt put the sourcecode online yet since it's all in the debugging phase right now and everything is still hard coded (user,password, radio channel etc). When everything is done i'll post the full sourcecode here.

The functions that I’ve build now are shown in the following picture

The javascript code for these functions is shown below. (I will put it all on my site as a gadget when the whole thing is done).

This is all i could do in my spare time the last 2 days. I hope to get a lot further tomorrow and i'll post the results again.

function Play()

{

duration = 0;

document.WindowsMediaPlayer.Stop();

GetMetaData();

currentlyPlaying = true;

 

setTimeout("UpdateTimer()", 1000);

 

}

function stop()

{

currentlyPlaying = false;

document.WindowsMediaPlayer.Stop();

}

function UpdateTimer()

{

if (currentlyPlaying)

{

if((document.WindowsMediaPlayer.CurrentPosition < duration) || (duration == 0))

{

document.getElementById("counter").innerHTML = ConvertSecondsToTime(document.WindowsMediaPlayer.CurrentPosition);setTimeout("UpdateTimer()", 950);

 

}

else

{

//alert("restart");

document.WindowsMediaPlayer.Stop();

SendHandshake();

}

}

else

{

stop();

}

}

function ConvertSecondsToTime(seconds)

{

var date = new Date(seconds * 1000);

var timeString = date.getMinutes() + ":" + date.getSeconds();

return timeString;

}

function makeRequest(url) { http_request = false;

if (window.XMLHttpRequest) { // Mozilla, Safari,...

http_request = new XMLHttpRequest();

if (http_request.overrideMimeType) {http_request.overrideMimeType(

'text/xml');

}

} else if (window.ActiveXObject) { // IE

try {

http_request = new ActiveXObject("Msxml2.XMLHTTP");}

catch (e) {

try {http_request =

new ActiveXObject("Microsoft.XMLHTTP");} catch (e) {alert("error");}

}

}

if (!http_request) {

alert('Giving up :( Cannot create an XMLHTTP instance');

return false;

}

http_request.onreadystatechange = alertContents;

http_request.open('GET', url, true); http_request.send(null);

}

function alertContents()

{

if (http_request.readyState == 4)

{

if (http_request.status == 200)

{

document.getElementById("debug").innerHTML = http_request.responseText;

 

switch(functionCall)

{

case "SendHandshake" :

GetHandshakeResponse(http_request.responseText);

break;case "TuneIn" :

GetTuneInResponse(http_request.responseText);

break;

case "GetMetaData" :

GetMetaDataResponse(http_request.responseText);

break;default:

alert(functionCall);

}

}

else

{

alert('There was a problem with the request.' + http_request.status);

}

}

}

function SendHandshake()

{

var now = new Date();

now.setHours(now.getUTCHours(),now.getUTCMinutes(),now.getUTCSeconds(),now.getUTCMilliseconds());

var time = parseInt(now.getTime()/1000.0)

 

functionCall = "SendHandshake";

url = "http://post.audioscrobbler.com/?hs=true&p=1.2&c=tst&v=1.3.1.1&u="

url += "geertvdcruijsen";url += "&t=";

url += time;

url += "&a=";

var md5String = MD5("password");

md5String += (time);

url += MD5(md5String);

makeRequest(url);

}

function GetHandshakeResponse(response)

{

arr_response = response.split("\n");

//stream_url = arr_response[1].split("stream_url=")[1];

session = arr_response[0].split("session=")[1];document.getElementById("session").innerHTML =response;

TuneIn();

}

function TuneIn()

{

functionCall = "TuneIn";url = "http://ws.audioscrobbler.com/radio/adjust.php?session=";

url += session;

url += "&url="

url += "lastfm://artist/Chemical+Brothers/similarartists";url += "&debug=0";

makeRequest(url);

}

function GetTuneInResponse(response)

{

Play();

}

function GetMetaData()

{

var now = new Date();

functionCall = "GetMetaData";url =

"http://ws.audioscrobbler.com/radio/xspf.php?sk=";

url += session;

url += "&discovery=0&desktop=1.3.1.1&time="

url += now.getTime();

makeRequest(url);

}

function GetMetaDataResponse(response)

{

arr_location = response.split("<location>");stream_url = arr_location[1].split("</location>")[0];

 

arr_duration = response.split("<duration>");duration = arr_duration[1].split(

"</duration>")[0];

 

duration = (parseInt(duration,0)/1000) -3;

document.getElementById("metadata").innerHTML = ConvertSecondsToTime(duration);

 

document.WindowsMediaPlayer.fileName = stream_url;

document.WindowsMediaPlayer.Play();

}

<object id="wmp" standby="standby" type="application/x-oleobject"> <embed type="application/x-mplayer2" id="WindowsMediaPlayer" name="WindowsMediaPlayer" showstatusbar="-1"></embed>

</object>


Comments (0)

Volta, Seadragon and Photosynth. Cool stuff from Microsoft Live labs

December 30, 2007 13:37 by Geert van der Cruijsen

Almost 1 month ago Microsoft showed us their first technology preview of Volta. Volta is a new technology by Microsoft which makes it possible to change code to run on the server or client by only changing 1 line of code.

Imagine the possibilities on proof of concept projects where you don’t know where the bottlenecks will be. With this technology you can just build a test application and when you’re finished you can change pieces of code to run on the client or server to increase performance. Go and download the Volta technology preview on the live labs site now.

Another thing I wanted to show you is Seadragon. Seadragon is another technology by Live Labs from Microsoft. Seadragon is a technology where really high resolution pictures are stored on a server and you can zoom into them on the client. This makes it really easy to watch really high resolution images without having them on the client location. The Server application only sends the information that the client can see to the client application. These generated images are far less big in size as the original images are on the server.

Photosynth is another technology made by Live Labs and it is using the Seadragon technology to stream the images to the client. Photosynth is a tool to view a collection of images based on the location of where the images are taken. Photosynth can scan through a big collection of images of for example a big building and make up a 3d model of this building by using the images in the collection. You can view the building by selecting the angle of a specific image and the application will load that image with the Seadragon technology. From this new angle on the building you can zoom or select another image and you can take a virtual tour around the building like that.

You can test Photosynth on the live labs website with a few collections off famous buildings/objects like the NASA space shuttle Endeavour or Piazza San marco in Venice.

I found a really nice video about Seadragon and Photosynth on Youtube. If you want to see what is possible with these new technologies you really have to check it out.

I really think these technologies can grow big if you combine it for example with sites as Flickr so you can get a really new experience browsing through pictures.

Geert van der Cruijsen

 


Comments (0)

Creating a multitouch User interface in C# using the WiiMote

December 22, 2007 18:03 by Geert van der Cruijsen

I think most people heard about Microsoft Surface. (If not check http://www.microsoft.com/surface/) This machine will cost around 5000 to 10000 dollars but hey it's a really cool device. Now on my daily journey surfing the internet I came across a really cool project that everyone can try at home if you have knowledge about .net and own a Nintendo Wii to create your own multi touch user interface!

Since the Wii remote is using a Bluetooth connection towards it’s remote it’s also possible to connect it to your own pc. The Wii remote has an infra red sensor which can sense multiple infra red light sources at the same time.

How this all works is explained at http://www.cs.cmu.edu/~johnny/projects/wii/

There is also a C# sample code how to connect your pc to your Wii remote and how you’re able to do cool stuff with it. If I have enough time in the coming weeks I’ll try to test it myself if I can get my hands on some infra red LED’s.

Have fun!

Geert van der Cruijsen


Comments (0)