@raphiiko/wavelink-cli 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -27
- package/dist/index.js +4880 -4789
- package/package.json +3 -3
- package/src/commands/channel.ts +243 -0
- package/src/commands/info.ts +19 -0
- package/src/commands/input.ts +128 -0
- package/src/commands/mix.ts +98 -0
- package/src/commands/output.ts +207 -0
- package/src/index.ts +14 -754
- package/src/services/client.ts +24 -0
- package/src/services/finders.ts +150 -0
- package/src/types/index.ts +23 -0
- package/src/utils/error.ts +4 -0
- package/src/utils/format.ts +15 -0
- package/src/utils/validation.ts +9 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { WaveLinkClient } from "@raphiiko/wavelink-ts";
|
|
2
|
+
import { Argument, Command } from "commander";
|
|
3
|
+
import { withClient } from "../services/client.js";
|
|
4
|
+
import { requireOutput, requireMix } from "../services/finders.js";
|
|
5
|
+
import { formatPercent, formatMuted } from "../utils/format.js";
|
|
6
|
+
import { parsePercent } from "../utils/validation.js";
|
|
7
|
+
|
|
8
|
+
export async function setOutputVolume(
|
|
9
|
+
client: WaveLinkClient,
|
|
10
|
+
outputId: string,
|
|
11
|
+
volumePercent: number
|
|
12
|
+
): Promise<void> {
|
|
13
|
+
const output = await requireOutput(client, outputId);
|
|
14
|
+
await client.setOutputVolume(output.deviceId, output.outputId, volumePercent / 100);
|
|
15
|
+
console.log(`Successfully set output '${output.outputName}' volume to ${volumePercent}%`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function setOutputMute(
|
|
19
|
+
client: WaveLinkClient,
|
|
20
|
+
outputId: string,
|
|
21
|
+
isMuted: boolean
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
const output = await requireOutput(client, outputId);
|
|
24
|
+
await client.setOutputDevice({
|
|
25
|
+
outputDevice: { id: output.deviceId, outputs: [{ id: output.outputId, isMuted }] },
|
|
26
|
+
});
|
|
27
|
+
console.log(`Successfully ${isMuted ? "muted" : "unmuted"} output '${output.outputName}'`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function listOutputs(client: WaveLinkClient): Promise<void> {
|
|
31
|
+
const { outputDevices, mainOutput } = await client.getOutputDevices();
|
|
32
|
+
const { mixes } = await client.getMixes();
|
|
33
|
+
|
|
34
|
+
console.log("\n=== Output Devices ===\n");
|
|
35
|
+
|
|
36
|
+
if (outputDevices.length === 0) {
|
|
37
|
+
console.log("No output devices found.");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const device of outputDevices) {
|
|
42
|
+
const isMain = device.id === mainOutput ? " (MAIN OUTPUT)" : "";
|
|
43
|
+
console.log(`Device: ${device.name || device.id}${isMain}`);
|
|
44
|
+
console.log(` Device ID: ${device.id}`);
|
|
45
|
+
console.log(` Wave Device: ${formatMuted(device.isWaveDevice)}`);
|
|
46
|
+
|
|
47
|
+
if (device.outputs.length === 0) {
|
|
48
|
+
console.log(" No outputs available");
|
|
49
|
+
} else {
|
|
50
|
+
for (const output of device.outputs) {
|
|
51
|
+
const mix = mixes.find((m) => m.id === output.mixId);
|
|
52
|
+
const mixDisplay = output.mixId
|
|
53
|
+
? `${mix?.name ?? output.mixId} (${output.mixId})`
|
|
54
|
+
: "Not assigned";
|
|
55
|
+
console.log(` Output: ${output.name || output.id}`);
|
|
56
|
+
console.log(` Output ID: ${output.id}`);
|
|
57
|
+
console.log(` Current Mix: ${mixDisplay}`);
|
|
58
|
+
console.log(` Level: ${formatPercent(output.level)}`);
|
|
59
|
+
console.log(` Muted: ${formatMuted(output.isMuted)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function assignOutputToMix(
|
|
67
|
+
client: WaveLinkClient,
|
|
68
|
+
outputId: string,
|
|
69
|
+
mixId: string
|
|
70
|
+
): Promise<void> {
|
|
71
|
+
const mix = await requireMix(client, mixId);
|
|
72
|
+
const output = await requireOutput(client, outputId);
|
|
73
|
+
|
|
74
|
+
if (output.currentMixId === mix.id) {
|
|
75
|
+
console.log(`Output '${output.outputName}' is already assigned to mix '${mix.name}'`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await client.switchOutputMix(output.deviceId, output.outputId, mix.id);
|
|
80
|
+
console.log(`Successfully assigned output '${output.outputName}' to mix '${mix.name}'`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function unassignOutputDevice(
|
|
84
|
+
client: WaveLinkClient,
|
|
85
|
+
outputId: string
|
|
86
|
+
): Promise<void> {
|
|
87
|
+
const output = await requireOutput(client, outputId);
|
|
88
|
+
await client.removeOutputFromMix(output.deviceId, output.outputId);
|
|
89
|
+
console.log(`Successfully unassigned output '${output.outputName}'`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function setSingleOutputForMix(
|
|
93
|
+
client: WaveLinkClient,
|
|
94
|
+
outputId: string,
|
|
95
|
+
mixId: string
|
|
96
|
+
): Promise<void> {
|
|
97
|
+
const mix = await requireMix(client, mixId);
|
|
98
|
+
const targetOutput = await requireOutput(client, outputId);
|
|
99
|
+
|
|
100
|
+
const { outputDevices } = await client.getOutputDevices();
|
|
101
|
+
|
|
102
|
+
let outputsRemoved = 0;
|
|
103
|
+
let targetOutputAssigned = false;
|
|
104
|
+
|
|
105
|
+
for (const device of outputDevices) {
|
|
106
|
+
for (const output of device.outputs) {
|
|
107
|
+
const isTargetOutput =
|
|
108
|
+
device.id === targetOutput.deviceId && output.id === targetOutput.outputId;
|
|
109
|
+
|
|
110
|
+
if (isTargetOutput && output.mixId !== mix.id) {
|
|
111
|
+
await client.switchOutputMix(device.id, output.id, mix.id);
|
|
112
|
+
targetOutputAssigned = true;
|
|
113
|
+
} else if (!isTargetOutput && output.mixId === mix.id) {
|
|
114
|
+
await client.removeOutputFromMix(device.id, output.id);
|
|
115
|
+
outputsRemoved++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (targetOutputAssigned && outputsRemoved > 0) {
|
|
121
|
+
console.log(
|
|
122
|
+
`Successfully set '${targetOutput.outputName}' as the only output for mix '${mix.name}' ` +
|
|
123
|
+
`(removed ${outputsRemoved} other output(s) from the mix)`
|
|
124
|
+
);
|
|
125
|
+
} else if (targetOutputAssigned) {
|
|
126
|
+
console.log(
|
|
127
|
+
`Successfully assigned '${targetOutput.outputName}' to mix '${mix.name}' ` +
|
|
128
|
+
`(it is now the only output on this mix)`
|
|
129
|
+
);
|
|
130
|
+
} else if (outputsRemoved > 0) {
|
|
131
|
+
console.log(
|
|
132
|
+
`'${targetOutput.outputName}' was already assigned to mix '${mix.name}'. ` +
|
|
133
|
+
`Removed ${outputsRemoved} other output(s) from the mix.`
|
|
134
|
+
);
|
|
135
|
+
} else {
|
|
136
|
+
console.log(`'${targetOutput.outputName}' is already the only output for mix '${mix.name}'`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function registerOutputCommands(program: Command): void {
|
|
141
|
+
const outputCmd = program.command("output").description("Manage output devices");
|
|
142
|
+
|
|
143
|
+
outputCmd
|
|
144
|
+
.command("list")
|
|
145
|
+
.description("List all output devices with their IDs and current mix assignments")
|
|
146
|
+
.action(() => withClient(listOutputs));
|
|
147
|
+
|
|
148
|
+
outputCmd
|
|
149
|
+
.command("assign")
|
|
150
|
+
.description("Assign an output device to a specific mix")
|
|
151
|
+
.addArgument(
|
|
152
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
153
|
+
)
|
|
154
|
+
.addArgument(new Argument("<mix-id-or-name>", "ID or name of the mix (case-insensitive)"))
|
|
155
|
+
.action((outputId: string, mixId: string) =>
|
|
156
|
+
withClient((client) => assignOutputToMix(client, outputId, mixId))
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
outputCmd
|
|
160
|
+
.command("unassign")
|
|
161
|
+
.description("Unassign an output device from its current mix")
|
|
162
|
+
.addArgument(
|
|
163
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
164
|
+
)
|
|
165
|
+
.action((outputId: string) => withClient((client) => unassignOutputDevice(client, outputId)));
|
|
166
|
+
|
|
167
|
+
outputCmd
|
|
168
|
+
.command("set-volume")
|
|
169
|
+
.description("Set output device volume")
|
|
170
|
+
.addArgument(
|
|
171
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
172
|
+
)
|
|
173
|
+
.addArgument(new Argument("<volume>", "Volume level (0-100)"))
|
|
174
|
+
.action((outputId: string, volume: string) => {
|
|
175
|
+
const volumePercent = parsePercent(volume, "Volume");
|
|
176
|
+
return withClient((client) => setOutputVolume(client, outputId, volumePercent));
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
outputCmd
|
|
180
|
+
.command("mute")
|
|
181
|
+
.description("Mute an output device")
|
|
182
|
+
.addArgument(
|
|
183
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
184
|
+
)
|
|
185
|
+
.action((outputId: string) => withClient((client) => setOutputMute(client, outputId, true)));
|
|
186
|
+
|
|
187
|
+
outputCmd
|
|
188
|
+
.command("unmute")
|
|
189
|
+
.description("Unmute an output device")
|
|
190
|
+
.addArgument(
|
|
191
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
192
|
+
)
|
|
193
|
+
.action((outputId: string) => withClient((client) => setOutputMute(client, outputId, false)));
|
|
194
|
+
|
|
195
|
+
outputCmd
|
|
196
|
+
.command("toggle-mute")
|
|
197
|
+
.description("Toggle output device mute state")
|
|
198
|
+
.addArgument(
|
|
199
|
+
new Argument("<output-id-or-name>", "ID or name of the output device (case-insensitive)")
|
|
200
|
+
)
|
|
201
|
+
.action((outputId: string) =>
|
|
202
|
+
withClient(async (client) => {
|
|
203
|
+
const output = await requireOutput(client, outputId);
|
|
204
|
+
await setOutputMute(client, outputId, !output.isMuted);
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
}
|