Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify playing sounds #76

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,22 +126,6 @@ put a clone of this repository (or a symlink) in this directory::
note that the files must be directly in this directory, not in a
subdirectory thereof.

starting with version 14, the new sound notification feature is available and enabled by default.
it requires the gobject introspection data for the gstreamer plugins base library installed in your system.
having no sound, check your system logs for:

Unable to import sound module. Playing sound is not available. Is GStreamer package installed?

Requiring GstAudio, version none: Typelib file for namespace 'GstAudio' (any version) not found

and eventually install it. for ubuntu::

sudo apt install gir1.2-gst-plugins-base-1.0

for fedora::

sudo dnf install gstreamer1-plugins-base

why?
====

Expand Down
78 changes: 31 additions & 47 deletions extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import Meta from "gi://Meta";
import Shell from "gi://Shell";
import Gvc from "gi://Gvc";
import GObject from "gi://GObject";
import Gst from "gi://Gst";
import GstAudio from "gi://GstAudio";

import * as Main from "resource:///org/gnome/shell/ui/main.js";
import * as PanelMenu from "resource:///org/gnome/shell/ui/panelMenu.js";
import { Extension } from "resource:///org/gnome/shell/extensions/extension.js";

import * as Signals from "resource:///org/gnome/shell/misc/signals.js";

const isPlayingSoundSupported = Gst != null && GstAudio != null;

const EXCLUDED_APPLICATION_IDS = [
"org.gnome.VolumeControl",
"org.PulseAudio.pavucontrol",
Expand All @@ -28,10 +24,11 @@ const MICROPHONE_ACTIVE_STYLE_CLASS = "screencast-indicator";
let initialised = false; // flag to avoid notifications on startup
let settings = null;
let microphone;
let audio_player;
let panel_button;

class Microphone extends Signals.EventEmitter {
constructor(dir) {
constructor() {
super();
this.active = null;
this.stream = null;
Expand All @@ -44,11 +41,6 @@ class Microphone extends Signals.EventEmitter {
this.mixer_control.connect("default-source-changed", refresh_cb);
this.mixer_control.connect("stream-added", refresh_cb);
this.mixer_control.connect("stream-removed", refresh_cb);
if (isPlayingSoundSupported) {
Gst.init(null);
this.on_sound = init_sound(dir, "on");
this.off_sound = init_sound(dir, "off");
}
this.refresh();
}

Expand Down Expand Up @@ -102,6 +94,29 @@ class Microphone extends Signals.EventEmitter {
}
}

class AudioPlayer {
#sound_on;
#sound_off;

constructor(dir) {
this.#sound_on = dir.get_child("sounds/on.ogg");
this.#sound_off = dir.get_child("sounds/off.ogg");
}

#play_sound(sound_file) {
let player = global.display.get_sound_player();
player.play_from_file(sound_file, "Toggle mute", null);
}

play_on() {
this.#play_sound(this.#sound_on);
}

play_off() {
this.#play_sound(this.#sound_off);
}
}

const MicrophonePanelButton = GObject.registerClass(
{ GTypeName: "MicrophonePanelButton" },
class extends PanelMenu.Button {
Expand All @@ -119,26 +134,6 @@ const MicrophonePanelButton = GObject.registerClass(
},
);

function init_sound(dir, name) {
const playbin = Gst.ElementFactory.make("playbin", null);
const path = dir.get_child(`sounds/${name}.ogg`).get_path();
const uri = Gst.filename_to_uri(path);
playbin.set_property("uri", uri);
const sink = Gst.ElementFactory.make("pulsesink", "sink");
playbin.set_property("audio-sink", sink);
playbin.set_volume(GstAudio.StreamVolumeFormat.LINEAR, 0.5);

// Fix audio node suspend-on-idle; stop playback at end-of-stream
const bus = playbin.get_bus();
bus.add_signal_watch();
bus.connect('message', (_bus, msg) => {
if (msg.type === Gst.MessageType.EOS)
playbin.set_state(Gst.State.NULL);
});

return playbin;
}

function get_icon_name(muted) {
// TODO: use -low and -medium icons based on .level
return muted
Expand Down Expand Up @@ -172,11 +167,8 @@ function on_activate({ give_feedback }) {
if (give_feedback) {
show_osd(null, false, microphone.level);
}
if (
isPlayingSoundSupported &&
settings.get_boolean("play-feedback-sounds")
) {
play_sound(microphone.on_sound);
if (settings.get_boolean("play-feedback-sounds")) {
audio_player.play_on();
}
} else {
// use a delay before muting; this makes push-to-talk work
Expand All @@ -193,26 +185,18 @@ function on_activate({ give_feedback }) {
if (give_feedback) {
show_osd(null, true, 0);
}
if (
isPlayingSoundSupported &&
settings.get_boolean("play-feedback-sounds")
) {
play_sound(microphone.off_sound);
if (settings.get_boolean("play-feedback-sounds")) {
audio_player.play_off();
}
});
}
}

function play_sound(sound) {
// Rewind in case the sound has played already.
sound.set_state(Gst.State.NULL);
sound.set_state(Gst.State.PLAYING);
}

export default class extends Extension {
enable() {
settings = this.getSettings();
microphone = new Microphone(this.dir);
microphone = new Microphone();
audio_player = new AudioPlayer(this.dir);
panel_button = new MicrophonePanelButton(this.metadata);
panel_button.visible = icon_should_be_visible(microphone.active);
const indicatorName = `${this.metadata.name} indicator`;
Expand Down
15 changes: 0 additions & 15 deletions prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import Gio from "gi://Gio";
import Gtk from "gi://Gtk";
import GObject from "gi://GObject";
import Adw from "gi://Adw";
import Gst from "gi://Gst";
import GstAudio from "gi://GstAudio";

import { ExtensionPreferences } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js";

Expand Down Expand Up @@ -144,18 +142,5 @@ export default class extends ExtensionPreferences {
Gio.SettingsBindFlags.DEFAULT,
);
group.add(feedbackSoundsSwitch);

// no sound alert row
const isPlayingSoundSupported = Gst != null && GstAudio != null;
if (!isPlayingSoundSupported) {
const playingSoundNotSupportedLabel = new Gtk.Label({
halign: Gtk.Align.START,
});
playingSoundNotSupportedLabel.set_markup(
"<span foreground='red'>WARNING. Playing sound is not supported on this system. Is GStreamer package installed?</span>",
);
playingSoundNotSupportedLabel.set_wrap(true);
group.add(playingSoundNotSupportedLabel);
}
}
}