dot/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/sound.js

202 lines
5.3 KiB
JavaScript

'use strict';
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
/**
* Used to ensure 'audible-bell' is enabled for fallback
*/
const WM_SETTINGS = new Gio.Settings({
schema_id: 'org.gnome.desktop.wm.preferences',
path: '/org/gnome/desktop/wm/preferences/'
});
var Sound = class Sound {
constructor() {
}
get backend() {
if (this._backend === undefined) {
// Prefer GSound
try {
this._gsound = new imports.gi.GSound.Context();
this._gsound.init(null);
this._backend = 'gsound';
// Try falling back to libcanberra, otherwise just re-run the test
// in case one or the other is installed later
} catch (e) {
if (GLib.find_program_in_path('canberra-gtk-play') !== null) {
this._canberra = new Gio.SubprocessLauncher({
flags: Gio.SubprocessFlags.NONE
});
this._backend = 'libcanberra';
} else {
return null;
}
}
}
return this._backend;
}
get playing() {
if (this._playing === undefined) {
this._playing = new Set();
}
return this._playing;
}
_canberraPlaySound(name, cancellable) {
return new Promise((resolve, reject) => {
let proc = this._canberra.spawnv(['canberra-gtk-play', '-i', name]);
proc.wait_check_async(cancellable, (proc, res) => {
try {
resolve(proc.wait_check_finish(res));
} catch (e) {
reject(e);
}
});
});
}
async _canberraLoopSound(name, cancellable) {
while (!cancellable.is_cancelled()) {
await this._canberraPlaySound(name, cancellable);
}
}
_gsoundPlaySound(name, cancellable) {
return new Promise((resolve, reject) => {
this._gsound.play_full(
{'event.id': name},
cancellable,
(source, res) => {
try {
resolve(source.play_full_finish(res));
} catch (e) {
reject(e);
}
}
);
});
}
async _gsoundLoopSound(name, cancellable) {
while (!cancellable.is_cancelled()) {
await this._gsoundPlaySound(name, cancellable);
}
}
_gdkPlaySound(name, cancellable) {
if (this._display === undefined) {
this._display = Gdk.Display.get_default();
}
let count = 0;
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => {
try {
if (count++ < 4 && !cancellable.is_cancelled()) {
this._display.beep();
return GLib.SOURCE_CONTINUE;
}
return GLib.SOURCE_REMOVE;
} catch (e) {
logError(e);
return GLib.SOURCE_REMOVE;
}
});
return !cancellable.is_cancelled();
}
_gdkLoopSound(name, cancellable) {
this._gdkPlaySound(name, cancellable);
GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
1500,
this._gdkPlaySound.bind(this, name, cancellable)
);
}
async playSound(name, cancellable) {
try {
if (!(cancellable instanceof Gio.Cancellable)) {
cancellable = new Gio.Cancellable();
}
this.playing.add(cancellable);
switch (this.backend) {
case 'gsound':
await this._gsoundPlaySound(name, cancellable);
break;
case 'canberra':
await this._canberraPlaySound(name, cancellable);
break;
default:
await this._gdkPlaySound(name, cancellable);
}
} catch (e) {
if (!e.code || e.code !== Gio.IOErrorEnum.CANCELLED) {
logError(e);
}
} finally {
this.playing.delete(cancellable);
}
}
async loopSound(name, cancellable) {
try {
if (!(cancellable instanceof Gio.Cancellable)) {
cancellable = new Gio.Cancellable();
}
this.playing.add(cancellable);
switch (this.backend) {
case 'gsound':
await this._gsoundLoopSound(name, cancellable);
break;
case 'canberra':
await this._canberraLoopSound(name, cancellable);
break;
default:
await this._gdkLoopSound(name, cancellable);
}
} catch (e) {
if (!e.code || e.code !== Gio.IOErrorEnum.CANCELLED) {
logError(e);
}
} finally {
this.playing.delete(cancellable);
}
}
destroy() {
for (let cancellable of this.playing) {
cancellable.cancel();
}
}
};
/**
* The service class for this component
*/
var Component = Sound;