reorganise dir structure

This commit is contained in:
2025-07-03 09:26:46 +01:00
parent d5876762d0
commit 7595c2f2ee
10 changed files with 11 additions and 11 deletions

248
src/audio.js Normal file
View File

@@ -0,0 +1,248 @@
/**
* @file audio.js
* @module utils/audio
* @description
* Utilities for managing audio tracks in a Meld session via CLI.
* Provides commands to list, mute, unmute, toggle, and check the status of audio tracks.
* Integrates with cli-meow-help for command-line help and cli-table3 for tabular output.
*/
import meowHelp from 'cli-meow-help'
import Table from 'cli-table3'
import style from './style.js'
const commands = {
list: {
desc: 'List all audio devices'
},
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'
}
}
/**
* Contains the help information for the audio command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const audioHelp = meowHelp({
name: 'meld-cli audio',
desc: 'Manage audio settings in Meld',
commands,
flags,
defaults: false
})
/**
* List all audio tracks in the Meld session.
* @param {Object} channel - The channel object containing Meld session data.
* @param {boolean} showId - Whether to display the audio track ID.
* @returns {Promise<Table|string>} Resolves with a Table instance or a message if no devices found.
*/
function audioList (channel, showId) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const headers = [{ content: 'Audio Name', hAlign: 'center' }, { content: 'Muted', hAlign: 'center' }]
if (showId) {
headers.push({ content: 'ID', hAlign: 'center' })
}
const table = new Table({
style: {
head: ['none'],
compact: true
},
head: headers
})
const meld = channel.objects.meld
for (const [key, value] of Object.entries(meld.session.items)) {
if (value.type === 'track') {
if (showId) {
table.push([style.highlight(value.name), { content: value.muted ? style.highlight('✓') : '✗', hAlign: 'center' }, style.highlight(key)])
} else {
table.push([style.highlight(value.name), { content: value.muted ? style.highlight('✓') : '✗', hAlign: 'center' }])
}
}
}
if (table.length === 0) {
return Promise.resolve('No audio devices found.')
}
return Promise.resolve(table)
}
/**
* Mute a specific audio track by name.
* @param {Object} channel - The channel object containing Meld session data.
* @param {string} audioName - The name of the audio track to mute.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
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 ${style.errHighlight(audioName)} found.`))
}
if (isMuted) {
return Promise.reject(new Error(`Audio track ${style.errHighlight(audioName)} is already muted.`))
}
return new Promise((resolve, reject) => {
meld.toggleMute(itemId)
.then(() => {
resolve(`Audio track ${style.highlight(audioName)} has been muted.`)
})
.catch((err) => {
reject(new Error(`Error muting audio track: ${err.message}`))
})
})
}
/**
* Unmute a specific audio track by name.
* @param {Object} channel - The channel object containing Meld session data.
* @param {string} audioName - The name of the audio track to unmute.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
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.reject(new Error(`Audio track ${style.errHighlight(audioName)} is already unmuted.`))
}
return new Promise((resolve, reject) => {
meld.toggleMute(itemId)
.then(() => {
resolve(`Audio track ${style.highlight(audioName)} has been unmuted.`)
})
.catch((err) => {
reject(new Error(`Error unmuting audio track: ${err.message}`))
})
})
}
/**
* Toggle the mute state of a specific audio track by name.
* @param {Object} channel - The channel object containing Meld session data.
* @param {string} audioName - The name of the audio track to toggle.
* @returns {Promise<string>} Resolves with a message indicating the new state or rejects with an error.
*/
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 ${style.errHighlight(audioName)} found.`))
}
return new Promise((resolve, reject) => {
meld.toggleMute(itemId)
.then(() => {
const status = isMuted ? 'unmuted' : 'muted'
resolve(`Audio track ${style.highlight(audioName)} has been ${status}.`)
})
.catch((err) => {
reject(new Error(`Error toggling audio track: ${err.message}`))
})
})
}
/**
* Get the mute status of a specific audio track by name.
* @param {Object} channel - The channel object containing Meld session data.
* @param {string} audioName - The name of the audio track to check.
* @returns {Promise<string>} Resolves with the current mute status or rejects with an error.
*/
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 ${style.errHighlight(audioName)} found.`))
}
return new Promise((resolve, reject) => {
resolve(`${style.highlight(audioName)} is ${isMuted ? 'muted' : 'unmuted'}`)
})
}
export {
audioHelp,
audioList,
audioMute,
audioUnmute,
audioToggle,
audioStatus
}

61
src/cli.js Normal file
View File

@@ -0,0 +1,61 @@
import meow from 'meow'
import meowHelp from 'cli-meow-help'
const commands = {
scene: {
desc: 'Manage scenes'
},
audio: {
desc: 'Manage audio settings'
},
stream: {
desc: 'Manage streaming'
},
record: {
desc: 'Manage recording'
},
clip: {
desc: 'Save a clip'
},
screenshot: {
desc: 'Take a screenshot'
},
virtualcam: {
desc: 'Manage virtual camera settings'
}
}
const flags = {
host: {
type: 'string',
shortFlag: 'H',
desc: 'Host address for the Meld server'
},
port: {
type: 'number',
shortFlag: 'P',
desc: 'Port number for the Meld server'
},
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
},
version: {
type: 'boolean',
shortFlag: 'v',
desc: 'Display the version number'
}
}
const helpText = meowHelp({
name: 'meld-cli',
flags,
commands,
defaults: false
})
export default meow(helpText, {
importMeta: import.meta,
flags
})

50
src/clip.js Normal file
View File

@@ -0,0 +1,50 @@
/**
* @file clip.js
* @module utils/clip
* @description
* Utilities for managing clips in a Meld session via CLI.
* Provides commands to save clips and display help information.
* Integrates with cli-meow-help for command-line help.
*/
import meowHelp from 'cli-meow-help'
/**
* Contains the help information for the clip command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const clipHelp = meowHelp({
name: 'meld-cli clip',
desc: 'Manage clips in Meld',
commands: {
save: {
desc: 'Save a clip'
}
},
flags: {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
}
},
defaults: false
})
/**
* Save a clip.
* @param {Object} channel - The channel object containing Meld session data.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
async function clipSave (channel) {
await channel.objects.meld.sendCommand('meld.recordClip')
return 'Clip saved successfully.'
}
export { clipHelp, clipSave }

151
src/record.js Normal file
View File

@@ -0,0 +1,151 @@
/**
* @file record.js
* @module utils/record
* @description
* Utilities for managing recording state in a Meld session via CLI.
* Provides commands to start, stop, toggle, and check the status of recording.
* Integrates with cli-meow-help for command-line help.
*/
import meowHelp from 'cli-meow-help'
const commands = {
start: {
desc: 'Start recording'
},
stop: {
desc: 'Stop recording'
},
toggle: {
desc: 'Toggle recording state'
},
status: {
desc: 'Show the current recording status'
}
}
const flags = {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
}
}
/**
* Contains the help information for the record command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const recordHelp = meowHelp({
name: 'meld-cli record',
desc: 'Manage recording in Meld',
commands,
flags,
defaults: false
})
/**
* Start recording using the Meld object in the provided channel.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
function recordStart (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
if (meld.isRecording) {
return Promise.reject(new Error('Recording is already active.'))
}
return new Promise((resolve, reject) => {
meld.toggleRecord()
.then(() => {
resolve('Recording started successfully.')
})
.catch((err) => {
reject(new Error(`Failed to start recording: ${err.message}`))
})
})
}
/**
* Stop recording using the Meld object in the provided channel.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
function recordStop (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
if (!meld.isRecording) {
return Promise.reject(new Error('Recording is not currently active.'))
}
return new Promise((resolve, reject) => {
meld.toggleRecord()
.then(() => {
resolve('Recording stopped successfully.')
})
.catch((err) => {
reject(new Error(`Failed to stop recording: ${err.message}`))
})
})
}
/**
* Toggle the recording state using the Meld object in the provided channel.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a message indicating the new recording state or rejects with an error.
*/
function recordToggle (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
return new Promise((resolve, reject) => {
meld.toggleRecord()
.then(() => {
resolve(`Recording ${meld.isRecording ? 'stopped' : 'started'} successfully.`)
})
.catch((err) => {
reject(new Error(`Failed to toggle recording: ${err.message}`))
})
})
}
/**
* Get the current recording status from the Meld object in the provided channel.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a message indicating if recording is active or inactive.
*/
function recordStatus (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
return Promise.resolve(`Recording is currently ${meld.isRecording ? 'active' : 'inactive'}`)
}
export {
recordHelp,
recordStart,
recordStop,
recordToggle,
recordStatus
}

157
src/scene.js Normal file
View File

@@ -0,0 +1,157 @@
/**
* @file scene.js
* @module utils/scene
* @description
* Utilities for managing scenes in a Meld session via CLI.
* Provides commands to list, switch, and show the current scene.
* Integrates with cli-meow-help for command-line help and cli-table3 for tabular output.
*/
import meowHelp from 'cli-meow-help'
import Table from 'cli-table3'
import style from './style.js'
const commands = {
list: {
desc: 'List all scenes, optionally showing IDs'
},
switch: {
desc: 'Switch to a scene by name'
},
current: {
desc: 'Show the current scene, optionally showing its ID'
}
}
const flags = {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
},
id: {
type: 'boolean',
desc: 'Display scene IDs'
}
}
/**
* Contains the help information for the scene command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const sceneHelp = meowHelp({
name: 'meld-cli scene',
desc: 'Manage scenes in Meld',
commands,
flags,
defaults: false
})
/**
* Lists all scenes in the current Meld session, optionally showing their IDs.
* @param {Object} channel - The channel object containing Meld session data.
* @param {boolean} showId - Whether to display scene IDs in the output.
* @returns {Promise<Table|string>} A promise that resolves to a Table instance or a message if no scenes are found.
*/
function sceneList (channel, showId) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const headers = [{ content: 'Scene Name', hAlign: 'center' }, { content: 'Active', hAlign: 'center' }]
if (showId) {
headers.push({ content: 'ID', hAlign: 'center' })
}
const table = new Table({
style: {
head: ['none'],
compact: true
},
head: headers
})
const meld = channel.objects.meld
for (const [key, value] of Object.entries(meld.session.items)) {
if (value.type === 'scene') {
if (showId) {
table.push([style.highlight(value.name), { content: value.current ? style.highlight('✓') : '✗', hAlign: 'center' }, style.highlight(key)])
} else {
table.push([style.highlight(value.name), { content: value.current ? style.highlight('✓') : '✗', hAlign: 'center' }])
}
}
}
if (table.length === 0) {
return Promise.resolve('No scenes found.')
}
return Promise.resolve(table)
}
/**
* Switches to a scene by its name.
* @param {Object} channel - The channel object containing Meld session data.
* @param {string} sceneName - The name of the scene to switch to.
* @returns {Promise<string>} A promise that resolves to a confirmation message or rejects if the scene is not found.
*/
function sceneSwitch (channel, sceneName) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
let itemId
for (const [key, value] of Object.entries(meld.session.items)) {
if (value.type === 'scene' && value.name === sceneName) {
itemId = key
break
}
}
if (!itemId) {
return Promise.reject(new Error(`No scene with name ${style.errHighlight(sceneName)} found.`))
}
return new Promise((resolve, reject) => {
meld.showScene(itemId).then(() => {
resolve(`Switched to scene: ${style.highlight(sceneName)}`)
}).catch(err => {
reject(err)
})
})
}
/**
* Shows the current active scene, optionally displaying its ID.
* @param {Object} channel - The channel object containing Meld session data.
* @param {boolean} showId - Whether to display the scene ID.
* @returns {Promise<string>} A promise that resolves to the current scene information or rejects if not found.
*/
function sceneCurrent (channel, showId) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
for (const [key, value] of Object.entries(meld.session.items)) {
if (value.type === 'scene' && value.current) {
if (showId) {
return Promise.resolve(`Current scene: ${style.highlight(value.name)} (ID: ${style.highlight(key)})`)
}
return Promise.resolve(`Current scene: ${style.highlight(value.name)}`)
}
}
return Promise.reject(new Error('No current scene found.'))
}
export {
sceneHelp,
sceneList,
sceneSwitch,
sceneCurrent
}

52
src/screenshot.js Normal file
View File

@@ -0,0 +1,52 @@
/**
* @file screenshot.js
* @module utils/screenshot
* @description
* Utilities for managing screenshots in a Meld session via CLI.
* Provides commands to take screenshots and display help information.
* Integrates with cli-meow-help for command-line help.
*/
import meowHelp from 'cli-meow-help'
/**
* Contains the help information for the screenshot command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const screenshotHelp = meowHelp({
name: 'meld-cli screenshot',
desc: 'Manage screenshots in Meld',
commands: {
take: {
desc: 'Take a screenshot'
}
},
flags: {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
}
},
defaults: false
})
/**
* Takes a screenshot by sending the 'meld.screenshot' command through the provided channel.
*
* @async
* @param {Object} channel - The communication channel with Meld.
* @returns {Promise<string>} Resolves with a success message when the screenshot is taken.
*/
async function screenshotTake (channel) {
await channel.objects.meld.sendCommand('meld.screenshot')
return 'Screenshot taken successfully.'
}
export { screenshotHelp, screenshotTake }

152
src/stream.js Normal file
View File

@@ -0,0 +1,152 @@
/**
* @file stream.js
* @module utils/stream
* @description
* Utilities for managing streaming in a Meld session via CLI.
* Provides commands to start, stop, toggle, and check the status of streaming.
* Integrates with cli-meow-help for command-line help.
*/
import meowHelp from 'cli-meow-help'
const commands = {
start: {
desc: 'Start streaming'
},
stop: {
desc: 'Stop streaming'
},
toggle: {
desc: 'Toggle streaming state'
},
status: {
desc: 'Show the current streaming status'
}
}
const flags = {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
}
}
/**
* Contains the help information for the stream command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const streamHelp = meowHelp({
name: 'meld-cli stream',
desc: 'Manage streaming in Meld',
commands,
flags,
defaults: false
})
/**
* Start streaming if not already active.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
function streamStart (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
if (meld.isStreaming) {
return Promise.reject(new Error('Streaming is already active.'))
}
return new Promise((resolve, reject) => {
meld.toggleStream()
.then(() => {
resolve('Streaming started successfully.')
})
.catch((err) => {
reject(new Error(`Failed to start streaming: ${err.message}`))
})
})
}
/**
* Stop streaming if currently active.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a success message or rejects with an error.
*/
function streamStop (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
if (!meld.isStreaming) {
return Promise.reject(new Error('Streaming is not currently active.'))
}
return new Promise((resolve, reject) => {
meld.toggleStream()
.then(() => {
resolve('Streaming stopped successfully.')
})
.catch((err) => {
reject(new Error(`Failed to stop streaming: ${err.message}`))
})
})
}
/**
* Toggle the streaming state.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a message indicating the new streaming state or rejects with an error.
*/
function streamToggle (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
return new Promise((resolve, reject) => {
meld.toggleStream()
.then(() => {
resolve(`Streaming ${meld.isStreaming ? 'stopped' : 'started'} successfully.`)
})
.catch((err) => {
reject(new Error(`Failed to toggle streaming: ${err.message}`))
})
})
}
/**
* Get the current streaming status.
* @function
* @param {Object} channel - The channel object containing Meld.
* @returns {Promise<string>} Resolves with a message indicating whether streaming is active or inactive.
*/
function streamStatus (channel) {
if (!channel.objects || !channel.objects.meld) {
return Promise.reject(new Error('Meld object not found in channel.'))
}
const meld = channel.objects.meld
return Promise.resolve(`Streaming is currently ${meld.isStreaming ? 'active' : 'inactive'}`)
}
export {
streamStart,
streamStop,
streamToggle,
streamStatus,
streamHelp
}

21
src/style.js Normal file
View File

@@ -0,0 +1,21 @@
/**
* @file style.js
* @module utils/style
* @description
* Utilities for styling console output in the Meld CLI.
*/
import clc from 'cli-color'
/**
* Styles for console output in the Meld CLI.
* @constant
* @type {object}
*/
const style = {
highlight: clc.cyan,
err: clc.red.bold,
errHighlight: clc.yellow.bold
}
export default style

57
src/virtualcam.js Normal file
View File

@@ -0,0 +1,57 @@
/**
* @file virtualcam.js
* @module utils/virtualcam
* @description
* Utilities for managing the virtual camera in a Meld session via CLI.
* Provides commands to toggle the virtual camera on or off.
* Integrates with cli-meow-help for command-line help.
*/
import meowHelp from 'cli-meow-help'
const commands = {
toggle: {
desc: 'Toggle the virtual camera on or off'
}
}
const flags = {
help: {
type: 'boolean',
shortFlag: 'h',
desc: 'Display help information'
}
}
/**
* Contains the help information for the virtualcam command group.
*
* @type {object}
* @property {string} name - The name of the CLI command.
* @property {string} desc - Description of the command's purpose.
* @property {object} commands - The available subcommands.
* @property {object} flags - The available flags for the command.
* @property {boolean} defaults - Indicates if default values are shown.
*/
const virtualcamHelp = meowHelp({
name: 'virtualcam',
desc: 'Manage virtual camera settings in Meld',
commands,
flags,
defaults: false
})
/**
* Toggles the virtual camera on or off by sending a command through the provided channel.
*
* @async
* @function virtualcamToggle
* @param {object} channel - The channel object containing the 'meld' object for sending commands.
* @returns {Promise<string>} A promise that resolves to a success message upon toggling the virtual camera.
*/
async function virtualcamToggle (channel) {
await channel.objects.meld.sendCommand('meld.toggleVirtualCameraAction')
return 'Virtual camera toggled successfully.'
}
export { virtualcamHelp, virtualcamToggle }