const ExtensionUtils = imports.misc.extensionUtils; const Meta = imports.gi.Meta; const Main = imports.ui.main; const PopupMenu = imports.ui.popupMenu; const Shell = imports.gi.Shell; const Me = ExtensionUtils.getCurrentExtension(); const Utils = Me.imports.utils; const AudioOutputSubMenu = class AudioOutputSubMenu extends PopupMenu.PopupSubMenuMenuItem { constructor() { super("Audio Output: Connecting...", true); this._control = Main.panel.statusArea.aggregateMenu._volume._control; this._controlSignal = this._control.connect('default-sink-changed', () => { this._updateDefaultSink(); }); this._updateDefaultSink(); this.menu.connect('open-state-changed', (menu, isOpen) => { if (isOpen) this._updateSinkList(); }); //Unless there is at least one item here, no 'open' will be emitted... let item = new PopupMenu.PopupMenuItem('Connecting...'); this.menu.addMenuItem(item); } _updateDefaultSink() { let defsink = this._control.get_default_sink(); //Unfortunately, Gvc neglects some pulse-devices, such as all "Monitor of ..." if (!defsink) this.label.set_text("Other"); else this.label.set_text(defsink.get_description()); } _updateSinkList() { this.menu.removeAll(); let defsink = this._control.get_default_sink(); let sinklist = this._control.get_sinks(); let control = this._control; for (let i=0; i { control.set_default_sink(sink); }); this.menu.addMenuItem(item); } if (sinklist.length == 0 || (sinklist.length == 1 && sinklist[0] === defsink)) { item = new PopupMenu.PopupMenuItem("No more Devices"); this.menu.addMenuItem(item); } } destroy() { this._control.disconnect(this._controlSignal); this.parent(); } } let sinkIndex = 0; let settings = null; let audioOutputSubMenu = null; function init () { sinkIndex = 0; settings = Utils.getSettings(); } function enable () { if (audioOutputSubMenu) { return; } audioOutputSubMenu = new AudioOutputSubMenu(); //Try to add the output-switcher right below the output slider... let volMen = Main.panel.statusArea.aggregateMenu._volume._volumeMenu; let items = volMen._getMenuItems(); let i = 0; while (i < items.length) if (items[i] === volMen._output.item) break; else i++; volMen.addMenuItem(audioOutputSubMenu, i+1); //Add keyboard shortcut for fast switching let keyBindingMode = null; if (Shell.ActionMode) { //KeyBindingMode was renamed to ActionMode in Gnome 3.15.3 keyBindingMode = Shell.ActionMode.ALL; } else { keyBindingMode = Shell.KeyBindingMode.ALL; } Main.wm.addKeybinding("switch-next-audio-output", settings, Meta.KeyBindingFlags.NONE, keyBindingMode, function(display, screen, window, binding) { let control = Main.panel.statusArea.aggregateMenu._volume._control; let sinklist = control.get_sinks(); if (sinklist.length === 0) { return; } sinkIndex++ if (sinkIndex >= sinklist.length) { sinkIndex = 0 } let sink = sinklist[sinkIndex]; control.set_default_sink(sink); } ); } function disable () { audioOutputSubMenu.destroy(); audioOutputSubMenu = null; }