Wednesday, January 15, 2014

Arduino Yun Grooveshark Radio


I got an Arduino Yun as Christmas preset this year. After a few days playing around with it, I decided that I wanted to turn it into an internet audio playback device. I found there is a cool python library to access Grooveshark, which is even cooler than traditional internet radios... I will explain here the steps to get it to work. I assume basic Linux and programming knowledge in my explanation.

The first step was to get USB audio working as per the explanations in here... easy...

Next step was to get some audio player running on the Linux side which would play an mp3 from a URL (rather than from file as madplay). I checked on the available packages and there was no mplayer, no vlc, no mpg123... crap... so I checked on how to compile my own packages. The first step was to compile linino image and packages:

git clone https://github.com/arduino/linino.git
cd linino/trunk
./scripts/feeds uninstall -a  
rm -rf feeds
./scripts/feeds update -a
./scripts/feeds install -a
rm -f .config
git checkout .config
make oldconfig
make V=s

During this process I found some compile issues, in fact I did not get to build all the packages, but seems like it was enough to later build mpg123.

In order to build the mpg123 package, I got the makefile from here, copied it inside my linino tree in linino/trunk/package/feeds/packages/mpg123/ and then did:

make package/mpg123/compile V=s

Somehow that did not create a .ipk file to install in the yun, as I was expecting, but everything from the ipk package that should have been created was available in linino/trunk/build_dir/target-mips_r2_uClibc-0.9.33.2/mpg123-1.13.2/ipkg-install/, so I just had to copy that folder into a pen drive and from there into the yun filesystem.

When I tried to run mpg123 I faced another issue, libltdl shared library was missing. Seems like that library was built during the linino image compilation here: linino/trunk/staging_dir/target-mips_r2_uClibc-0.9.33.2/usr/lib/libltdl.so.7.3.0. As with mpg123 before, I copied it into a pen drive and into the filesystem of the yun. Et voila... mpg123 was working.

Unfortunately, sound quality alternated between OK and very bad (with stuttering sound). In  order to fix this, I created the file /etc/asound.conf with the following contents:

pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_key_add_uid false
    ipc_perm 0666
    slave {
        pcm "hw:0,0"
        ### WARNING: do NOT add period_time, period_size or buffer_size here!!! ###
        rate 44100
    }
    bindings {
        0 0
        1 1
    }
}

pcm.dsp0 {
    type plug
    slave.pcm "dmixer"
}

pcm.!default {
    type plug
    slave.pcm "dmixer"
}

pcm.default {
   type plug
   slave.pcm "dmixer"
}

ctl.mixer0 {
    type hw
    card 0
}

This came from here. That seemed to fix the issues.

OK, so we now have mpg123 working, yuhuuu... next step was pygrooveshark. I downloaded it from here, put it into a pendrive and did:

python setup.py install

Based on the pygrooveshark radio example, I made this python script in /root/examples-pygrooveshark/radio_mpg123.py which takes a number representing the radio genre as parameter (17 is for METAL, if you want to try it from the command line):

from __future__ import print_function

import subprocess
import sys

from grooveshark import Client
from grooveshark.classes import Radio

client = Client()
client.init()
cmdargs = str(sys.argv)

for song in client.radio(sys.argv[1]):
    print(song.name)
    print(song.artist.name)
    print(song.album.name)
    sys.stdout.flush()
    subprocess.call(['mpg123', song.stream.url])

Tried running it but found another issue. Do not remember the exact error, but basically python on the yun was built without SSL support. The solution was to copy the file linino/trunk/staging_dir/target-mips_r2_uClibc-0.9.33.2/root-ar71xx/usr/lib/python2.7/lib-dynload/_ssl.so in /usr/lib/python2.7/lib-dynload/_ssl.so in the yun filesystem. Once that was done, I was able to run pygrooveshark scripts from the yun linux terminal.

Last step was to get some way of launching the different radio genres from the arduino/AVR side. Here is the hardware setup:



And here the sketch running on the AVR side:


#include <FileIO.h>

#define    GENRE_NONE             0
#define    GENRE_ROCK             12
#define    GENRE_BLUES            230
#define    GENRE_ELECTRONICA      67
#define    GENRE_CLASSICROCK      3529
#define    GENRE_INDIE            136
#define    GENRE_METAL            17


int stations[] = { GENRE_NONE,
    GENRE_ROCK,
    GENRE_BLUES,
    GENRE_ELECTRONICA,
    GENRE_CLASSICROCK,
    GENRE_INDIE,
    GENRE_METAL };

int genres;
int val = 0;
int prevVal = 0;
Process radio_process;

void setup() {
  genres = sizeof(stations)/sizeof(int);
  Bridge.begin();
  Serial.begin(9600);

  while(!Serial);  // wait for Serial port to connect.
  Serial.println("Grooveshark Radio example");

  start_radio(val);  
}

void loop() {
  val = analogRead(3);
  val = (val*genres)/1023;

  
  if(val != prevVal) {
    String text;
    text = "Value: ";
    text += val;
    Serial.println(text);

    start_radio(val);
    
    prevVal = val;
  } 

  while(radio_process.available() > 0){
    char c = radio_process.read();
    Serial.print(c);
  }
  delay(400);
}

void start_radio(int val) {
    String parameter = "";
    radio_process.close();
    Process killer;
    killer.begin("killall");
    killer.addParameter("mpg123");
    killer.run();
    if(stations[val] != 0) {
      radio_process.begin("python");
      radio_process.addParameter("/root/examples-pygrooveshark/radio_mpg123.py");
      parameter+= stations[val];
      radio_process.addParameter(parameter);
      radio_process.runAsynchronously();
    }
    else {
      radio_process.begin("echo");
      radio_process.addParameter("Do Nothing!!!");
      radio_process.runAsynchronously();
    }
}

I can change grooveshark radios by moving the potentiometer.

What is next? I have ordered an LCD screen and a rotary encoder for user interface. My plan is to allow playback of grooveshark user favourites and playlists, but that requires a lot more changes in both the AVR and Linux.

1 comment:

  1. your blog describe a nice view of the things. It is very effective for the reader. Please post more blog related to this.
    Visit :- radio Arduino

    ReplyDelete