athenoc's Journal

sirius7

 

     Qt is an amazing framework.  It has a clean API and extensive documentation to ensure that a user sails well.

 

That said, it was pretty cool to bring together my favorite music streaming service and Qt together for this app.

 

 

This app is an Internet Radio Streamer for 977 Music. The streaming service is undergoing some re-branding and their mobile apps website is not active at the time of writing this. But if you are still rocking your Symbian^3+ Nokia, feel free to email Jeff (The awesome dude that owns 977 Music) and ask him for the download link (He might probably just send you the .sis file).

 

 

Let’s get into some details. This is how things are put together:

 

      C++ handles extracting metadata from the stream and manages the actual music player.

Qml manages the interface (let’s face it, Qt/C++ is not the best choice for slick interfaces on mobile devices, but Qml does the job pretty well).

 

     I will only provide some details, on extracting metadata and querying last.fm as these are the only things that aren’t very straight forward to implement (will be happy to help if you need anything else) .

 

 

 

 

     Extracting metadata:

 

Playing a stream in Qt/C++ (a very general, raw idea) :

player = new QMediaPlayer(this);

player->setVolume(50);

player->setMedia(QUrl(streamUrl.toStdString().c_str()));

player->play();

 

//where streamUrl is a QString that has the stream address.

     To get data from streams (strictly, streams from the icecast/shoutcast family), you need to ‘GET’ request  the stream, with a field:

 

Icy-MetaData 1

 

In Qt, it should be something like this,

 

QNetworkRequest request;

request.setUrl(QUrl(url));

request.setRawHeader("Icy-MetaData", "1");

reply = manager->get(request);

This gives you a header of the form:

 

Icy-metaint: n

 

     Where, n is the number of bytes after which a metadata block is sent in the stream.

 

Now you read n bytes , the next byte specifies the length of the metadata block. Now read those many bytes, and you have the metadata !

 

You will find a string, similar to,

StreamTitle= “linkin park - numb”

 

    We can now use the artist and song name to querry last.fm for more details.

 

    Querying last.fm:

 

     The Last.fm API allows you to call methods that respond in REST style xml (last.fm).

 

     We need to parse the xml;  a convenient way is to use XmlListModel.

     XmlListModel lets you specify the source and the querry, which is the particular last.fm method  you want to call.

 

In Qml, it looks something like:

XmlListModel{

id:nfo          

source:"http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist="+info.artist+"&autocorrect=1&api_key=…"

     

       query: "/lfm/artist"

     

       XmlRole {name: "name"; query: "name/string()"}

       XmlRole {name:"imageSma";query:"image[1]/string()"}

       XmlRole {name:"summary";query: "bio/summary/string()"}

 

       onStatusChanged: {

           if(status===XmlListModel.Ready){

               if(artist=="") return;

               if(count>0)

                   info.lastArtist=nfo.get(0)

           }

       }

   }

And there you go!

stream 1 2 updscreenshotapp75[1]