Weekend Project: Pi Music Box – Raspberry Pi as a Music streaming device

Get Grooveshark to run on a Raspberry Pi, Let your friends connect to and vote for their favourite songs. Let the majority rule what you hear at home or office.

We used to play songs regularly at work. Most of the time I play Dubstep while rest of the team want to listen to Trance or a different genre, this is where the clash of genres occur. This is where this system would be useful, if you get this running on a network then you can ask people to search their favourite songs and queue them in the system. Based on the votes they/others make for the song, it may float up or down making it either famous or not-so-famous. This makes a playlist of highest voted or popular songs.

The basic idea of the system is you connect the computer that streams music to a speaker/stereo. The system consists of two applications, one is used for streaming music and controlling the output of songs while the other interface/application takes user inputs via a Web Browser.

Media Streaming Application

Media streaming application is a console based service that runs in a threaded environment (multiple threads) to handle a player and a TCP server to accept user connections and pass user commands to the player to control the music output.

The preferred framework for most of my cross-application development is Qt, so I went with it for this project as well. I used the latest release of it which is Qt 5.1. I have specifically programmed this application to run on single board computers that run embedded Linux which implements a TCPIP stack and GStreamer based audio playback.

If you look at the “grooveshark-server” project hosted in Github you should be able to understand how to get it up and running on a Raspberry Pi, a Beaglebone or any other type of single board embedded computer. I still prefer you to give it a try on your desktop computer first and make sure it compiles correct on your x86 or x86_64 box before running it on ARM based environment.

In a nutshell all you need to do is to get Qt 5.1 running with Qt Core, Multimedia and Networking modules and then run Gstreamer with HTTPs based streaming plugin and mpeg4 decoder (this is found under “gstreamer ugly” package section of your distribution).

User Interface

The purpose of this application is to show a pretty interface to the user and let them search their favourite songs and queue them in the media streaming server, which we discussed above., since the above application only accepts 5 or so commands, this UI shows a eye-candy interface to the user and let them control the playlists and player attributes.

I cheated here, I could have implemented this into the media streaming server as a HTTP server (probably by embedding something like mongoose), implement my own templating engine in C and make it serve dynamic content. Since I wanted to make this project short-and-sweet (preferably finish within a weekend or so — basics :D ) I chose LAMP stack to build the Web based user interface to control the media server. This gives an added bonus of letting it run on the embedded computer (that runs the media streaming server) or another server sitting on the same network (this is achieved via TCP service that media server implements).

UI is build with LAMP stack as I mentioned before. jQuery and Bootstrap 3 is used for front-end content manipulation.

Look below for source code and demo of both applications working together to build a complete media streaming system.

frontpage navmenu search_results

Source
Server: https://github.com/purinda/grooveshark-server
UI: https://github.com/purinda/grooveshark-webui

Demos

How to check if a Port is open or not in C (Unix/Linux)

Thought of posting this script as I found this useful to embed in any socket based programs to figure out if a port is open or not in a certain host.
Tested on a Linux box and appears to be working fine.

Localhost and port 22 is hard coded into the snippet.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int main(int argc, char *argv[])
{
    int portno     = 22;
    char *hostname = "localhost;

    int sockfd;
    struct sockaddr_in serv_addr;
    struct hostent *server;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        error("ERROR opening socket");
    }

    server = gethostbyname(hostname);

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr,
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);

    serv_addr.sin_port = htons(portno);
    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
        printf("Port is closed");
    } else {
        printf("Port is active");
    }

    close(sockfd);
    return 0;
}

Beaglebone RF24(nRF24L01) Library

Why?

I started working on a project which require communication with multiple radios. I started looking at nRF24L01 chip and found it to be very useful, cheap little device which has many features built-in. Initially I got two AVRs to talk to each other through the simple library found here (http://www.tinkerer.eu/AVRLib/nRF24L01). But I found multiple issues with the library when the number of nodes in the network increases,

  • Didn’t support retries
  • Dynamic packet sizes
  • Channel scanning, etc

It was a simple library to start with and understand how the radio actually works in different configurations. I didn’t want to spend lot of time implementing all features I wanted so started looking around for complete libraries for nRF24L01, and I found RF24.

RF24 is one of the most complete libraries available for the nRF24L01[+]. So I implemented my project using RF24, It was an excellent library for AVRs (Arduino), but there was no port for devices running linux, as one of the nodes in my network was running linux I had to hack the code in order to get it to work on the beaglebone. So I had to spend a weekend hacking the RF24 library to come up with a very thin layer below the library to support all its features on embedded linux boards. I used a beaglebone for testing.

This is a Beaglebone port of the popular RF24(nrf24l01) library posted on https://github.com/maniacbug/RF24/.
If you find the library is out of sync with the Arduino library please drop an email to purinda@gmail.com

Contains portions of the GPIO library posted here,
https://github.com/mrshu/GPIOlib

Complete wiki can be found here
http://maniacbug.github.com/RF24Network/index.html

Features

  • Refer to RF24 documentation.

Requirements

How to connect the pins

  • I used one of these boards to test the library. http://iteadstudio.com/store/images/produce/Wireless/RF2401/RF24013.jpg
  • Connect PIN 1 (GND) of NRF24L01 board to Expansion header P9 PIN 1(GND) of Beagleboard
  • Connect PIN 2 (VCC) of NRF24L01 board to Expansion header P9 PIN 3(3v3) of Beagleboard
  • Connect PIN 3 (CE) of NRF24L01 board to Expansion header P9 PIN 27(GPIO3_19) of Beagleboard
  • Connect PIN 4 (CSN) of NRF24L01 board to Expansion header P9 PIN 25(GPIO3_21) of Beagleboard
  • Connect PIN 5 (SCK) of NRF24L01 board to Expansion header P9 PIN 31(SPI1_SCLK) of Beagleboard
  • Connect PIN 6 (MOSI) of NRF24L01 board to Expansion header P9 PIN 30(SPI1_D1) of Beagleboard
  • Connect PIN 7 (MISO) of NRF24L01 board to Expansion header P9 PIN 29(SPI1_D0) of Beagleboard

Notes

  • Note that the library uses a GPIO pin in BeagleBone as CS pin, which is an workaround/issue exist in the code. Planning to fix it whenever I have time.
  • Project is written using NetBeans and I have commited some files used by netbeans IDE.
  • main.c contains a program which prints out the information of the connected NRF24L01 device and ping demo.
  • you may need to upload the Arduino sketch in ‘pingpair_dyn_arduino_pongback’ directory to a Arduino board in order for both Beaglebone and Arduino to run interactively.

Download the source here

https://bitbucket.org/purinda/rf24bb/src