9d941f8202
xgettext gained some support for template strings, and no longer fails when encountering '/' somewhere between backticks. Unfortunately its support is still buggy as hell, and it is now silently dropping translatable strings, yay. I hate making the code worse, but until xgettext really gets its shit together, the only viable way forward seems to be to not use template strings in any files listed in POTFILES. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1014
196 lines
6.3 KiB
JavaScript
196 lines
6.3 KiB
JavaScript
/* exported AudioDeviceSelectionDBus */
|
|
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
|
|
|
const Dialog = imports.ui.dialog;
|
|
const Main = imports.ui.main;
|
|
const ModalDialog = imports.ui.modalDialog;
|
|
|
|
const { loadInterfaceXML } = imports.misc.fileUtils;
|
|
|
|
var AudioDevice = {
|
|
HEADPHONES: 1 << 0,
|
|
HEADSET: 1 << 1,
|
|
MICROPHONE: 1 << 2,
|
|
};
|
|
|
|
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
|
|
|
|
var AudioDeviceSelectionDialog = GObject.registerClass({
|
|
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } },
|
|
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
|
|
_init(devices) {
|
|
super._init({ 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');
|
|
}
|
|
|
|
_buildLayout() {
|
|
let content = new Dialog.MessageDialogContent({
|
|
title: _('Select Audio Device'),
|
|
});
|
|
|
|
this._selectionBox = new St.BoxLayout({
|
|
style_class: 'audio-selection-box',
|
|
x_expand: true,
|
|
});
|
|
content.add_child(this._selectionBox);
|
|
|
|
this.contentLayout.add_child(content);
|
|
|
|
if (Main.sessionMode.allowSettings) {
|
|
this.addButton({ action: this._openSettings.bind(this),
|
|
label: _("Sound Settings") });
|
|
}
|
|
this.addButton({ action: this.close.bind(this),
|
|
label: _("Cancel"),
|
|
key: Clutter.KEY_Escape });
|
|
}
|
|
|
|
_getDeviceLabel(device) {
|
|
switch (device) {
|
|
case AudioDevice.HEADPHONES:
|
|
return _("Headphones");
|
|
case AudioDevice.HEADSET:
|
|
return _("Headset");
|
|
case AudioDevice.MICROPHONE:
|
|
return _("Microphone");
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
_getDeviceIcon(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(device) {
|
|
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
|
|
vertical: true });
|
|
box.connect('notify::height', () => {
|
|
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
|
|
box.width = box.height;
|
|
return GLib.SOURCE_REMOVE;
|
|
});
|
|
});
|
|
|
|
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', () => {
|
|
this.emit('device-selected', device);
|
|
this.close();
|
|
Main.overview.hide();
|
|
});
|
|
}
|
|
|
|
_openSettings() {
|
|
let desktopFile = 'gnome-sound-panel.desktop';
|
|
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
|
|
|
|
if (!app) {
|
|
log('Settings panel for desktop file %s could not be loaded!'.format(desktopFile));
|
|
return;
|
|
}
|
|
|
|
this.close();
|
|
Main.overview.hide();
|
|
app.activate();
|
|
}
|
|
});
|
|
|
|
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
|
|
constructor() {
|
|
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() {
|
|
this._audioSelectionDialog = null;
|
|
}
|
|
|
|
_onDeviceSelected(dialog, device) {
|
|
let connection = this._dbusImpl.get_connection();
|
|
let info = this._dbusImpl.get_info();
|
|
let deviceName = Object.keys(AudioDevice).filter(
|
|
dev => 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(params, invocation) {
|
|
if (this._audioSelectionDialog) {
|
|
invocation.return_value(null);
|
|
return;
|
|
}
|
|
|
|
let [deviceNames] = params;
|
|
let devices = 0;
|
|
deviceNames.forEach(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', this._onDialogClosed.bind(this));
|
|
dialog.connect('device-selected',
|
|
this._onDeviceSelected.bind(this));
|
|
dialog.open();
|
|
|
|
this._audioSelectionDialog = dialog;
|
|
invocation.return_value(null);
|
|
}
|
|
|
|
CloseAsync(params, invocation) {
|
|
if (this._audioSelectionDialog &&
|
|
this._audioSelectionDialog._sender == invocation.get_sender())
|
|
this._audioSelectionDialog.close();
|
|
|
|
invocation.return_value(null);
|
|
}
|
|
};
|