#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib

GST_OK = False
try:
    gi.require_version('Gst', '1.0')
    from gi.repository import Gst
    Gst.init(None)
    GST_OK = True
except Exception:
    pass

STATIONS = [
    ('BBC Radio 1', 'http://stream.live.vc.bbcmedia.co.uk/bbc_radio_one'),
    ('BBC World Service', 'http://stream.live.vc.bbcmedia.co.uk/bbc_world_service'),
    ('Classic FM', 'http://media-ice.musicradio.com/ClassicFMMP3'),
    ('JAZZ FM', 'http://edge-bauerre.sharp-stream.com/jazzfm.mp3'),
    ('NPR News', 'https://npr-ice.streamguys1.com/live.mp3'),
    ('Smooth Radio', 'http://media-ice.musicradio.com/SmoothUKMP3'),
    ('Capital FM', 'http://media-ice.musicradio.com/CapitalMP3'),
    ('Heart FM', 'http://media-ice.musicradio.com/HeartMP3'),
]

class App(Gtk.Window):
    def __init__(self):
        super().__init__(title='Internet Radio Player')
        self.set_default_size(440, 380)
        self.pipeline = None
        self.playing_idx = None
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        vbox.set_margin_top(8); vbox.set_margin_bottom(8)
        vbox.set_margin_start(8); vbox.set_margin_end(8)
        self.add(vbox)
        self.now_lbl = Gtk.Label(label='Select a station and press Play')
        self.now_lbl.set_line_wrap(True)
        vbox.pack_start(self.now_lbl, False, False, 0)
        sw = Gtk.ScrolledWindow()
        self.store = Gtk.ListStore(str, str, bool)
        for name, url in STATIONS:
            self.store.append([name, url, False])
        tv = Gtk.TreeView(model=self.store)
        r_play = Gtk.CellRendererToggle(); r_play.set_radio(True)
        col_play = Gtk.TreeViewColumn('', r_play, active=2)
        tv.append_column(col_play)
        tv.append_column(Gtk.TreeViewColumn('Station', Gtk.CellRendererText(), text=0))
        tv.get_selection().connect('changed', self.on_select)
        sw.add(tv)
        vbox.pack_start(sw, True, True, 0)
        hb = Gtk.Box(spacing=8)
        self.play_btn = Gtk.Button(label='▶ Play')
        self.play_btn.connect('clicked', self.play)
        hb.pack_start(self.play_btn, True, True, 0)
        self.stop_btn = Gtk.Button(label='⏹ Stop')
        self.stop_btn.connect('clicked', self.stop)
        self.stop_btn.set_sensitive(False)
        hb.pack_start(self.stop_btn, True, True, 0)
        vbox.pack_start(hb, False, False, 0)
        if not GST_OK:
            vbox.add(Gtk.Label(label='GStreamer not available — cannot play streams'))
        self.selected = None
    def on_select(self, sel):
        model, it = sel.get_selected()
        if it: self.selected = (model[it][0], model[it][1], int(str(model.get_path(it))))
    def play(self, *_):
        if not GST_OK or not self.selected: return
        name, url, idx = self.selected
        self.stop()
        if GST_OK:
            try:
                self.pipeline = Gst.parse_launch(f'playbin uri="{url}"')
                self.pipeline.set_state(Gst.State.PLAYING)
                self.playing_idx = idx
                self.now_lbl.set_markup(f'<b>▶ {name}</b>')
                self.play_btn.set_sensitive(False)
                self.stop_btn.set_sensitive(True)
                for i, row in enumerate(self.store):
                    row[2] = (i == idx)
            except Exception as e:
                self.now_lbl.set_text(f'Error: {e}')
    def stop(self, *_):
        if self.pipeline:
            self.pipeline.set_state(Gst.State.NULL)
            self.pipeline = None
        self.playing_idx = None
        self.play_btn.set_sensitive(True)
        self.stop_btn.set_sensitive(False)
        self.now_lbl.set_text('Stopped')
        for row in self.store: row[2] = False

win = App()
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
