205 lines
6.1 KiB
Python
205 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
||
|
||
|
||
import gi
|
||
gi.require_version('Gtk', '4.0')
|
||
gi.require_version('Adw', '1')
|
||
import locale
|
||
|
||
from gi.repository import Gtk, Adw, GObject
|
||
|
||
from mcg.zeroconf import ZeroconfProvider
|
||
|
||
|
||
|
||
|
||
@Gtk.Template(resource_path='/xyz/suruatoel/mcg/ui/server-panel.ui')
|
||
class ServerPanel(Adw.Bin):
|
||
__gtype_name__ = 'McgServerPanel'
|
||
__gsignals__ = {
|
||
'connection-changed': (GObject.SIGNAL_RUN_FIRST, None, (str, int, str)),
|
||
'change-output-device': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,bool,)),
|
||
}
|
||
|
||
# Widgets
|
||
toolbar = Gtk.Template.Child()
|
||
connection_status_page = Gtk.Template.Child()
|
||
status_page = Gtk.Template.Child()
|
||
stats_page = Gtk.Template.Child()
|
||
devices_page = Gtk.Template.Child()
|
||
# Connection widgets
|
||
zeroconf_list = Gtk.Template.Child()
|
||
host_row = Gtk.Template.Child()
|
||
port_spinner = Gtk.Template.Child()
|
||
password_row = Gtk.Template.Child()
|
||
# Status widgets
|
||
status_file = Gtk.Template.Child()
|
||
status_audio = Gtk.Template.Child()
|
||
status_bitrate = Gtk.Template.Child()
|
||
status_error = Gtk.Template.Child()
|
||
# Stats widgets
|
||
stats_artists = Gtk.Template.Child()
|
||
stats_albums = Gtk.Template.Child()
|
||
stats_songs = Gtk.Template.Child()
|
||
stats_dbplaytime = Gtk.Template.Child()
|
||
stats_playtime = Gtk.Template.Child()
|
||
stats_uptime = Gtk.Template.Child()
|
||
# Audio ouptut devices widgets
|
||
output_devices = Gtk.Template.Child()
|
||
|
||
|
||
def __init__(self, **kwargs):
|
||
super().__init__(**kwargs)
|
||
self._none_label = ""
|
||
self._output_buttons = {}
|
||
self._is_selected = False
|
||
|
||
# Widgets
|
||
self._none_label = self.status_file.get_label()
|
||
|
||
# Zeroconf provider
|
||
self._zeroconf_provider = ZeroconfProvider()
|
||
self._zeroconf_provider.connect_signal(ZeroconfProvider.SIGNAL_SERVICE_NEW, self.on_new_service)
|
||
|
||
|
||
def set_selected(self, selected):
|
||
self._is_selected = selected
|
||
|
||
|
||
def get_toolbar(self):
|
||
return self.toolbar
|
||
|
||
|
||
def on_new_service(self, service):
|
||
name, host, port = service
|
||
|
||
row_button = Gtk.Button()
|
||
row_button.set_label(locale.gettext("use"))
|
||
row_button.connect("clicked", self.on_service_selected, host, port)
|
||
|
||
row = Adw.ActionRow()
|
||
row.set_title(name)
|
||
row.set_subtitle("{} ({})".format(host, port))
|
||
row.add_suffix(row_button)
|
||
|
||
self.zeroconf_list.insert(row, -1)
|
||
|
||
|
||
def on_service_selected(self, widget, host, port):
|
||
self.set_host(host)
|
||
self.set_port(port)
|
||
|
||
|
||
@Gtk.Template.Callback()
|
||
def on_host_entry_apply(self, widget):
|
||
self._call_back()
|
||
|
||
|
||
@Gtk.Template.Callback()
|
||
def on_port_spinner_value_changed(self, widget):
|
||
self._call_back()
|
||
|
||
|
||
def set_connection_sensitive(self, sensitive):
|
||
self.connection_status_page.set_sensitive(sensitive)
|
||
self.status_page.set_visible(not sensitive)
|
||
self.stats_page.set_visible(not sensitive)
|
||
self.devices_page.set_visible(not sensitive)
|
||
|
||
|
||
def set_host(self, host):
|
||
self.host_row.set_text(host)
|
||
|
||
|
||
def get_host(self):
|
||
return self.host_row.get_text()
|
||
|
||
|
||
def set_port(self, port):
|
||
self.port_spinner.set_value(port)
|
||
|
||
|
||
def get_port(self):
|
||
return self.port_spinner.get_value_as_int()
|
||
|
||
|
||
def set_password(self, password):
|
||
if password is None:
|
||
password = ""
|
||
self.password_row.set_text(password)
|
||
|
||
|
||
def get_password(self):
|
||
if self.password_row.get_text() == "":
|
||
return None
|
||
else:
|
||
return self.password_entry.get_text()
|
||
|
||
|
||
def on_output_device_toggled(self, widget, device):
|
||
self.emit('change-output-device', device, widget.get_active())
|
||
|
||
|
||
def set_status(self, file, audio, bitrate, error):
|
||
if file:
|
||
file = GObject.markup_escape_text(file)
|
||
else:
|
||
file = self._none_label
|
||
self.status_file.set_markup(file)
|
||
# Audio information
|
||
if audio:
|
||
parts = audio.split(":")
|
||
if len(parts) == 3:
|
||
audio = "{} Hz, {} bit, {} channels".format(parts[0], parts[1], parts[2])
|
||
else:
|
||
audio = self._none_label
|
||
self.status_audio.set_markup(audio)
|
||
# Bitrate
|
||
if bitrate:
|
||
bitrate = bitrate + " kb/s"
|
||
else:
|
||
bitrate = self._none_label
|
||
self.status_bitrate.set_markup(bitrate)
|
||
# Error
|
||
if error:
|
||
error = GObject.markup_escape_text(error)
|
||
else:
|
||
error = self._none_label
|
||
self.status_error.set_markup(error)
|
||
|
||
|
||
def set_stats(self, artists, albums, songs, dbplaytime, playtime, uptime):
|
||
self.stats_artists.set_text(str(artists))
|
||
self.stats_albums.set_text(str(albums))
|
||
self.stats_songs.set_text(str(songs))
|
||
self.stats_dbplaytime.set_text(str(dbplaytime))
|
||
self.stats_playtime.set_text(str(playtime))
|
||
self.stats_uptime.set_text(str(uptime))
|
||
|
||
|
||
def set_output_devices(self, devices):
|
||
device_ids = []
|
||
|
||
# Add devices
|
||
for device in devices:
|
||
device_ids.append(device.get_id())
|
||
if device.get_id() in self._output_buttons.keys():
|
||
self._output_buttons[device.get_id()].freeze_notify()
|
||
self._output_buttons[device.get_id()].set_active(device.is_enabled())
|
||
self._output_buttons[device.get_id()].thaw_notify()
|
||
else:
|
||
button = Gtk.CheckButton.new_with_label(device.get_name())
|
||
if device.is_enabled():
|
||
button.set_active(True)
|
||
handler = button.connect('toggled', self.on_output_device_toggled, device)
|
||
self.output_devices.insert(button, -1)
|
||
self._output_buttons[device.get_id()] = button
|
||
|
||
# Remove devices
|
||
for id in self._output_buttons.keys():
|
||
if id not in device_ids:
|
||
self.output_devices.remove(self._output_buttons[id].get_parent())
|
||
|
||
|
||
def _call_back(self):
|
||
self.emit('connection-changed', self.get_host(), self.get_port(), self.get_password(),)
|