Fip Now Plays

I’ve been tweaking my touch-screen Raspberry Pi radio. It’s optimised for the Pimoroni HyperPixel display, but it would work with any touch-screen, although it may need scaling for different sized screens.

Aside from the mpd/mpc music player and adding some radio stations, it doesn’t need any other libraries installing and should run on vanilla Raspbian. You’ll need some GIF images of logos, the ones I used are on the page for the old version of this program.

I’ve tidied up the display a bit, added a button to shut the system down and added a button that shows the track that is currently playing on Fip, my favourite radio station. This is actually rather useful as Fip’s music is famously eclectic and sometimes you just have to know what that achingly cool Belgian techno-influenced rockabilly-jazz tune is and who recorded it.

I can’t, it seems, easily do this for BBC radio, alas. France’s state broadcaster syndicates its ‘now playing’ track info as a JSON feed and I had a huge amount of, er, ‘fun’ working out how to parse this. Turns out you have to ‘drill down’ quite far in the data:
key = feed['levels'][0]['items'][3]
to extract a UUID number that you then need to use to look up the track name. And sometimes the ‘performer’ field is missing for some reason, so I added an exception for that. But at least it’s there. Unlike BBC radio.

And I learned a bit about handling JSON in Python.

I made a really cool Raspberry Pi radio a few years ago that you controlled from a web page that had ‘now playing’ info for Fip (culled from a twitter account) and from the BBC via Last.fm. It looks like the Last.fm kludge doesn’t work any more, and the BBC seems to have closed the ‘Backstage’ operation which provided API access to its ‘now playing’ data for independent websites like https://dyl.anjon.es/onradio/1 – which, oddly, still seems to work. I could screen-scrape that web page, I suppose, but it seems a bit unfair on Mr Jones. It is very frustrating the BBC doesn’t seem to do this any more – if anyone knows different I’d be grateful. Fip doesn’t even require an API key.

Anyway, here’s the Python program. It only fetches the Fip JSON data when you press the ‘fip now plays’ button so it doesn’t update all the time, and also does not bombard Fip’s servers with data requests.

#!/usr/bin/env python3
from tkinter import Tk, Label, Button, PhotoImage
import os, time, subprocess, json
from urllib.request import urlopen

def get_jsonparsed_data(url):
    response = urlopen(url)
    data = response.read().decode("utf-8")
    return json.loads(data)

url = ("https://www.fip.fr/livemeta/7/")
time1 = ''

IP = subprocess.check_output(["hostname", "-I"]).split()[0]

class MyFirstGUI:
    def __init__(self, master):
        global fiplogo
        self.master = master
        master.title("HyperPixelRadio")

        fiplogo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/fip100.gif")

        self.label = Label(master, text="HyperPixel Radio by @blogmywiki", font=('Lato Heavy',25), fg = 'blue')
        self.label.grid(columnspan=7, pady=20)

        self.fip_button = Button(master, image=fiplogo, command=self.fip, height=100, width = 100)
        self.fip_button.image = fiplogo
        self.fip_button.grid(row=1, pady=10, padx=4)

        r2logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/radio2.gif")
        self.r2_button = Button(master, image=r2logo, command=self.r2, height=100, width = 100)
        self.r2_button.image = r2logo
        self.r2_button.grid(row=1, column=1, padx=4)

        r4logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/radio4.gif")
        self.r4_button = Button(master, image=r4logo, command=self.r4, height=100, width = 100)
        self.r4_button.image = r4logo
        self.r4_button.grid(row=1, column=2, padx=4)

        x4logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/4extra.gif")
        self.x4_button = Button(master, image=x4logo, command=self.x4, height=100, width = 100)
        self.x4_button.image = x4logo
        self.x4_button.grid(row=1, column=3, padx=4)

        r5logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/5live.gif")
        self.r5_button = Button(master, image=r5logo, command=self.r5, height=100, width = 100)
        self.r5_button.image = r5logo
        self.r5_button.grid(row=1, column=4, padx=4)

        r6logo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/6music.gif")
        self.r6music_button = Button(master, image=r6logo, command=self.r6music, height=100, width = 100)
        self.r6music_button.image = r6logo
        self.r6music_button.grid(row=1, column=5, padx=4)

        wslogo = PhotoImage(file="/home/pi/Desktop/HyperPixelRadio/bbcws.gif")
        self.ws_button = Button(master, image=wslogo, command=self.ws, height=100, width = 100)
        self.ws_button.image = wslogo
        self.ws_button.grid(row=1, column=6, padx=4)

        self.down_button = Button(master, text="< VOL", command=self.down, height=5, width=10)
        self.down_button.grid(row=2)

        self.up_button = Button(master, text="shut down", command=self.shutdown, height=5, width=10)
        self.up_button.grid(row=2, column=1)

        self.close_button = Button(master, text="close app", command=self.close, height=5, width=10)
        self.close_button.grid(row=2, column=2)

        self.ip_button = Button(master, text="show IP", command=self.ipaddr, height=5, width=10)
        self.ip_button.grid(row=2, column=3)

        self.ip_button = Button(master, text="fip now plays", command=self.nowPlaying, height=5, width=10)
        self.ip_button.grid(row=2, column=4)

        self.stop_button = Button(master, text="pause", command=self.stop, height=5, width = 10)
        self.stop_button.grid(row=2, column=5)

        self.up_button = Button(master, text="VOL >", command=self.up, height=5, width=10)
        self.up_button.grid(row=2, column=6)

        self.nowPlayingLabel = Label(master, text=" ", font=('Lato Light',18), fg = 'black')
        self.nowPlayingLabel.grid(row=4, columnspan=7, pady=0)

    def ipaddr(self):
        self.label.config(text=IP)

    def nowPlaying(self):
        feed=get_jsonparsed_data(url)
        # Get UUID of song now playing so we can look it up
        key = feed['levels'][0]['items'][3]
        title = feed['steps'][key]['title']
        try:
            artist=feed['steps'][key]['performers']
        except KeyError:
            try:
                artist=feed['steps'][key]['authors']
            except KeyError:
                artist="Artist unknown"
        nowPlayingText = 'fip now playing:\n'+title.title()+' by '+artist.title()
        self.nowPlayingLabel.config(text=nowPlayingText)

    def fip(self):
        print("fip!")
        self.label.config(text='fip - France Inter Paris')
        os.system("mpc play 1")

    def r4(self):
        print("BBC Radio 4 FM")
        self.label.config(text='BBC Radio 4 FM')
        os.system("mpc play 2")

    def x4(self):
        print("BBC Radio 4 Extra")
        self.label.config(text='BBC Radio 4 Extra')
        os.system("mpc play 7")

    def r6music(self):
        print("BBC 6music")
        self.label.config(text='BBC Radio 6Music')
        os.system("mpc play 3")

    def ws(self):
        print("BBC World Service News Stream")
        self.label.config(text='BBC World Service News')
        os.system("mpc play 4")

    def r2(self):
        print("BBC Radio 2")
        self.label.config(text='BBC Radio 2')
        os.system("mpc play 5")

    def r5(self):
        print("BBC Radio 5 Live")
        self.label.config(text='BBC Radio 5 Live')
        os.system("mpc play 6")

    def stop(self):
        print("stop MPC player")
        self.label.config(text='-paused-')
        os.system("mpc stop")

    def close(self):
        os.system("mpc stop")
        root.destroy()

    def up(self):
        os.system("mpc volume +30")

    def down(self):
        os.system("mpc volume -30")

    def shutdown(self):
        print("shutting down system")
        os.system("sudo shutdown now")

root = Tk()

#root.configure(background='cyan3')
root.configure(cursor='none')
root.attributes('-fullscreen', True)
my_gui = MyFirstGUI(root)

time1 = ''
clock = Label(root, font=('Lato Light', 48, 'bold'))
clock.grid(row=3, columnspan=7, pady=15)
def tick():
    global time1
    # get the current local time from the PC
    time2 = time.strftime('%H:%M:%S')
    # if time string has changed, update it
    if time2 != time1:
        time1 = time2
        clock.config(text=time2)
    # calls itself every 200 milliseconds
    # to update the time display as needed
    # could use >200 ms, but display gets jerky
    clock.after(200, tick)
tick()

root.mainloop()
This entry was posted in radio, Raspberry Pi and tagged , , , , , . Bookmark the permalink.

2 Responses to Fip Now Plays

  1. Chap says:

    Very cool!

    I see that FIP has an open API ( https://developers.radiofrance.fr/ ) and is doing regular hackathons.

    My skill is zero, otherwise I’d be playing FIP on my PasPi already…

  2. JW says:

    FIP fan here. Interesting re the “now playing” data you extracted from the FIP stream. I use various iOS and Mac apps to stream web radio, and some stations will easily show the song info in the app, like Classic FM http://media-ice.musicradio.com/ClassicFMMP3.m3u and Radio Paradise http://radioparadise.com/m3u/mp3-128.m3u , and some won’t, like the BBC stations as you mention. Although this BBC page claims that they do send the song name data for R1, R2, R3 and R6… https://www.bbc.co.uk/sounds/help/mobile/chrome/track_now_playing …unfortunately it does not show in any app I’ve used. Would be good if it did.
    I’m particularly keen to see the song names for FIP – I’m not a programmer though, I’m only using web radio streaming apps. I can only use radio streams as they come, so either they have the song name info or they don’t. The FIP stream http://direct.fipradio.fr/live/fip-midfi.mp3 doesn’t give me song names, yet you’re able to extract them as you detail above. For me the song name needs to be sent in the stream in the more conventional way, if this makes sense, as Radio Paradise etc do. I’ve just sent an email (in french) to FIP / Radio France asking about this. I’ll see what they say. Who knows, they might update their systems.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>