129 lines
3.2 KiB
JavaScript
129 lines
3.2 KiB
JavaScript
|
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<sinklist.length; i++) {
|
||
|
let sink = sinklist[i];
|
||
|
if (sink === defsink)
|
||
|
continue;
|
||
|
let item = new PopupMenu.PopupMenuItem(sink.get_description());
|
||
|
item.connect('activate', () => {
|
||
|
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;
|
||
|
}
|