#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
from gi.repository import Gtk, Gst
import time
class RadioApp(Gtk.Window):
def __init__(self):
super().__init__()
self.connect("destroy", Gtk.main_quit)
self.init_ui()
self.init_gstreamer()
def init_ui(self):
self.set_size_request(500, 650)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_title('Python3 + GTK3 + Gstreamer Demo')
vbox = Gtk.Box()
vbox.set_orientation(Gtk.Orientation.VERTICAL)
hbox = Gtk.Box()
hbox.set_orientation(Gtk.Orientation.HORIZONTAL)
btn_radio = Gtk.Button.new_with_label("Radio")
btn_atc = Gtk.Button.new_with_label("Air Traffic Control")
btn_police = Gtk.Button.new_with_label("Police")
btn_atc.connect("clicked", self.load_atc)
btn_radio.connect("clicked", self.load_radio)
btn_police.connect("clicked", self.load_police)
hbox.pack_start(btn_radio, False, False, 0)
hbox.pack_start(btn_atc, False, False, 0)
hbox.pack_start(btn_police, False, False, 0)
vbox.pack_start(hbox, False, False, 0)
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled_window2 = Gtk.ScrolledWindow()
vbox.pack_start(scrolled_window, True, True, 0)
vbox.pack_start(scrolled_window2, True, True, 0)
self.store = Gtk.ListStore(str, str, str)
self.load_radio(None) # Load initial radio stations
self.treeview = Gtk.TreeView(model=self.store)
self.treeview.connect("row-activated", self.on_activated)
#self.treeview.set_rules_hint(True)
scrolled_window.add(self.treeview)
renderer_text = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Station", renderer_text, text=0)
column.set_sort_column_id(0)
self.treeview.append_column(column)
renderer_text = Gtk.CellRendererText()
column = Gtk.TreeViewColumn("Description", renderer_text, text=1)
column.set_sort_column_id(1)
self.treeview.append_column(column)
self.listbox = Gtk.ListBox()
scrolled_window2.add(self.listbox)
#vbox.pack_start(self.listbox, True, True, 0)
global nowplaying
nowplaying = Gtk.Label()
vbox.pack_start(nowplaying, False, False, 0)
global statusbar
statusbar = Gtk.Statusbar()
vbox.pack_start(statusbar, False, False, 0)
hbox = Gtk.HBox()
hbox.pack_end(statusbar, True, True, 0)
global btn
btn = Gtk.Button.new_with_label("Stop")
btn.connect("clicked", self.stop)
hbox.pack_end(btn, False, False, 0)
global btn2
btn2 = Gtk.Button.new_with_label("Vol -")
btn2.connect("clicked", self.voldown)
hbox.pack_end(btn2, False, False, 0)
global btn3
btn3 = Gtk.Button.new_with_label("Vol +")
btn3.connect("clicked", self.volup)
hbox.pack_end(btn3, False, False, 0)
#hbox.pack_end(btn_radio, False, False, 0)
#hbox.pack_end(btn_atc, False, False, 0)
#hbox.pack_end(btn_police, False, False, 0)
vbox.pack_start(hbox, False, False, 0)
self.add(vbox)
self.show_all()
def init_gstreamer(self):
Gst.init(None)
self.playbin = Gst.ElementFactory.make("playbin", "player")
bus = self.playbin.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
bus.connect("message::tag", self.bus_message_tag)
#bus.connect("message", self.bus_message_tag)
def bus_message_tag(self, bus, message):
taglist = message.parse_tag()
tag_string = taglist.get_string(Gst.TAG_TITLE)
print(tag_string[1])
if tag_string[1] is None:
nowplaying.set_text("No Stream Info")
else:
nowplaying.set_text(tag_string[1])
label = Gtk.Label()
label.set_text(tag_string[1] +" : "+ time.ctime())
self.listbox.add(label)
self.show_all()
#for key in taglist.keys():
# print(key.ljust(15) + " : " + str(taglist[key]))
#t = taglist.get_string("title")
#nowplaying.set_text(t)
def voldown(self, widget):
self.playbin.set_property("volume", self.playbin.get_property("volume") - 0.1)
def volup(self, widget):
self.playbin.set_property("volume", self.playbin.get_property("volume") + 0.1)
print(self.playbin.get_property("volume"))
def stop(self, widget):
txt = btn.get_label()
if txt == "Stop":
print("Stop selected")
btn.set_label("Play")
self.playbin.set_state(Gst.State.NULL)
elif txt == "Play":
print("Play selected")
btn.set_label("Stop")
self.playbin.set_state(Gst.State.PLAYING)
def on_activated(self, treeView, path, column):
txt = btn.get_label()
model = treeView.get_model()
iter = model.get_iter(path)
if iter:
text = model.get_value(iter, 2)
#statusbar.push(0, text)
self.playbin.set_state(Gst.State.NULL)
self.playbin.set_property("uri", text)
self.playbin.set_state(Gst.State.PLAYING)
if txt == "Play":
btn.set_label("Stop")
def load_atc(self, widget):
self.store.clear()
for station in atc:
self.store.append(list(station))
def load_radio(self, widget):
self.store.clear()
for station in stations:
self.store.append(list(station))
def load_police(self, widget):
self.store.clear()
for station in police:
self.store.append(list(station))
if __name__ == "__main__":
stations = [('Deep House Radio','Bucharest - Romania','https://streaming-01.xtservers.com:7000/stream'),
('HIRU FM', 'Sri Lanka', "https://radio.lotustechnologieslk.net:2020/stream/hirufmgarden"),
('SHAA FM','Sri Lanka','https://radio.lotustechnologieslk.net:2020/stream/shaafmgarden'),
('Sirasa FM','Sri Lanka','http://live.trusl.com:1170/;;'),
('Hot 80s Hits', 'ShoutCast', 'http://216.245.210.78:9900/stream'),
('Heartbeat FM', 'Lovesongs & Heartbreakers', 'http://cast5.magicstreams.gr:8010/stream')]
atc = [('Tokyo International Airport', 'Japan', 'https://s1-bos.liveatc.net/rjtt_app_dep?nocache=2024062002221314785"'),
('Kuwait International Airport', 'Kuwait City', 'http://d.liveatc.net/okbk'),
('Esenboga International Airport', 'Ankara, Turkey', 'http://d.liveatc.net/ltac'),
('TTC','Toronto','https://broadcastify.cdnstream1.com/31629')]
police = [('Bay Area','San Francisco','https://broadcastify.cdnstream1.com/34756')]
app = RadioApp()
Gtk.main()