Can someone write a python WiFi Radio program?
Moderators: adafruit_support_bill, adafruit

Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/

Can someone write a python WiFi Radio program?

by pentiger on Wed Jun 26, 2013 10:33 pm

Hello,

I love RPi and I am learning python with it.

I tried the WiFi radio program, but I am not a big fan of pandora, I prefer online radio.
There's a nice project online at http://usualpanic.com that does this. Sheldon, who runs the site and wrote the program is a great guy, but very busy.
I was able to modify the program a little to what I need but I'ts not great, as I mentioned I am learning python.

I am looking for features similar to the pandora radio on RPi but with an external playlist of radio streams.
Sheldon's program shows the name of the station pre-configured in the playlist file.

Many stations show the name of the station and current song info visible in MPC just like with shoutcast and winamp on PC.

I was able to achieve the decoding in python, with this code

Code: Select all | TOGGLE FULL SIZE
     
      f1=os.popen('echo "currentsong" | nc localhost 6600 | grep -e "^Name: "')
      f2=os.popen('echo "currentsong" | nc localhost 6600 | grep -e "^Title: "')
      firstline = f1.readline()
      secondline = f2.readline()     
      firstline = firstline[6:]
      secondline1 = secondline[7:]


when entered in the loop it will read the name of the station and can be displayed on LCD, ( I forgot to mention that I am using the Pi LCD keypad from Adafruit)
It's all great but in the same while loop I am reading the buttons state (the whole program is on [url]usualpanic.com[/url] )
and when I continue to display the song and station info the buttons become nonresponsive. I am dealing with this by introducing a countdown to update info every 30 seconds and it works to an extent, when I click a button during the wait time it will change the station but if I click it during the update state it will not change and I have to press again.

In my code when the SELECT button is pressed it will show the full name of the song and in other times only the first 16 characters, again I did this to save some time for the buttons to work.

It's possible to show the whole title either scrolling or line by line divided by 16 charachters but it takes long and buttons do not work then.

If someone is interested here is my (based on Sheldon's program) complete code and the playlist.

Code: Select all | TOGGLE FULL SIZE

#!/usr/bin/python

# radio.py, version 2.1 (RGB LCD Pi Plate version)
# February 17, 2013
# Written by Sheldon Hartling for Usual Panic
# BSD license, all text above must be included in any redistribution
#

#
# based on code from Kyle Prier (http://wwww.youtube.com/meistervision)
# and AdaFruit Industries (https://www.adafruit.com)
# Kyle Prier - https://www.dropbox.com/s/w2y8xx7t6gkq8yz/radio.py
# AdaFruit   - https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git, Adafruit_CharLCDPlate
#

#dependancies
from Adafruit_I2C          import Adafruit_I2C
from Adafruit_MCP230xx     import Adafruit_MCP230XX
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
from datetime              import datetime
from subprocess            import *
from time                  import sleep, strftime
from Queue                 import Queue
from threading             import Thread
import os
import smbus

# initialize the LCD plate
#   use busnum = 0 for raspi version 1 (256MB)
#   and busnum = 1 for raspi version 2 (512MB)
LCD = Adafruit_CharLCDPlate(busnum = 0)

# Define a queue to communicate with worker thread
LCD_QUEUE = Queue()

# Globals
PLAYLIST_MSG   = []
STATION        = 1
NUM_STATIONS   = 0

# Buttons
NONE           = 0x00
SELECT         = 0x01
RIGHT          = 0x02
DOWN           = 0x04
UP             = 0x08
LEFT           = 0x10
UP_AND_DOWN    = 0x0C
LEFT_AND_RIGHT = 0x12



# ----------------------------
# WORKER THREAD
# ----------------------------

# Define a function to run in the worker thread
def update_lcd(q):
   
   while True:
      msg = q.get()
      # if we're falling behind, skip some LCD updates
      while not q.empty():
         q.task_done()
         msg = q.get()
      LCD.setCursor(0,0)
      LCD.message(msg)
      q.task_done()
   return


# ----------------------------
# MAIN LOOP
# ----------------------------

def main():
   global STATION, NUM_STATIONS, PLAYLIST_MSG, firstline, secondline, press

   # Stop music player
   output = run_cmd("mpc stop" ) 
   # Setup AdaFruit LCD Plate
   LCD.begin(16,2)
   LCD.clear()
   LCD.backlight(LCD.ON)
       
   # Create the worker thread and make it a daemon
   worker = Thread(target=update_lcd, args=(LCD_QUEUE,))
   worker.setDaemon(True)
   worker.start()

   # Load our station playlist
   load_playlist()
   sleep(2)
       
# ----------------------------
# START THE MUSIC!
# ----------------------------

   # Start music player
   run_cmd("mpc volume +100")
   last_song = ""
   current_song = ""
   current_station = ""
   last_station = ""
   update = 0
   i = 6
   i1 = 5
   line_lenght = 7
   line1_lenght = 6   
   countdown_to_play = 5
   delay = 0
   mpc_play(STATION)
   clearline = ("                ")
   # Main loop
   while True:
     
      press = read_buttons()
      if delay == 0:
       
        f1=os.popen('echo "currentsong" | nc localhost 6600 | grep -e "^Name: "')
        f2=os.popen('echo "currentsong" | nc localhost 6600 | grep -e "^Title: "')
        firstline = f1.readline()
        secondline = f2.readline()     
        firstline = firstline[6:]
        firstline = (PLAYLIST_MSG[STATION - 1])
        secondline1 = secondline[7:]
        secondline2 = secondline[23:]
        secondline3 = secondline[39:] 
        secondline4 = secondline[55:]
        secondline5 = secondline[71:]
        line2_lenght = len(secondline)
        current_song = secondline1   
        current_station = firstline
     
        if current_station != last_station:
              LCD_QUEUE.put(clearline)
              LCD_QUEUE.join()
              LCD_QUEUE.put(firstline)
              LCD_QUEUE.join()
     
        if current_song != last_song:
             

              if (line2_lenght > 0):
                  LCD_QUEUE.put("\n" + secondline1)
                  LCD_QUEUE.join()
                  LCD_QUEUE.put(clearline)
                  LCD_QUEUE.join()
                  LCD_QUEUE.put(firstline)
                  LCD_QUEUE.join()

                     

              if (line2_lenght == 0):
                  LCD_QUEUE.put("\n                ")
                  LCD_QUEUE.join()
     
                       
                     
       # LEFT button pressed
      while (press == LEFT):
         
         press = read_buttons()
         STATION -= 1
         if(STATION < 1):
            STATION = NUM_STATIONS
         LCD_QUEUE.put(PLAYLIST_MSG[STATION - 1], True)
         delay_milliseconds(20)
         LCD_QUEUE.join()
         if press != LEFT:
            countdown_to_play = 3
            continue
         
         
       # RIGHT button pressed
      while(press == RIGHT):
         press = read_buttons()
         STATION += 1
         if(STATION > NUM_STATIONS):
            STATION = 1
         delay_milliseconds(20)
         LCD_QUEUE.put(PLAYLIST_MSG[STATION - 1], True)
         LCD_QUEUE.join()
         if press != RIGHT:
            countdown_to_play = 3
            continue
   
             
                 
         
         
     
      # UP button pressed
      if(press == UP):
         output = run_cmd("mpc volume +2")
         
         
      # DOWN button pressed
      if(press == DOWN):
         output = run_cmd("mpc volume -2")
         

      # SELECT button pressed
      while(press == SELECT):
         press = read_buttons()
         LCD_QUEUE.put("\n" + clearline)
         LCD_QUEUE.join()
         

         if (line2_lenght >= 16):
              LCD_QUEUE.put("\n" + secondline2)
              LCD_QUEUE.join()
              sleep(1)
              LCD_QUEUE.put("\n" + clearline)
              LCD_QUEUE.join()
             
           
         if (line2_lenght >= 32):
                  LCD_QUEUE.put("\n" + secondline3)
                  LCD_QUEUE.join()
                  sleep(1)
                  LCD_QUEUE.put("\n" + clearline)
                  LCD_QUEUE.join()
                 

         if (line2_lenght >= 48):
                     LCD_QUEUE.put("\n" + secondline4)
                     LCD_QUEUE.join()
                     sleep(1)
                     LCD_QUEUE.put("\n" + clearline)
                     LCD_QUEUE.join()                       
                     
           
         if (line2_lenght >= 64):
                         LCD_QUEUE.put("\n" + secondline5)
                         LCD_QUEUE.join()
                         sleep(1)
                         LCD_QUEUE.put("\n" + clearline)
                         LCD_QUEUE.join()
                         

         if (line2_lenght > 0):
           press = read_buttons()
           LCD_QUEUE.put("\n" + secondline1)
           LCD_QUEUE.join()
           if press != SELECT:
              continue
                           

      if(countdown_to_play > 0):
         countdown_to_play -= 1
         if(countdown_to_play == 0):
            # Play requested station
            mpc_play(STATION)

           
             
       
      last_song = current_song
      last_station = current_station
     
   update_lcd.join()         
   


# ----------------------------
# READ SWITCHES
# ----------------------------

def read_buttons():

   buttons = LCD.readButtons()
   # Debounce push buttons
   if(buttons != 0):
      while(LCD.readButtons() != 0):
         delay_milliseconds(10)
         return buttons
   
def delay_milliseconds(milliseconds):
   seconds = milliseconds / float(1000)   # divide milliseconds by 1000 for seconds
   sleep(seconds)



# ----------------------------
# LOAD PLAYLIST OF STATIONS
# ----------------------------

def load_playlist():
   global STATION, NUM_STATIONS, PLAYLIST_MSG

   # Run shell script to add all stations
   # to the MPC/MPD music player playlist
   output = run_cmd("mpc clear")
   output = run_cmd("/home/pi/projects/radio/radio_playlist.sh")

   # Load PLAYLIST_MSG list
   PLAYLIST_MSG = []
   with open ("/home/pi/projects/radio/radio_playlist.sh", "r") as playlist:
      # Skip leading hash-bang line
      for line in playlist:
         if line[0:1] != '#!': 
               break
      # Remaining comment lines are loaded
      for line in playlist:
         if line[0] == "#" :
            PLAYLIST_MSG.append(line.replace(r'\n','\n')[1:-1] + "                ")
   playlist.close()
   NUM_STATIONS = len(PLAYLIST_MSG)


# ----------------------------
# RADIO SETUP MENU
# ----------------------------


 

def run_cmd(cmd):
   p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
   output = p.communicate()[0]
   return output

#def run_cmd_nowait(cmd):
   #pid = Popen(cmd, shell=True, stdout=NONE, stderr=STDOUT).pid

def mpc_play(STATION):
   pid = Popen(["/usr/bin/mpc", "play", '%d' % ( STATION )]).pid


if __name__ == '__main__':
  main()
 
#if secondline != update:
       #LCD_QUEUE.put(firstline + "\n" + secondline)
       #update = secondline





and the playlist


Code: Select all | TOGGLE FULL SIZE

#! /bin/sh

#1: RMF FM
mpc add http://files.kusmierz.be/rmf/rmf-2.mp3

#2: BEST OF RMF ON
mpc add http://files.kusmierz.be:80/rmf/bestofrmfon-2.mp3

#3: ELO
mpc add http://files.kusmierz.be:80/rmf/elo-2.mp3

#4: RMF 2
mpc add http://files.kusmierz.be:80/rmf/rmf2-2.mp3

#5:  RMF 2000
mpc add http://files.kusmierz.be:80/rmf/2000-2.mp3

#6: RMF 3
mpc add http://files.kusmierz.be:80/rmf/rmf3-2.mp3

#7: RMF 4
mpc add http://files.kusmierz.be:80/rmf/rmf4-2.mp3

#8: RMF 5
mpc add http://files.kusmierz.be:80/rmf/rmf5-2.mp3

#9: RMF 50'S
mpc add http://files.kusmierz.be:80/rmf/50s-1.mp3

#10: RMF 60'S
mpc add http://files.kusmierz.be:80/rmf/60s-1.mp3

#11: RMF 70's
mpc add http://files.kusmierz.be:80/rmf/70s-1.mp3

#12: RMF 70's Disco
mpc add http://files.kusmierz.be:80/rmf/70sdisco-1.mp3

#13: RMF 80's
mpc add http://files.kusmierz.be:80/rmf/80s-1.mp3

#14: RMF 80's Disco
mpc add http://files.kusmierz.be:80/rmf/80sdisco-1.mp3

#15: RMF 90's
mpc add http://files.kusmierz.be:80/rmf/90s-1.mp3

#16: RMF Alternatywa
mpc add http://files.kusmierz.be:80/rmf/alternatywa-1.mp3

#17: RMF Baby
mpc add http://files.kusmierz.be:80/rmf/baby-1.mp3

#18: RMF Bealtlemania
mpc add http://files.kusmierz.be:80/rmf/beatlemania-1.mp3

#19: RMF BRAVO
mpc add http://files.kusmierz.be:80/rmf/bravo-1.mp3

#20: RMF Celtic
mpc add http://files.kusmierz.be:80/rmf/celtic-1.mp3

#21: RMF Chillout
mpc add http://files.kusmierz.be:80/rmf/chillout-1.mp3

#22: RMF Chopin
mpc add http://files.kusmierz.be:80/rmf/chopin-1.mp3

#23: RMF Classic
mpc add http://files.kusmierz.be:80/rmf/classic-1.mp3

#24: RMF Classic Rock
mpc add http://files.kusmierz.be:80/rmf/classicrock-1.mp3

#25: RMF Club
mpc add http://files.kusmierz.be:80/rmf/club-1.mp3

#26: RMF ClubBreaks
mpc add http://files.kusmierz.be:80/rmf/clubbreaks-1.mp3

#27: RMF Cover
mpc add http://files.kusmierz.be:80/rmf/cover-1.mp3

#28: RMF Cuba
mpc add http://files.kusmierz.be:80/rmf/cuba-1.mp3

#29: RMF DANCE
mpc add http://files.kusmierz.be:80/rmf/dance-1.mp3

#30: RMF DepecheMode
mpc add http://files.kusmierz.be:80/rmf/depechemode-1.mp3

#31: RMF Electroshockwave
mpc add http://files.kusmierz.be:80/rmf/electroshockwave-1.mp3

#32: RMF Blues
mpc add http://files.kusmierz.be:80/rmf/blues-1.mp3

#33: RMF 20 lat
mpc add http://files.kusmierz.be:80/rmf/20lat-1.mp3

#34: RMF Flamenco
mpc add http://files.kusmierz.be:80/rmf/flamenco-1.mp3

#35: RMF Football
mpc add http://files.kusmierz.be:80/rmf/football-1.mp3

#36: RMF Francais
mpc add http://files.kusmierz.be:80/rmf/francais-1.mp3

#37: RMF Gold
mpc add http://files.kusmierz.be:80/rmf/gold-1.mp3

#38: RMF Grove
mpc add http://files.kusmierz.be:80/rmf/groove-1.mp3

#39: RMF Grunge
mpc add http://files.kusmierz.be:80/rmf/grunge-1.mp3

#40: RMF Hardheavy
mpc add http://files.kusmierz.be:80/rmf/hardheavy-1.mp3

#41: RMF Hiphop
mpc add http://files.kusmierz.be:80/rmf/hiphop-1.mp3

#42: RMF HopBec OldSchool
mpc add http://files.kusmierz.be:80/rmf/hopbecoldschool-1.mp3

#43: RMF Hot New
mpc add http://files.kusmierz.be:80/rmf/hotnew-1.mp3

#44: RMF Lady Pank
mpc add http://files.kusmierz.be:80/rmf/ladypank-1.mp3

#45: RMF Love
mpc add http://files.kusmierz.be:80/rmf/love-1.mp3

#46: RMF Maxxx
mpc add http://files.kusmierz.be:80/rmf/maxxx-1.mp3

#47: RMF HopBec
mpc add http://files.kusmierz.be:80/rmf/hopbec-1.mp3

#48: RMF Ibiza
mpc add http://files.kusmierz.be:80/rmf/ibiza-1.mp3

#49: RMF Michael Jackson
mpc add http://files.kusmierz.be:80/rmf/jackson-1.mp3

#50: RMF MJ
mpc add http://files.kusmierz.be:80/rmf/mj-1.mp3

#51: RMF FILMOWA
mpc add http://files.kusmierz.be:80/rmf/filmowa-1.mp3

#52: RMF KLASYCZNA
mpc add http://files.kusmierz.be:80/rmf/klasyczna-1.mp3

#53: RMF MUZZO
mpc add http://files.kusmierz.be:80/rmf/muzzo-1.mp3

#54: RMF NIEZAPOMNIANE
mpc add http://files.kusmierz.be:80/rmf/niezapomnianemelodie-1.mp3

#55: RMF NIPPON
mpc add http://files.kusmierz.be:80/rmf/nippon-1.mp3

#56: RMF NOSTALGIA
mpc add http://files.kusmierz.be:80/rmf/nostalgia-1.mp3

#57: RMF COUNTRY
mpc add http://files.kusmierz.be:80/rmf/country-1.mp3

#58: RMF PARTY
mpc add http://files.kusmierz.be:80/rmf/party-1.mp3

#59: RMF LITERACKA
mpc add http://files.kusmierz.be:80/rmf/literacka-1.mp3

#60: RMF POLSKIROCK
mpc add http://files.kusmierz.be:80/rmf/polskirock-1.mp3

#61: RMF POLSKIE DISCO
mpc add http://files.kusmierz.be:80/rmf/polskiedisco-1.mp3

#62: RMF POLSKIE PRZEBOJE
mpc add http://files.kusmierz.be:80/rmf/pprzeboje-1.mp3

#63: RMF POPCOLORS
mpc add http://files.kusmierz.be:80/rmf/popcolors-1.mp3

#64: RMF POPLISTA
mpc add http://files.kusmierz.be:80/rmf/poplista-1.mp3

#65: RMF POPLISTA 10LAT
mpc add http://files.kusmierz.be:80/rmf/poplista10lat-1.mp3

#66: RMF PRL
mpc add http://files.kusmierz.be:80/rmf/prl-1.mp3

#67: RMF PRZEBOJ LATA
mpc add http://files.kusmierz.be:80/rmf/przebojlata-1.mp3

#68: RMF PUNK
mpc add http://files.kusmierz.be:80/rmf/punk-1.mp3

#69: RMF QUEEN
mpc add http://files.kusmierz.be:80/rmf/queen-1.mp3

#70: RMF RNB
mpc add http://files.kusmierz.be:80/rmf/rnb-1.mp3

#71: RMF REGGAE
mpc add http://files.kusmierz.be:80/rmf/reggae-1.mp3

#72: RMF ROCK
mpc add http://files.kusmierz.be:80/rmf/rock-1.mp3

#73: RMF PROGRES. ROCK
mpc add http://files.kusmierz.be:80/rmf/progrock-1.mp3

#74: RMF RUMOR
mpc add http://files.kusmierz.be:80/rmf/rumor-1.mp3

#75: RMF SADE
mpc add http://files.kusmierz.be:80/rmf/sade-1.mp3

#76: RMF SMOOTH JAZZ
mpc add http://files.kusmierz.be:80/rmf/smoothjazz-1.mp3

#77: RMF STYL
mpc add http://files.kusmierz.be:80/rmf/styl-1.mp3

#78: RMF SZANTY
mpc add http://files.kusmierz.be:80/rmf/szanty-1.mp3

#79: RMF SLONECZNE PRZEBOJE
mpc add http://files.kusmierz.be:80/rmf/sloneczneprzeboje-1.mp3

#80: RMF WOLD MUSIC
mpc add http://files.kusmierz.be:80/rmf/worldmusic-1.mp3

#81: RMF ZIOM
mpc add http://files.kusmierz.be:80/rmf/ziom-1.mp3

#82: RMF FEST.MUZ.FILM.
mpc add http://files.kusmierz.be:80/rmf/fmf-1.mp3






Sheldon's Site http://usualpanic.com has details on how to use the files.

If maybe someone else has a working program, please post it, or maybe someone is very efficient in Python and can do it in 30 minutes, hopefully to mimic the functionality of pandora radio for Rpi.

Thanks in advance, this project is important to me and hopefully many other's will benefit from it.

-pentiger
pentiger
 
Posts: 8
Joined: Wed Jun 26, 2013 9:55 pm