-
Notifications
You must be signed in to change notification settings - Fork 233
Description
I'm opening this issue so that implementation can be discussed independently of #3419, which will be superseded by this approach. I'll copy the relevant comments across with attribution.
Originally posted by @softins in #3419 (comment)
I still disagree. I'm effectively virtualising the channel numbers so that own channel is always 0.
If that's the intent, discussing "MIDI" throughout the approach is highly misleading.
Well, yes, but that concept only came to mind when you started also relating JSON-RPC to it.
OK, let's take this concept and run with it, although without the "virtual" term.
Currently, there is no distinction between "client-side" channel and "server-side" channel. The iChannelID
or iChannelIdx
, and also the iMyChannelID
, currently refer to the channel index allocated within the connected server and sent to the client. The Jamulus protocol by definition uses the server-side channel number to identify channels.
Let's decouple the client-side and server-side channel numbers, and make "client-side channel" a concept local to an individual client, mapping it within the client at the lowest level possible to the "server-side channel". Something like this within client.h
:
class CClientChannel {
...
int iServerChannelID;
...
};
CClientChannel clientChannels[MAX_NUM_CHANNELS];
Maybe we put other items in there that are currently just arrays indexed by server channel index. Or maybe not, but they would now be indexed by client-side channel ID.
-
When the client connects to a server (unless the server is ancient), it receives a
CLIENT_ID
message before anything else, containing the server-side channel allocated to that client. We assign that server channel to client channel 0, always, and put the received ID intoclientChannels[0].iServerChannelID
. -
When we receive a list of connected clients from the server, for any new server channel in the list, we allocated the lowest free client channel to it and again store the server channel in
iServerChannelID
. For existing known server channels, we just look up the associated client channel to update its data if necessary. -
If connected to an ancient server that doesn't send
CLIENT_ID
, the channels will just be allocated as received, so the "own" channel could be anywhere. That's unavoidable, but hopefully very rare. In that case, we don't reserve client channel 0, and it will get used by the first server channel to be seen. -
Any time we pass an
iChannelIdx
oriChannelID
around within the client hierarchy, it is referring only to a client channel. -
Server channel numbers only get used when processing or sending protocol messages. If we have a server channel ID and need to find the associated client channel, we can either do a quick linear search for matching
iServerChannelID
or can maintain a lookup table ofinteger client channel IDs, indexed by server channel ID. Obviously, to convert from a client channel ID to a server channel ID for sending to the server, we just index theCClientChannel*
pointersCClientChannel
array/vector by client channel ID and fetchiServerChannelID
. Both of these operations should be local to theCClient
. -
Once a server channel has been assigned to a specific client channel, that assignment will not be changed until that server channel disappears again. This will avoid things like fader assignments jumping unexpectedly. When a server-side channel disappears due a remote client disconnecting, our client-side channel that it was associated with gets marked as free for re-use (
iServerChannelID = INVALID_INDEX;
), but other channels do not get moved to occupy the freed client channel. -
Midi controller number offsets can then be used unchanged to index into client-side channels, and channel 0 will always be the client's own channel (except with an ancient server). There will be no need for the kludgy
z
option in--ctrlmidich
, nor for a duplicate fader. -
Other potential operations such as a JSON-RPC method would also identify channels only by client-side channel ID. As would the GUI Audio Mixer Board.
-
"No sorting" will by default be by client-side channel ID, so "Sort by Server Channel" would no longer be required. I can't see any reason to sort by actual server-side channel number.Actually on second thoughts, it might still be required for the same reason it was introduced, due to the current allocation strategy of the faders in the GUI. But it could just be renamed to “Sort by Channel”, as it would be sorting on the client-side channel number. -
This technique would also overcome the observation of @AndersGoran that when he connected to a server where the only other user had a high-numbered server channel, he could not control it with a MIDI fader.