From 1bdbc9eed666ee292aba8debdc24d1ff569e9408 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Fri, 22 Nov 2024 19:13:01 +0100 Subject: [PATCH 1/8] Added new parameters for soundcard and input choice --- .../files/MuteToggler@jebeaudet.com/applet.js | 37 +++++++++++++++++-- .../settings-schema.json | 18 +++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index b13c0fad0ac..e8d20487212 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -55,6 +55,16 @@ MyApplet.prototype = { this.set_applet_tooltip(_("Click to mute/unmute microphone")); try { + this.settings.bindProperty(Settings.BindingDirection.IN, + "soundcard", + "soundcard", + this.on_settings_changed, + null); + this.settings.bindProperty(Settings.BindingDirection.IN, + "input", + "input", + this.on_settings_changed, + null); this.settings.bindProperty(Settings.BindingDirection.IN, "keybinding", "keybinding", @@ -97,15 +107,34 @@ MyApplet.prototype = { if (this.settings) { this.on_settings_changed(); } + + // per default use first soundcard + this.soundcard_id = "0"; + let soundcard_list_cmd = "cat /proc/asound/cards"; + let [res, stdout] = GLib.spawn_command_line_sync(soundcard_list_cmd); + + if (res) { + // Split the result into lines + let lines = stdout.toString().split('\n'); + + // Filter lines that contain the soundcard search string + let filteredLines = lines.filter(line => line.includes(this.soundcard)); + + // Extract the field after splitting by space and getting the second field (index 1) + this.soundcard_id = filteredLines.map(line => line.split(' ')[1]); + } + + log("Use soundcard id: '" + this.soundcard_id + "'"); + + this.amixer = "amixer -c " + this.soundcard_id; - this.amixer = "amixer"; const parameters = ["", " -D pulse"]; for (let param of parameters) { let cmd = this.amixer + param + " scontrols"; log("Test mixer command '" + cmd + "'"); // TODO: Make it async. let [res, stdout] = GLib.spawn_command_line_sync(cmd); - if (res && to_string(stdout).indexOf("'Capture'") != -1) { + if (res && to_string(stdout).indexOf(this.input) != -1) { this.amixer += param; log("Use mixer command '" + this.amixer + "'"); break; @@ -146,7 +175,7 @@ MyApplet.prototype = { let cmd = [ "sh", "-c", - this.amixer + " sget Capture" + this.amixer + " sget " + this.input ]; Util.spawn_async(cmd, (stdout) => { try{ @@ -197,7 +226,7 @@ MyApplet.prototype = { let cmd = [ "sh", "-c", - this.amixer + " set Capture toggle" + this.amixer + " set " + this.input + " toggle" ]; Util.spawn_async(cmd, (stdout) => { this.is_audio_muted(); diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json index fbbc347488a..a4bc8d10a01 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json @@ -1,4 +1,22 @@ { + "section_soundcard": { + "type": "section", + "description": "Soundcard settings", + "keys": [ + "soundcard", + "input" + ] + }, + "soundcard": { + "type": "entry", + "description": "Soundcard identifier", + "default": "USB-Audio - USB" + }, + "input": { + "type": "entry", + "description": "Input name (e.g. Capture, Mic, ...)", + "default": "Mic" + }, "section_keybinding": { "type": "section", "description": "Keyboard shortcuts", From e9cd3e2790477f5a32d09cbf2999ce3da79bbf62 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Sat, 23 Nov 2024 10:28:58 +0100 Subject: [PATCH 2/8] Implicit input eval and improved soundcard eval --- .../files/MuteToggler@jebeaudet.com/applet.js | 81 +++++++++++++------ .../settings-schema.json | 12 +-- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index e8d20487212..9aaf8194381 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -16,7 +16,9 @@ const APPNAME = "MuteToggler"; const UUID = APPNAME + "@jebeaudet.com"; const HOME_DIR = GLib.get_home_dir(); -var VERBOSE = true; // VERBOSE value will be changed according to this applet settings. +var VERBOSE = false; // VERBOSE value will be changed according to this applet settings. + +const POTENTIAL_INPUTS = ["'Capture'", "'Mic'"]; /** * Usage of log and logError: @@ -41,6 +43,15 @@ function _(str) { return gettext(str); } +function findFirstMatch(searchStrings, checkString) { + for (let i = 0; i < searchStrings.length; i++) { + if (checkString.includes(searchStrings[i])) { + return searchStrings[i]; + } + } + return null; // Return null if no match is found +} + MyApplet.prototype = { __proto__: Applet.IconApplet.prototype, @@ -60,11 +71,6 @@ MyApplet.prototype = { "soundcard", this.on_settings_changed, null); - this.settings.bindProperty(Settings.BindingDirection.IN, - "input", - "input", - this.on_settings_changed, - null); this.settings.bindProperty(Settings.BindingDirection.IN, "keybinding", "keybinding", @@ -108,26 +114,10 @@ MyApplet.prototype = { this.on_settings_changed(); } - // per default use first soundcard - this.soundcard_id = "0"; - let soundcard_list_cmd = "cat /proc/asound/cards"; - let [res, stdout] = GLib.spawn_command_line_sync(soundcard_list_cmd); - - if (res) { - // Split the result into lines - let lines = stdout.toString().split('\n'); - - // Filter lines that contain the soundcard search string - let filteredLines = lines.filter(line => line.includes(this.soundcard)); - - // Extract the field after splitting by space and getting the second field (index 1) - this.soundcard_id = filteredLines.map(line => line.split(' ')[1]); - } - - log("Use soundcard id: '" + this.soundcard_id + "'"); - - this.amixer = "amixer -c " + this.soundcard_id; + this.amixer = "amixer"; + this.evaluate_soundcard(); + const parameters = ["", " -D pulse"]; for (let param of parameters) { let cmd = this.amixer + param + " scontrols"; @@ -141,6 +131,8 @@ MyApplet.prototype = { } } + this.evaluate_input(); + this.applet_is_running = true; this.set_not_muted_icon(); this.is_audio_muted(); @@ -221,6 +213,45 @@ MyApplet.prototype = { } }, + evaluate_soundcard: function() { + // only use specific soundcard if searchstring is not empty + if (this.soundcard.trim() !== '') + { + // per default use first soundcard + this.soundcard_id = "0"; + + let soundcard_list_cmd = "cat /proc/asound/cards"; + let [res, stdout] = GLib.spawn_command_line_sync(soundcard_list_cmd); + + if (res) { + // Split the result into lines + let lines = stdout.toString().split('\n'); + + // Filter lines that contain the soundcard search string + let filteredLines = lines.filter(line => line.includes(this.soundcard)); + + // Extract the field after splitting by space and getting the second field (index 1) + this.soundcard_id = filteredLines.map(line => line.split(' ')[1]); + } + log("Use specific soundcard id: '" + this.soundcard_id + "'"); + + this.amixer = this.amixer + " -c " + this.soundcard_id; + } + }, + + evaluate_input: function() { + this.input = POTENTIAL_INPUTS[0]; + let [res, stdout] = GLib.spawn_command_line_sync(this.amixer); + if (res) { + let found_input = findFirstMatch(POTENTIAL_INPUTS, to_string(stdout)); + if (found_input !== null) + { + this.input = found_input; + } + } + log("Use input: " + this.input); + }, + on_applet_clicked: function(event) { try{ let cmd = [ diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json index a4bc8d10a01..14d58dc073b 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/settings-schema.json @@ -3,19 +3,13 @@ "type": "section", "description": "Soundcard settings", "keys": [ - "soundcard", - "input" + "soundcard" ] }, "soundcard": { "type": "entry", - "description": "Soundcard identifier", - "default": "USB-Audio - USB" - }, - "input": { - "type": "entry", - "description": "Input name (e.g. Capture, Mic, ...)", - "default": "Mic" + "description": "Soundcard search string in /proc/asound/cards (empty: deactivate)", + "default": "" }, "section_keybinding": { "type": "section", From 7376897f4d58a1c45da8895bd67cdd1cf39d8226 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Sat, 23 Nov 2024 10:35:26 +0100 Subject: [PATCH 3/8] reordered. input must be evaluated before -D pulse eval --- .../files/MuteToggler@jebeaudet.com/applet.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index 9aaf8194381..69ce37b3e71 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -16,7 +16,7 @@ const APPNAME = "MuteToggler"; const UUID = APPNAME + "@jebeaudet.com"; const HOME_DIR = GLib.get_home_dir(); -var VERBOSE = false; // VERBOSE value will be changed according to this applet settings. +var VERBOSE = true; // VERBOSE value will be changed according to this applet settings. const POTENTIAL_INPUTS = ["'Capture'", "'Mic'"]; @@ -116,8 +116,9 @@ MyApplet.prototype = { this.amixer = "amixer"; - this.evaluate_soundcard(); - + this.evaluate_soundcard(); + this.evaluate_input(); + const parameters = ["", " -D pulse"]; for (let param of parameters) { let cmd = this.amixer + param + " scontrols"; @@ -130,8 +131,6 @@ MyApplet.prototype = { break; } } - - this.evaluate_input(); this.applet_is_running = true; this.set_not_muted_icon(); From e5db34c7d0212ae9050d746a4a0ecdfd73f62c0c Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Sat, 23 Nov 2024 13:24:56 +0100 Subject: [PATCH 4/8] Changes due to code review --- .../files/MuteToggler@jebeaudet.com/applet.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index 69ce37b3e71..3deac664928 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -214,7 +214,7 @@ MyApplet.prototype = { evaluate_soundcard: function() { // only use specific soundcard if searchstring is not empty - if (this.soundcard.trim() !== '') + if (this.soundcard.trim().length > 0) { // per default use first soundcard this.soundcard_id = "0"; @@ -224,7 +224,7 @@ MyApplet.prototype = { if (res) { // Split the result into lines - let lines = stdout.toString().split('\n'); + let lines = to_string(stdout).split('\n'); // Filter lines that contain the soundcard search string let filteredLines = lines.filter(line => line.includes(this.soundcard)); From b98b9cf40e4914529c78f952a63bb5719ab03379 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Sat, 23 Nov 2024 15:38:49 +0100 Subject: [PATCH 5/8] Async calls via Util.spawn_async --- .../files/MuteToggler@jebeaudet.com/applet.js | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index 3deac664928..46654365225 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -55,7 +55,7 @@ function findFirstMatch(searchStrings, checkString) { MyApplet.prototype = { __proto__: Applet.IconApplet.prototype, - _init: function(metadata, orientation, panel_height, instance_id) { + _init: async function(metadata, orientation, panel_height, instance_id) { try { this.settings = new Settings.AppletSettings(this, UUID, instance_id); VERBOSE = this.settings.getValue("verbose"); @@ -115,9 +115,8 @@ MyApplet.prototype = { } this.amixer = "amixer"; - - this.evaluate_soundcard(); - this.evaluate_input(); + await this.evaluate_soundcard(); + await this.evaluate_input(); const parameters = ["", " -D pulse"]; for (let param of parameters) { @@ -213,42 +212,54 @@ MyApplet.prototype = { }, evaluate_soundcard: function() { - // only use specific soundcard if searchstring is not empty - if (this.soundcard.trim().length > 0) - { - // per default use first soundcard - this.soundcard_id = "0"; - - let soundcard_list_cmd = "cat /proc/asound/cards"; - let [res, stdout] = GLib.spawn_command_line_sync(soundcard_list_cmd); - - if (res) { - // Split the result into lines - let lines = to_string(stdout).split('\n'); + return new Promise((resolve, reject) => { + // only use specific soundcard if searchstring is not empty + if (this.soundcard.trim().length > 0) { + // per default use first soundcard + this.soundcard_id = "0"; + + let soundcard_list_cmd = + Util.spawn_async(["sh","-c","cat /proc/asound/cards"], (stdout) => { + try { + // Split the result into lines + let lines = stdout.split('\n'); - // Filter lines that contain the soundcard search string - let filteredLines = lines.filter(line => line.includes(this.soundcard)); + // Filter lines that contain the soundcard search string + let filteredLines = lines.filter(line => line.includes(this.soundcard)); - // Extract the field after splitting by space and getting the second field (index 1) - this.soundcard_id = filteredLines.map(line => line.split(' ')[1]); + // Extract the field after splitting by space and getting the second field (index 1) + if (filteredLines.length > 0) { + this.soundcard_id = filteredLines[0].split(' ')[1]; + } + log("Use specific soundcard id: '" + this.soundcard_id + "'"); + this.amixer = this.amixer + " -c " + this.soundcard_id; + resolve(); + } catch (e) { + reject(e); + } + }); + } else { + resolve(); } - log("Use specific soundcard id: '" + this.soundcard_id + "'"); - - this.amixer = this.amixer + " -c " + this.soundcard_id; - } + }); }, evaluate_input: function() { - this.input = POTENTIAL_INPUTS[0]; - let [res, stdout] = GLib.spawn_command_line_sync(this.amixer); - if (res) { - let found_input = findFirstMatch(POTENTIAL_INPUTS, to_string(stdout)); - if (found_input !== null) - { - this.input = found_input; - } - } - log("Use input: " + this.input); + return new Promise((resolve, reject) => { + this.input = POTENTIAL_INPUTS[0]; + Util.spawn_async(["sh", "-c", this.amixer], (stdout) => { + try { + let found_input = findFirstMatch(POTENTIAL_INPUTS, stdout); + if (found_input !== null) { + this.input = found_input; + } + log("Use input: " + this.input); + resolve(); + } catch (e) { + reject(e); + } + }); + }); }, on_applet_clicked: function(event) { From 3dcba7bafefc7f5bc6572a61e8dc1425db15bfb0 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Sat, 23 Nov 2024 19:18:03 +0100 Subject: [PATCH 6/8] Removed remains of old implementation --- .../files/MuteToggler@jebeaudet.com/applet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index 46654365225..f4edc989156 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -218,7 +218,6 @@ MyApplet.prototype = { // per default use first soundcard this.soundcard_id = "0"; - let soundcard_list_cmd = Util.spawn_async(["sh","-c","cat /proc/asound/cards"], (stdout) => { try { // Split the result into lines From 673bebfd9f6d4c9c0608c93b7d66764a0ec9e257 Mon Sep 17 00:00:00 2001 From: claudiux <33965039+claudiux@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:47:25 +0100 Subject: [PATCH 7/8] Update applet.js: Added 'this.evaluate_soundcard();' at the end of on_settings_changed. --- .../files/MuteToggler@jebeaudet.com/applet.js | 1 + 1 file changed, 1 insertion(+) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index f4edc989156..e562c58c1ab 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -152,6 +152,7 @@ MyApplet.prototype = { } VERBOSE = this.verbose; + this.evaluate_soundcard(); }, refresh_loop: function() { From 91edc648eedfba990d77073627562b2285888ea2 Mon Sep 17 00:00:00 2001 From: Lars Rademacher Date: Fri, 29 Nov 2024 19:21:33 +0100 Subject: [PATCH 8/8] Moved cli eval to subfunc, executed on cfg change --- .../files/MuteToggler@jebeaudet.com/applet.js | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js index e562c58c1ab..6910518cef0 100644 --- a/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js +++ b/MuteToggler@jebeaudet.com/files/MuteToggler@jebeaudet.com/applet.js @@ -55,7 +55,7 @@ function findFirstMatch(searchStrings, checkString) { MyApplet.prototype = { __proto__: Applet.IconApplet.prototype, - _init: async function(metadata, orientation, panel_height, instance_id) { + _init: function(metadata, orientation, panel_height, instance_id) { try { this.settings = new Settings.AppletSettings(this, UUID, instance_id); VERBOSE = this.settings.getValue("verbose"); @@ -114,23 +114,6 @@ MyApplet.prototype = { this.on_settings_changed(); } - this.amixer = "amixer"; - await this.evaluate_soundcard(); - await this.evaluate_input(); - - const parameters = ["", " -D pulse"]; - for (let param of parameters) { - let cmd = this.amixer + param + " scontrols"; - log("Test mixer command '" + cmd + "'"); - // TODO: Make it async. - let [res, stdout] = GLib.spawn_command_line_sync(cmd); - if (res && to_string(stdout).indexOf(this.input) != -1) { - this.amixer += param; - log("Use mixer command '" + this.amixer + "'"); - break; - } - } - this.applet_is_running = true; this.set_not_muted_icon(); this.is_audio_muted(); @@ -152,7 +135,7 @@ MyApplet.prototype = { } VERBOSE = this.verbose; - this.evaluate_soundcard(); + this.evaluate_cmd_line(); }, refresh_loop: function() { @@ -262,6 +245,25 @@ MyApplet.prototype = { }); }, + evaluate_cmd_line: async function() { + this.amixer = "amixer"; + await this.evaluate_soundcard(); + await this.evaluate_input(); + + const parameters = ["", " -D pulse"]; + for (let param of parameters) { + let cmd = this.amixer + param + " scontrols"; + log("Test mixer command '" + cmd + "'"); + // TODO: Make it async. + let [res, stdout] = GLib.spawn_command_line_sync(cmd); + if (res && to_string(stdout).indexOf(this.input) != -1) { + this.amixer += param; + log("Use mixer command '" + this.amixer + "'"); + break; + } + } + }, + on_applet_clicked: function(event) { try{ let cmd = [