mirror of
https://github.com/edu4rdshl/gnome-shell.git
synced 2026-07-17 23:24:51 +00:00
Any symbols (including class properties) that should be visible outside the module it's defined in need to be defined as global. For now gjs still allows the access for 'const', but get rid of the warnings spill now by changing it. https://bugzilla.gnome.org/show_bug.cgi?id=785084
216 lines
6.9 KiB
JavaScript
216 lines
6.9 KiB
JavaScript
const Clutter = imports.gi.Clutter;
|
|
const Gio = imports.gi.Gio;
|
|
const GLib = imports.gi.GLib;
|
|
const Lang = imports.lang;
|
|
const Meta = imports.gi.Meta;
|
|
const Shell = imports.gi.Shell;
|
|
const St = imports.gi.St;
|
|
|
|
const Main = imports.ui.main;
|
|
const ModalDialog = imports.ui.modalDialog;
|
|
|
|
const AudioDevice = {
|
|
HEADPHONES: 1 << 0,
|
|
HEADSET: 1 << 1,
|
|
MICROPHONE: 1 << 2
|
|
};
|
|
|
|
const AudioDeviceSelectionIface = '<node> \
|
|
<interface name="org.gnome.Shell.AudioDeviceSelection"> \
|
|
<method name="Open"> \
|
|
<arg name="devices" direction="in" type="as" /> \
|
|
</method> \
|
|
<method name="Close"> \
|
|
</method> \
|
|
<signal name="DeviceSelected"> \
|
|
<arg name="device" type="s" /> \
|
|
</signal> \
|
|
</interface> \
|
|
</node>';
|
|
|
|
var AudioDeviceSelectionDialog = new Lang.Class({
|
|
Name: 'AudioDeviceSelectionDialog',
|
|
Extends: ModalDialog.ModalDialog,
|
|
|
|
_init: function(devices) {
|
|
this.parent({ styleClass: 'audio-device-selection-dialog' });
|
|
|
|
this._deviceItems = {};
|
|
|
|
this._buildLayout();
|
|
|
|
if (devices & AudioDevice.HEADPHONES)
|
|
this._addDevice(AudioDevice.HEADPHONES);
|
|
if (devices & AudioDevice.HEADSET)
|
|
this._addDevice(AudioDevice.HEADSET);
|
|
if (devices & AudioDevice.MICROPHONE)
|
|
this._addDevice(AudioDevice.MICROPHONE);
|
|
|
|
if (this._selectionBox.get_n_children() < 2)
|
|
throw new Error('Too few devices for a selection');
|
|
},
|
|
|
|
destroy: function() {
|
|
this.parent();
|
|
},
|
|
|
|
_buildLayout: function(devices) {
|
|
let title = new St.Label({ style_class: 'audio-selection-title',
|
|
text: _("Select Audio Device"),
|
|
x_align: Clutter.ActorAlign.CENTER });
|
|
|
|
this.contentLayout.style_class = 'audio-selection-content';
|
|
this.contentLayout.add(title);
|
|
|
|
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
|
|
this.contentLayout.add(this._selectionBox, { expand: true });
|
|
|
|
this.addButton({ action: Lang.bind(this, this._openSettings),
|
|
label: _("Sound Settings") });
|
|
this.addButton({ action: Lang.bind(this, this.close),
|
|
label: _("Cancel"),
|
|
key: Clutter.Escape });
|
|
},
|
|
|
|
_getDeviceLabel: function(device) {
|
|
switch(device) {
|
|
case AudioDevice.HEADPHONES:
|
|
return _("Headphones");
|
|
case AudioDevice.HEADSET:
|
|
return _("Headset");
|
|
case AudioDevice.MICROPHONE:
|
|
return _("Microphone");
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
|
|
_getDeviceIcon: function(device) {
|
|
switch(device) {
|
|
case AudioDevice.HEADPHONES:
|
|
return 'audio-headphones-symbolic';
|
|
case AudioDevice.HEADSET:
|
|
return 'audio-headset-symbolic';
|
|
case AudioDevice.MICROPHONE:
|
|
return 'audio-input-microphone-symbolic';
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
|
|
_addDevice: function(device) {
|
|
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
|
|
vertical: true });
|
|
box.connect('notify::height',
|
|
function() {
|
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
|
|
function() {
|
|
box.width = box.height;
|
|
});
|
|
});
|
|
|
|
let icon = new St.Icon({ style_class: 'audio-selection-device-icon',
|
|
icon_name: this._getDeviceIcon(device) });
|
|
box.add(icon);
|
|
|
|
let label = new St.Label({ style_class: 'audio-selection-device-label',
|
|
text: this._getDeviceLabel(device),
|
|
x_align: Clutter.ActorAlign.CENTER });
|
|
box.add(label);
|
|
|
|
let button = new St.Button({ style_class: 'audio-selection-device',
|
|
can_focus: true,
|
|
child: box });
|
|
this._selectionBox.add(button);
|
|
|
|
button.connect('clicked', Lang.bind(this,
|
|
function() {
|
|
this.emit('device-selected', device);
|
|
this.close();
|
|
Main.overview.hide();
|
|
}));
|
|
},
|
|
|
|
_openSettings: function() {
|
|
let desktopFile = 'gnome-sound-panel.desktop'
|
|
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
|
|
|
|
if (!app) {
|
|
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
|
|
return;
|
|
}
|
|
|
|
this.close();
|
|
Main.overview.hide();
|
|
app.activate();
|
|
}
|
|
});
|
|
|
|
var AudioDeviceSelectionDBus = new Lang.Class({
|
|
Name: 'AudioDeviceSelectionDBus',
|
|
|
|
_init: function() {
|
|
this._audioSelectionDialog = null;
|
|
|
|
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
|
|
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection');
|
|
|
|
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
|
|
},
|
|
|
|
_onDialogClosed: function() {
|
|
this._audioSelectionDialog = null;
|
|
},
|
|
|
|
_onDeviceSelected: function(dialog, device) {
|
|
let connection = this._dbusImpl.get_connection();
|
|
let info = this._dbusImpl.get_info();
|
|
let deviceName = Object.keys(AudioDevice).filter(
|
|
function(dev) {
|
|
return AudioDevice[dev] == device;
|
|
})[0].toLowerCase();
|
|
connection.emit_signal(this._audioSelectionDialog._sender,
|
|
this._dbusImpl.get_object_path(),
|
|
info ? info.name : null,
|
|
'DeviceSelected',
|
|
GLib.Variant.new('(s)', [deviceName]));
|
|
},
|
|
|
|
OpenAsync: function(params, invocation) {
|
|
if (this._audioSelectionDialog) {
|
|
invocation.return_value(null);
|
|
return;
|
|
}
|
|
|
|
let [deviceNames] = params;
|
|
let devices = 0;
|
|
deviceNames.forEach(function(n) {
|
|
devices |= AudioDevice[n.toUpperCase()];
|
|
});
|
|
|
|
let dialog;
|
|
try {
|
|
dialog = new AudioDeviceSelectionDialog(devices);
|
|
} catch(e) {
|
|
invocation.return_value(null);
|
|
return;
|
|
}
|
|
dialog._sender = invocation.get_sender();
|
|
|
|
dialog.connect('closed', Lang.bind(this, this._onDialogClosed));
|
|
dialog.connect('device-selected',
|
|
Lang.bind(this, this._onDeviceSelected));
|
|
dialog.open();
|
|
|
|
this._audioSelectionDialog = dialog;
|
|
invocation.return_value(null);
|
|
},
|
|
|
|
CloseAsync: function(params, invocation) {
|
|
if (this._audioSelectionDialog &&
|
|
this._audioSelectionDialog._sender == invocation.get_sender())
|
|
this._audioSelectionDialog.close();
|
|
|
|
invocation.return_value(null);
|
|
}
|
|
});
|