From 19a2bc84486b3dd7cca41f467637fe0c056776e4 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Mon, 30 Jun 2025 12:28:59 +0100 Subject: [PATCH] implement audio commands --- index.js | 90 ++++++++++++++++++++++++++++- utils/audio.js | 150 +++++++++++++++++++++++++++++++++++++++++++++++++ utils/cli.js | 3 + 3 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 utils/audio.js diff --git a/index.js b/index.js index b004807..62c470a 100755 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ import cli from "./utils/cli.js"; import { sceneHelp, sceneList, sceneSwitch, sceneCurrent } from "./utils/scene.js"; +import { audioHelp, audioMute, audioUnmute, audioToggle, audioStatus } from "./utils/audio.js"; import { QWebChannel } from "qwebchannel"; @@ -26,8 +27,8 @@ socket.onopen = function() { process.exit(0); } - const subcommand = input[1]; - switch (subcommand) { + const sceneCommand = input[1]; + switch (sceneCommand) { case "list": channel = new QWebChannel(socket, function (channel) { sceneList(channel) @@ -94,6 +95,91 @@ socket.onopen = function() { socket.close(); process.exit(0); } + + case "audio": + if (flags.help) { + console.log(audioHelp); + socket.close(); + process.exit(0); + } + + const audioCommand = input[1]; + const audioName = input[2]; + switch (audioCommand) { + case "mute": + if (!audioName) { + console.error("Error: Audio name is required for the mute command."); + process.exit(1); + } + + channel = new QWebChannel(socket, function (channel) { + audioMute(channel, audioName) + .then((message) => { + console.log(message); + socket.close(); + process.exit(0); + }) + .catch((err) => { + console.error(`${err}`); + socket.close(); + process.exit(1); + }); + }); + break; + case "unmute": + if (!audioName) { + console.error("Error: Audio name is required for the mute command."); + process.exit(1); + } + channel = new QWebChannel(socket, function (channel) { + audioUnmute(channel, audioName) + .then((message) => { + console.log(message); + socket.close(); + process.exit(0); + }) + .catch((err) => { + console.error(`${err}`); + socket.close(); + process.exit(1); + }); + }); + break; + case "toggle": + channel = new QWebChannel(socket, function (channel) { + audioToggle(channel, audioName) + .then((message) => { + console.log(message); + socket.close(); + process.exit(0); + }) + .catch((err) => { + console.error(`${err}`); + socket.close(); + process.exit(1); + }); + }); + break; + case "status": + channel = new QWebChannel(socket, function (channel) { + audioStatus(channel, audioName) + .then((status) => { + console.log(`${audioName} is ${status ? "muted" : "unmuted"}`); + socket.close(); + process.exit(0); + }) + .catch((err) => { + console.error(`Error fetching audio status: ${err}`); + socket.close(); + process.exit(1); + }); + }); + break; + default: + console.log(audioHelp); + socket.close(); + process.exit(0); + } } } catch (error) { console.error("Error handling CLI flags:", error); diff --git a/utils/audio.js b/utils/audio.js new file mode 100644 index 0000000..7dc7551 --- /dev/null +++ b/utils/audio.js @@ -0,0 +1,150 @@ +import meowHelp from "cli-meow-help"; + +const commands = { + mute: { + desc: "Mute the audio", + }, + unmute: { + desc: "Unmute the audio", + }, + toggle: { + desc: "Toggle audio mute state", + }, + status: { + desc: "Show current audio status", + }, +} + +const flags = { + help: { + type: "boolean", + shortFlag: "h", + desc: "Display help information" + }, +}; + +const audioHelp = meowHelp({ + name: "meld-cli audio", + flags, + commands, + description: "Manage audio settings in Meld", + defaults: false, +}); + +function audioMute(channel, audioName) { + if (!channel.objects || !channel.objects.meld) { + return Promise.reject(new Error("Meld object not found in channel.")); + } + const meld = channel.objects.meld; + let itemId; + let isMuted; + for (const [key, value] of Object.entries(meld.session.items)) { + if (value.type === "track" && value.name === audioName) { + itemId = key; + isMuted = value.muted; + break; + } + } + + if (!itemId) { + return Promise.reject(new Error(`No audio device with name ${audioName} found.`)); + } + if (isMuted) { + return Promise.resolve(`Audio track ${audioName} is already muted.`); + } + + return new Promise((resolve, reject) => { + meld.toggleMute(itemId) + .then(() => { + resolve(`Audio track ${audioName} has been muted.`); + }) + .catch((err) => { + reject(new Error(`Error muting audio track: ${err}`)); + }); + }) +} + +function audioUnmute(channel, audioName) { + if (!channel.objects || !channel.objects.meld) { + return Promise.reject(new Error("Meld object not found in channel.")); + } + const meld = channel.objects.meld; + let itemId; + let isMuted; + for (const [key, value] of Object.entries(meld.session.items)) { + if (value.type === "track" && value.name === audioName) { + itemId = key; + isMuted = value.muted; + break; + } + } + if (!itemId) { + return Promise.reject(new Error("No audio track found.")); + } + if (!isMuted) { + return Promise.resolve(`Audio track ${audioName} is already unmuted.`); + } + + return new Promise((resolve, reject) => { + meld.toggleMute(itemId) + .then(() => { + resolve(`Audio track ${audioName} has been unmuted.`); + }) + .catch((err) => { + reject(new Error(`Error unmuting audio track: ${err}`)); + }); + }); +} + +function audioToggle(channel, audioName) { + if (!channel.objects || !channel.objects.meld) { + return Promise.reject(new Error("Meld object not found in channel.")); + } + const meld = channel.objects.meld; + let itemId; + let isMuted; + for (const [key, value] of Object.entries(meld.session.items)) { + if (value.type === "track" && value.name === audioName) { + itemId = key; + isMuted = value.muted; + break; + } + } + if (!itemId) { + return Promise.reject(new Error(`No audio device with name ${audioName} found.`)); + } + return new Promise((resolve, reject) => { + meld.toggleMute(itemId) + .then(() => { + const status = isMuted ? "unmuted" : "muted"; + resolve(`Audio track ${audioName} has been ${status}.`); + }) + .catch((err) => { + reject(new Error(`Error toggling audio track: ${err}`)); + }); + }); +} + +function audioStatus(channel, audioName) { + if (!channel.objects || !channel.objects.meld) { + return Promise.reject(new Error("Meld object not found in channel.")); + } + const meld = channel.objects.meld; + let itemId; + let isMuted; + for (const [key, value] of Object.entries(meld.session.items)) { + if (value.type === "track" && value.name === audioName) { + itemId = key; + isMuted = value.muted; + break; + } + } + if (!itemId) { + return Promise.reject(new Error(`No audio device with name ${audioName} found.`)); + } + return new Promise((resolve, reject) => { + resolve(isMuted); + }); +} + +export { audioHelp, audioMute, audioUnmute, audioToggle, audioStatus } \ No newline at end of file diff --git a/utils/cli.js b/utils/cli.js index 15242cb..284d41f 100644 --- a/utils/cli.js +++ b/utils/cli.js @@ -5,6 +5,9 @@ const commands = { scene: { desc: "Manage scenes", }, + audio: { + desc: "Manage audio settings", + }, }; const flags = {