featherbear / presonus-studiolive-api

Exploring the PreSonus network control protocol from a StudioLive Series III
https://featherbear.cc/presonus-studiolive-api/
46 stars 13 forks source link

API not sending proper mute/unmute commands #3

Closed paco3346 closed 2 years ago

paco3346 commented 3 years ago

After the conversion to TypeScript the mute/unmute commands are no longer working.

I did a packet capture and found this was because the wrong command was being sent to the mixer. Here's a screenshot: image

In my case I was trying to mute channel 1. We should see line/ch1/mute instead of 1/mute.

featherbear commented 3 years ago

Hey @paco3346 !

I don't have any user-facing type definitions created yet (gotta figure out how to do that) - but my idea for the usage of the mute functions were that you would pass in one of the enum keys as defined in channels.ts

Your change will only allow the input channels from being (un)muted; however the main / aux / subs / fx can also be muted in the same fashion :)

featherbear commented 3 years ago

Something along the lines of

api.setMuteState(CHANNELS.CHANNEL_6, true)

///

api.setMuteState(CHANNELS.MAIN, false)
paco3346 commented 3 years ago

Wow, ya know, I'm not sure how all the other channel types (main, aux, sub, etc) slipped my mind.

I like the idea of Enums for internal use but as you stated - that doesn't really work for user-space code.

What about additional methods for each type of channel? Yes, it adds 8 methods but at least that way the user-space code doesn't even need to know about the Enum. The method names become self documenting and only need an int* passed.

*well... float since this is JS

featherbear commented 3 years ago

Number actually :P (or is it number...)

That sounds like a good idea to implement, having a muteMain / unmuteMain / setMuteMain / etc however I wouldn't want to pollute the namespace too much - and would think that overloading the method names would be better.


Is your use case currently calling

// let someChannel = 6

api.setMuteState(someChannel, true)

Perhaps a lookup function could be created instead, getLineChannel(6) which can be passed into the setMuteState method? What do you think?

paco3346 commented 3 years ago

Yes, my use case would be calling setMuteState() directly but it feels unnecessary to have a lookup for something as simple as a number.

I had a thought earlier that I think may work well- what about adding a third parameter named Type where Type is an enum of Channel, Aux, Main, etc. This way we don't have 60+ enums to represent the entity that needs to be muted and instead only have 6. This also lets you apply some assertion logic to the input params to ensure the channel number is valid for the given type.

For me, ideally the API would have simple calls where the user-space code wouldn't necessarily even need to know about the enums if it's not also using TS. (See example at bottom).

export enum CHANNEL_TYPE {
  LINE = 'line',
  MAIN = 'main',
  TALKBACK = 'talkback',
  AUX = 'aux',
  SUB = 'sub',
  FX = 'fxbus'
}
getChannelStr (channel: Number, type: CHANNEL_TYPE) {
  // maybe assert that the channel number provided doesn't go above the maximum for a given type?
  return `${type}/ch/${channel}`
}
setMuteState (channel: Number, type: CHANNEL_TYPE, state) {
  let channelStr = getChannelStr(channel, type);
  this.sendPacket(
    MessageTypes.Setting,
    Buffer.concat([
      Buffer.from(`${channelStr}/${ACTIONS.MUTE}\x00\x00\x00`),
      onOffCode(state)
    ])
  )
}
api.setMuteState(2, CHANNEL_TYPE.LINE, true)
api.setMuteState(2, 'line', true);
featherbear commented 3 years ago

@paco3346

Adding a third parameter sounds like a good idea :+1: Feel free to make a PR implementing that, otherwise it will be a while until I find time to get it done

featherbear commented 2 years ago

WIP in https://github.com/featherbear/presonus-studiolive-api/commit/1b3a43ebb57072fe6d9fa44666fde0be324ea824

featherbear commented 2 years ago

Latest v1.0.5 (f93b196c77727da60109f72ec9b2461a2f930a16) release has the following function calling conventions for muting

api.mute( ChannelSelector )
api.unmute( ChannelSelector )
api.toggleMute( ChannelSelector )
ChannelSelector = {
  type: "LINE",
  // type: CHANNELTYPES.LINE,
  // ^ Using the enum instead

  channel: 1,
  // channel: "10"
  // ^ We can pass a string if we need to (i.e. can't be bothered to convert)
}