@raphiiko/wavelink-cli 0.0.2 → 0.0.4

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 CHANGED
@@ -92,6 +92,10 @@ wavelink-cli channel set-mix-volume <channel-id> <mix-id-or-name> <volume>
92
92
  # Mute/Unmute in a specific mix
93
93
  wavelink-cli channel mute-in-mix <channel-id> <mix-id-or-name>
94
94
  wavelink-cli channel unmute-in-mix <channel-id> <mix-id-or-name>
95
+ wavelink-cli channel toggle-mute-in-mix <channel-id> <mix-id-or-name>
96
+
97
+ # Isolate a channel in a mix (mute all others)
98
+ wavelink-cli channel isolate <channel-id> <mix-id-or-name>
95
99
 
96
100
 
97
101
  ```
package/dist/index.js CHANGED
@@ -5642,12 +5642,7 @@ async function setSingleOutputForMix(client, deviceId, mixId) {
5642
5642
  const mix = await requireMix(client, mixId);
5643
5643
  const targetDevice = await requireOutputDevice(client, deviceId);
5644
5644
  const { outputDevices } = await client.getOutputDevices();
5645
- const { mixes } = await client.getMixes();
5646
- const otherMix = mixes.find((m) => m.id !== mix.id);
5647
- if (!otherMix) {
5648
- exitWithError("Cannot use 'single' command with only one mix available. At least two mixes are required.");
5649
- }
5650
- let devicesReassigned = 0;
5645
+ let devicesRemoved = 0;
5651
5646
  let targetDeviceAssigned = false;
5652
5647
  for (const device of outputDevices) {
5653
5648
  for (const output of device.outputs) {
@@ -5656,17 +5651,17 @@ async function setSingleOutputForMix(client, deviceId, mixId) {
5656
5651
  await client.switchOutputMix(device.id, output.id, mix.id);
5657
5652
  targetDeviceAssigned = true;
5658
5653
  } else if (!isTargetDevice && output.mixId === mix.id) {
5659
- await client.switchOutputMix(device.id, output.id, otherMix.id);
5660
- devicesReassigned++;
5654
+ await client.removeOutputFromMix(device.id, output.id);
5655
+ devicesRemoved++;
5661
5656
  }
5662
5657
  }
5663
5658
  }
5664
- if (targetDeviceAssigned && devicesReassigned > 0) {
5665
- console.log(`Successfully set '${targetDevice.deviceId}' as the only output for mix '${mix.name}' ` + `(reassigned ${devicesReassigned} other device(s) to '${otherMix.name}')`);
5659
+ if (targetDeviceAssigned && devicesRemoved > 0) {
5660
+ console.log(`Successfully set '${targetDevice.deviceId}' as the only output for mix '${mix.name}' ` + `(removed ${devicesRemoved} other device(s) from the mix)`);
5666
5661
  } else if (targetDeviceAssigned) {
5667
- console.log(`Successfully assigned '${targetDevice.deviceId}' to mix '${mix.name}' ` + `(it was already the only device on this mix)`);
5668
- } else if (devicesReassigned > 0) {
5669
- console.log(`'${targetDevice.deviceId}' was already assigned to mix '${mix.name}'. ` + `Reassigned ${devicesReassigned} other device(s) to '${otherMix.name}'`);
5662
+ console.log(`Successfully assigned '${targetDevice.deviceId}' to mix '${mix.name}' ` + `(it is now the only device on this mix)`);
5663
+ } else if (devicesRemoved > 0) {
5664
+ console.log(`'${targetDevice.deviceId}' was already assigned to mix '${mix.name}'. ` + `Removed ${devicesRemoved} other device(s) from the mix.`);
5670
5665
  } else {
5671
5666
  console.log(`'${targetDevice.deviceId}' is already the only output for mix '${mix.name}'`);
5672
5667
  }
@@ -5776,6 +5771,50 @@ channelCmd.command("unmute-in-mix").description("Unmute a channel in a specific
5776
5771
  await client.setChannelMixMute(channel.id, mix.id, false);
5777
5772
  console.log(`Successfully unmuted channel '${channel.name}' in mix '${mix.name}'`);
5778
5773
  }));
5774
+ channelCmd.command("toggle-mute-in-mix").description("Toggle channel mute state in a specific mix").addArgument(new Argument("<channel-id>", "ID of the channel")).addArgument(new Argument("<mix-id-or-name>", "ID or name of the mix (case-insensitive)")).action((channelId, mixId) => withClient(async (client) => {
5775
+ const mix = await requireMix(client, mixId);
5776
+ const { channels } = await client.getChannels();
5777
+ const channel = channels.find((c) => c.id === channelId);
5778
+ if (!channel)
5779
+ exitWithError(`Channel '${channelId}' not found`);
5780
+ const mixAssignment = channel.mixes?.find((m) => m.id === mix.id);
5781
+ if (!mixAssignment) {
5782
+ exitWithError(`Channel '${channelId}' is not available in mix '${mix.name}'`);
5783
+ }
5784
+ const newMuted = !mixAssignment.isMuted;
5785
+ await client.setChannelMixMute(channel.id, mix.id, newMuted);
5786
+ console.log(`Successfully toggled mute for channel '${channel.image?.name ?? channel.id}' in mix '${mix.name}'`);
5787
+ }));
5788
+ channelCmd.command("isolate").description("Mute all channels in a mix except for the specified one").addArgument(new Argument("<channel-id>", "ID of the channel to isolate")).addArgument(new Argument("<mix-id-or-name>", "ID or name of the mix (case-insensitive)")).action((channelId, mixId) => withClient(async (client) => {
5789
+ const mix = await requireMix(client, mixId);
5790
+ const targetChannel = await requireChannel(client, channelId);
5791
+ const { channels } = await client.getChannels();
5792
+ let mutedCount = 0;
5793
+ let alreadyMutedCount = 0;
5794
+ for (const channel of channels) {
5795
+ const assignment = channel.mixes?.find((m) => m.id === mix.id);
5796
+ if (!assignment)
5797
+ continue;
5798
+ if (channel.id === targetChannel.id) {
5799
+ if (assignment.isMuted) {
5800
+ await client.setChannelMixMute(channel.id, mix.id, false);
5801
+ console.log(`Unmuted target channel '${channel.image?.name ?? channel.id}'`);
5802
+ } else {
5803
+ console.log(`Target channel '${channel.image?.name ?? channel.id}' is already unmuted`);
5804
+ }
5805
+ } else {
5806
+ if (!assignment.isMuted) {
5807
+ await client.setChannelMixMute(channel.id, mix.id, true);
5808
+ mutedCount++;
5809
+ } else {
5810
+ alreadyMutedCount++;
5811
+ }
5812
+ }
5813
+ }
5814
+ console.log(`SUCCESS: Isolated '${targetChannel.id}' in mix '${mix.name}'.
5815
+ ` + ` - Muted ${mutedCount} other channels.
5816
+ ` + ` - ${alreadyMutedCount} channels were already muted.`);
5817
+ }));
5779
5818
  var inputCmd = program2.command("input").description("Manage input devices");
5780
5819
  inputCmd.command("list").description("List all input devices with their IDs").action(() => withClient(listInputs));
5781
5820
  inputCmd.command("set-gain").description("Set input device gain").addArgument(new Argument("<input-id>", "ID of the input device")).addArgument(new Argument("<gain>", "Gain level (0-100)")).action((inputId, gain) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raphiiko/wavelink-cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Command line interface for Elgato Wave Link 3.0",
5
5
  "author": "Raphiiko",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -336,16 +336,8 @@ async function setSingleOutputForMix(
336
336
  const targetDevice = await requireOutputDevice(client, deviceId);
337
337
 
338
338
  const { outputDevices } = await client.getOutputDevices();
339
- const { mixes } = await client.getMixes();
340
339
 
341
- const otherMix = mixes.find((m) => m.id !== mix.id);
342
- if (!otherMix) {
343
- exitWithError(
344
- "Cannot use 'single' command with only one mix available. At least two mixes are required."
345
- );
346
- }
347
-
348
- let devicesReassigned = 0;
340
+ let devicesRemoved = 0;
349
341
  let targetDeviceAssigned = false;
350
342
 
351
343
  for (const device of outputDevices) {
@@ -356,26 +348,26 @@ async function setSingleOutputForMix(
356
348
  await client.switchOutputMix(device.id, output.id, mix.id);
357
349
  targetDeviceAssigned = true;
358
350
  } else if (!isTargetDevice && output.mixId === mix.id) {
359
- await client.switchOutputMix(device.id, output.id, otherMix.id);
360
- devicesReassigned++;
351
+ await client.removeOutputFromMix(device.id, output.id);
352
+ devicesRemoved++;
361
353
  }
362
354
  }
363
355
  }
364
356
 
365
- if (targetDeviceAssigned && devicesReassigned > 0) {
357
+ if (targetDeviceAssigned && devicesRemoved > 0) {
366
358
  console.log(
367
359
  `Successfully set '${targetDevice.deviceId}' as the only output for mix '${mix.name}' ` +
368
- `(reassigned ${devicesReassigned} other device(s) to '${otherMix.name}')`
360
+ `(removed ${devicesRemoved} other device(s) from the mix)`
369
361
  );
370
362
  } else if (targetDeviceAssigned) {
371
363
  console.log(
372
364
  `Successfully assigned '${targetDevice.deviceId}' to mix '${mix.name}' ` +
373
- `(it was already the only device on this mix)`
365
+ `(it is now the only device on this mix)`
374
366
  );
375
- } else if (devicesReassigned > 0) {
367
+ } else if (devicesRemoved > 0) {
376
368
  console.log(
377
369
  `'${targetDevice.deviceId}' was already assigned to mix '${mix.name}'. ` +
378
- `Reassigned ${devicesReassigned} other device(s) to '${otherMix.name}'`
370
+ `Removed ${devicesRemoved} other device(s) from the mix.`
379
371
  );
380
372
  } else {
381
373
  console.log(`'${targetDevice.deviceId}' is already the only output for mix '${mix.name}'`);
@@ -638,6 +630,83 @@ channelCmd
638
630
  })
639
631
  );
640
632
 
633
+ channelCmd
634
+ .command("toggle-mute-in-mix")
635
+ .description("Toggle channel mute state in a specific mix")
636
+ .addArgument(new Argument("<channel-id>", "ID of the channel"))
637
+ .addArgument(new Argument("<mix-id-or-name>", "ID or name of the mix (case-insensitive)"))
638
+ .action((channelId: string, mixId: string) =>
639
+ withClient(async (client) => {
640
+ const mix = await requireMix(client, mixId);
641
+ const { channels } = await client.getChannels();
642
+ const channel = channels.find((c) => c.id === channelId);
643
+
644
+ if (!channel) exitWithError(`Channel '${channelId}' not found`);
645
+
646
+ const mixAssignment = channel.mixes?.find((m) => m.id === mix.id);
647
+
648
+ if (!mixAssignment) {
649
+ exitWithError(`Channel '${channelId}' is not available in mix '${mix.name}'`);
650
+ }
651
+
652
+ const newMuted = !mixAssignment.isMuted;
653
+ await client.setChannelMixMute(channel.id, mix.id, newMuted);
654
+ console.log(
655
+ `Successfully toggled mute for channel '${channel.image?.name ?? channel.id}' in mix '${
656
+ mix.name
657
+ }'`
658
+ );
659
+ })
660
+ );
661
+
662
+ channelCmd
663
+ .command("isolate")
664
+ .description("Mute all channels in a mix except for the specified one")
665
+ .addArgument(new Argument("<channel-id>", "ID of the channel to isolate"))
666
+ .addArgument(new Argument("<mix-id-or-name>", "ID or name of the mix (case-insensitive)"))
667
+ .action((channelId: string, mixId: string) =>
668
+ withClient(async (client) => {
669
+ const mix = await requireMix(client, mixId);
670
+ const targetChannel = await requireChannel(client, channelId);
671
+ const { channels } = await client.getChannels();
672
+
673
+ let mutedCount = 0;
674
+ let alreadyMutedCount = 0;
675
+
676
+ for (const channel of channels) {
677
+ // Find the channel's assignment for this mix
678
+ const assignment = channel.mixes?.find((m) => m.id === mix.id);
679
+
680
+ // If the channel isn't in this mix (unexpected for Wave Link, but possible in API types), skip
681
+ if (!assignment) continue;
682
+
683
+ if (channel.id === targetChannel.id) {
684
+ // This is the chosen channel: Unmute it
685
+ if (assignment.isMuted) {
686
+ await client.setChannelMixMute(channel.id, mix.id, false);
687
+ console.log(`Unmuted target channel '${channel.image?.name ?? channel.id}'`);
688
+ } else {
689
+ console.log(`Target channel '${channel.image?.name ?? channel.id}' is already unmuted`);
690
+ }
691
+ } else {
692
+ // This is NOT the chosen channel: Mute it
693
+ if (!assignment.isMuted) {
694
+ await client.setChannelMixMute(channel.id, mix.id, true);
695
+ mutedCount++;
696
+ } else {
697
+ alreadyMutedCount++;
698
+ }
699
+ }
700
+ }
701
+
702
+ console.log(
703
+ `SUCCESS: Isolated '${targetChannel.id}' in mix '${mix.name}'.\n` +
704
+ ` - Muted ${mutedCount} other channels.\n` +
705
+ ` - ${alreadyMutedCount} channels were already muted.`
706
+ );
707
+ })
708
+ );
709
+
641
710
  // Input commands
642
711
  const inputCmd = program.command("input").description("Manage input devices");
643
712