diff --git a/data/gtk.glade b/data/gtk.glade
index cc6be64..8cbb041 100644
--- a/data/gtk.glade
+++ b/data/gtk.glade
@@ -905,6 +905,50 @@
1
+
+
+
+ page2
+ Audio Devices
+ 2
+
+
True
diff --git a/mcg/client.py b/mcg/client.py
index 22cf6b7..ca9102d 100644
--- a/mcg/client.py
+++ b/mcg/client.py
@@ -114,6 +114,8 @@ class Client(Base):
SIGNAL_LOAD_ALBUMS = 'load-albums'
# Signal: load playlist
SIGNAL_LOAD_PLAYLIST = 'load-playlist'
+ # Signal: load audio output devices
+ SIGNAL_LOAD_OUTPUT_DEVICES = 'load-output-devices'
# Signal: error
SIGNAL_ERROR = 'error'
@@ -182,6 +184,19 @@ class Client(Base):
self._add_action(self._get_stats)
+ def get_output_devices(self):
+ """Determine the list of audio output devices."""
+ self._logger.info("get output devices")
+ self._add_action(self._get_output_devices)
+
+
+ def enable_output_device(self, device, enabled):
+ """Enable/disable an audio output device."""
+ self._logger.info("enable output device")
+ self._add_action(self._enable_output_device, device, enabled)
+
+
+
def load_albums(self):
self._logger.info("load albums")
self._add_action(self._load_albums)
@@ -351,6 +366,9 @@ class Client(Base):
self.load_albums()
self.load_playlist()
self.get_status()
+ if subsystems['changed'] == 'output':
+ self.get_output_devices()
+ self.get_status()
def _noidle(self):
@@ -447,6 +465,24 @@ class Client(Base):
self._callback(Client.SIGNAL_STATS, artists, albums, songs, dbplaytime, playtime, uptime)
+ def _get_output_devices(self):
+ """Action: Perform the real loading of output devices."""
+ devices = []
+ for output in self._parse_list(self._call('outputs'), ['outputid']):
+ device = OutputDevice(output['outputid'], output['outputname'])
+ device.set_enabled(int(output['outputenabled']) == 1)
+ devices.append(device)
+ self._callback(Client.SIGNAL_LOAD_OUTPUT_DEVICES, devices)
+
+
+ def _enable_output_device(self, device, enabled):
+ """Action: Perform the real enabling/disabling of an output device."""
+ if enabled:
+ self._call('enableoutput ', device.get_id())
+ else:
+ self._call('disableoutput ', device.get_id())
+
+
def _load_albums(self):
"""Action: Perform the real update."""
self._albums = {}
@@ -737,6 +773,33 @@ class Client(Base):
+class OutputDevice:
+
+
+ def __init__(self, id, name):
+ self._id = id
+ self._name = name
+ self._enabled = None
+
+
+ def get_id(self):
+ return self._id
+
+
+ def get_name(self):
+ return self._name
+
+
+ def set_enabled(self, enabled):
+ self._enabled = enabled
+
+
+ def is_enabled(self):
+ return self._enabled
+
+
+
+
class MCGAlbum:
DEFAULT_ALBUM = 'Various'
_FILE_NAMES = ['cover', 'folder']
diff --git a/mcg/widgets.py b/mcg/widgets.py
index e1e12d2..54bc881 100644
--- a/mcg/widgets.py
+++ b/mcg/widgets.py
@@ -145,6 +145,7 @@ class Window():
self._header_bar.connect('toolbar-playpause', self.on_header_bar_playpause)
self._header_bar.connect('toolbar-set-volume', self.on_header_bar_set_volume)
self._connection_panel.connect('connection-changed', self.on_connection_panel_connection_changed)
+ self._panels[Window._PANEL_INDEX_SERVER].connect('change-output-device', self.on_server_panel_output_device_changed)
self._panels[Window._PANEL_INDEX_COVER].connect('toggle-fullscreen', self.on_cover_panel_toggle_fullscreen)
self._panels[Window._PANEL_INDEX_COVER].connect('tracklist-size-changed', self.on_cover_panel_tracklist_size_changed)
self._panels[Window._PANEL_INDEX_COVER].connect('set-song', self.on_cover_panel_set_song)
@@ -161,6 +162,7 @@ class Window():
self._mcg.connect_signal(client.Client.SIGNAL_CONNECTION, self.on_mcg_connect)
self._mcg.connect_signal(client.Client.SIGNAL_STATUS, self.on_mcg_status)
self._mcg.connect_signal(client.Client.SIGNAL_STATS, self.on_mcg_stats)
+ self._mcg.connect_signal(client.Client.SIGNAL_LOAD_OUTPUT_DEVICES, self.on_mcg_load_output_devices)
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_PLAYLIST, self.on_mcg_load_playlist)
self._mcg.connect_signal(client.Client.SIGNAL_LOAD_ALBUMS, self.on_mcg_load_albums)
self._mcg.connect_signal(client.Client.SIGNAL_ERROR, self.on_mcg_error)
@@ -302,6 +304,10 @@ class Window():
self._mcg.play_album_from_playlist(album)
+ def on_server_panel_output_device_changed(self, widget, device, enabled):
+ self._mcg.enable_output_device(device, enabled)
+
+
def on_cover_panel_toggle_fullscreen(self, widget):
if not self._fullscreened:
self._appwindow.fullscreen()
@@ -351,6 +357,7 @@ class Window():
self._mcg.load_albums()
self._mcg.get_status()
self._mcg.get_stats()
+ self._mcg.get_output_devices()
self._connect_action.set_state(GLib.Variant.new_boolean(True))
self._play_action.set_enabled(True)
self._clear_playlist_action.set_enabled(True)
@@ -390,6 +397,10 @@ class Window():
self._panels[Window._PANEL_INDEX_SERVER].set_stats(artists, albums, songs, dbplaytime, playtime, uptime)
+ def on_mcg_load_output_devices(self, devices):
+ self._panels[Window._PANEL_INDEX_SERVER].set_output_devices(devices)
+
+
def on_mcg_load_playlist(self, playlist):
self._panels[self._PANEL_INDEX_PLAYLIST].set_playlist(self._connection_panel.get_host(), playlist)
@@ -800,10 +811,14 @@ class ConnectionPanel(GObject.GObject):
class ServerPanel(GObject.GObject):
+ __gsignals__ = {
+ 'change-output-device': (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,bool,)),
+ }
def __init__(self, builder):
GObject.GObject.__init__(self)
+ self._output_buttons = {}
# Widgets
self._panel = builder.get_object('server-panel')
@@ -824,6 +839,9 @@ class ServerPanel(GObject.GObject):
self._stats_playtime = builder.get_object('server-stats-playtime')
self._stats_uptime = builder.get_object('server-stats-uptime')
+ # Audio ouptut devices widgets
+ self._output_devices = builder.get_object('server-output-devices')
+
def get(self):
return self._panel
@@ -833,6 +851,10 @@ class ServerPanel(GObject.GObject):
return self._toolbar
+ 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 not file:
file = ""
@@ -866,6 +888,32 @@ class ServerPanel(GObject.GObject):
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(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
+ self._output_devices.show_all()
+
+ # 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())
+
+
+
class CoverPanel(GObject.GObject):