Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always give own channel MIDI number 0 #3419

Closed
wants to merge 2 commits into from

Conversation

softins
Copy link
Member

@softins softins commented Nov 6, 2024

Short description of changes

Ensure the user's own channel is always given MIDI channel 0, so that the user is always the leftmost fader when using an external MIDI fader bank.

  1. Moved my channel ID from the Mixer to the Client, so it is available when headless too.
  2. Client's own channel, sent by the server, is always assigned to MIDI number 0, for left-most fader. Server channel numbers less than the user's own channel are bumped up by 1 to get the MIDI channel.
  3. Translate between server channel and MIDI number at the client level.

CHANGELOG: Client: always assign MIDI channel 0 to the user's own channel.

Context: Fixes an issue?

Raised in https://github.com/orgs/jamulussoftware/discussions/2220#discussioncomment-10811813

This supersedes the solution proposed in #3394, and in particular avoids the use of a duplicate fader. It also needs no change to the --ctrlmidich parameter.

It is an implementation of my proposal in #3394 (comment)

Does this change need documentation? What needs to be documented and how?

Only to document that the user's own channel will always be given fader channel 0, and that this is only relevant
when using --ctrlmidich to assign an external fader bank.

Status of this Pull Request

Tested and ready for review

What is missing until this pull request can be merged?

Consensus on the approach and testing on other platforms. Tested on Pi Linux.

Checklist

  • I've verified that this Pull Request follows the general code principles
  • I tested my code and it does what I want
  • My code follows the style guide
  • I waited some time after this Pull Request was opened and all GitHub checks completed without errors.
  • I've filled all the content above

1. Moved my channel ID from the Mixer to the Client, so it is
   available when headless too.
2. Client's own channel, sent by the server, is always assigned
   to MIDI number 0, for left-most fader.
3. Translate between server channel and MIDI number at the client level.
@softins
Copy link
Member Author

softins commented Nov 6, 2024

@AndersGoran - I would be interested in your feedback on this solution. Thanks!

@AndersGoran
Copy link

@AndersGoran - I would be interested in your feedback on this solution. Thanks!

I'm happy with this for my purposes!

I can confirm I get my own fader mapped to the first CC I give in --ctrlmidich - without the "z" flag. Typically I will only give one (1) CC, so that's exactly what I need.

I tested on one server with two other people - I saw channel numbers 0 (me), 1, 2, and with midi string "0;f100*4", my first three physical controls map to channels 0,1,2 in order - perfect. No duplicate control for me.

That said, on another server, there was me (0) and someone else (9) and then I could only control my own fader, since 9 is out of range. That's not an issue for me but rather a general problem with --ctrlmidich, that the CC range we can give does not really correspond to channels on the screen, but to these internal channel numbers that can very well be out of range. That's perhaps a discussion for another time?

I tried the macOS build at https://github.com/jamulussoftware/jamulus/actions/runs/11702443604/artifacts/2151703050

@softins
Copy link
Member Author

softins commented Nov 6, 2024

I'm happy with this for my purposes!

I can confirm I get my own fader mapped to the first CC I give in --ctrlmidich - without the "z" flag. Typically I will only give one (1) CC, so that's exactly what I need.

I tested on one server with two other people - I saw channel numbers 0 (me), 1, 2, and with midi string "0;f100*4", my first three physical controls map to channels 0,1,2 in order - perfect. No duplicate control for me.

Great, thanks for the quick feedback!

That said, on another server, there was me (0) and someone else (9) and then I could only control my own fader, since 9 is out of range. That's not an issue for me but rather a general problem with --ctrlmidich, that the CC range we can give does not really correspond to channels on the screen, but to these internal channel numbers that can very well be out of range. That's perhaps a discussion for another time?

Yes, that could happen if there had been many people on a server, and most depart leaving one of the last joiners.

Addressing that kind of issue would require a considerably more complex design, and still probably wouldn't cater for the above scenario without fader positions jumping about.

I think the solution in this PR is worth having now for the majority of scenarios, without keeping it on hold awaiting a completely new design structure that might take ages to materialize!

@@ -436,6 +436,7 @@ void CChannelFader::Reset()
plblCountryFlag->setVisible ( false );
plblCountryFlag->setToolTip ( "" );
cReceivedChanInfo = CChannelInfo();
cReceivedMIDIID = INVALID_INDEX;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be using INVALID_INDEX here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it just needs to be something like -1 that couldn't match a real MIDI Controller offset from 0 upwards. I don't mind whether we use that symbol or define another symbol for it, although I don't see the point of changing it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I said. I was told it was confusing so I changed it. I'm raising here because it was one of the first objections on my pull request, so I'm assuming it was something important.

@@ -1123,7 +1123,7 @@ void CAudioMixerBoard::ChangeFaderOrder ( const EChSortType eChSortType )
}
break;
case ST_BY_SERVER_CHANNEL:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this get renamed if it's always the received MIDI ID?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did wonder about that, and even started to change the name, but then had second thoughts, as it implied the menu option should change to "Sort by MIDI Channel". I think this could be more confusing to some users.

The actual server channel numbers and the channel assigned to the particular client are never actually visible to the user, except when used for MIDI channels.

What we are doing here by mapping is presenting to the user a view that always uses 0 for the user's own channel, and maps the rest of the channels up by one. As far as the user is concerned, they are server channels (even if virtual); we just guarantee that the user themselves is channel zero. So whether or not a MIDI controller is used, a "Sort by Server Channel" will always put the user's own channel first, whether or not "Show Own Fader First" is enabled. I think that is a worthwhile improvement.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a definite source of potential confusion, to be honest. I'd only want my fader sorted first if I asked for it, if there's an option in the menu. I'd be wondering why the option was there, otherwise.

Certainly for "No sorting", always putting own fader first is wrong unless requested.

@@ -1267,7 +1267,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
vecpChanFader[iChanID]->Reset();
vecAvgLevels[iChanID] = 0.0f;

if ( static_cast<int> ( iChanID ) == iMyChannelID )
if ( static_cast<int> ( iChanID ) == pClient->GetMyChannelID() )
Copy link
Collaborator

@pljones pljones Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe stick pClient->GetMyChannelID() into a variable as it's used in a few places here. (The call is crossing threads, I think.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value doesn't change while connected, and it is just a simple Get method, so I don't think threads are relevant in this case. However, I see most of these uses are within a loop, so I'm happy to fetch once to a local variable within each function and use that within the loop. I'll add a commit for that shortly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 072b2af


int CClient::ChanToMIDI ( const int iChannelIdx )
{
if ( iMyChannelID == INVALID_INDEX )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, it was suggested using INVALID_INDEX for something that isn't an index into a vector wasn't a good idea.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, we can choose an additional name for a -1 value if you prefer. I see src/global.h has both INVALID_PORT and INVALID_INDEX for -1, so we could also add something like INVALID_ID, INVALID_CHANNEL or INVALID_VALUE ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my PR.

@@ -272,6 +274,10 @@ class CClient : public QObject
Channel.GetBufErrorRates ( vecErrRates, dLimit, dMaxUpLimit );
}

// convert between MIDI index and real channel index
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be done my the MIDI-handling code? Otherwise, it could do with a longer comment explaining why it's here.

{
// map the MIDI index to the real channel number
const int iChannelIdx = MIDIToChan ( iMIDIIdx );
Copy link
Collaborator

@pljones pljones Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client shouldn't need to worry about this. It should have been handled in the MIDI code. The MIDI code should signal this slot.

void ControllerInPanValue ( int iChannelIdx, int iValue );
void ControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );
void ControllerInFaderIsMute ( int iChannelIdx, bool bIsMute );
void ControllerInFaderLevel ( int iMIDIIdx, int iValue );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMidiCtlEntry should have the first entry renamed to match if it's not iChannel any more. Or else rename it to iChannel -- it's the value of CMidiCtlEntry::iChannel, after all...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really a "virtual channel", where 0 is our fader, and the others are allocated in server order.

In MIDI-speak it's not a channel anyway, it's a controller offset. We are just using it to access a Jamulus channel.

I'm happy to rename items if you have suggestions, but I still think the architecture is ok.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the offset from the base MIDI Controller number. It's the Jamulus channel numbers that get re-ordered so that the user's own Jamulus channel is at offset 0 when the user uses z (and should only be when they use z).

Copy link
Member Author

@softins softins Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, whatever. My problem with the z solution is the duplicate fader. That's a show-stopper for me, and why I put in a lot of work to come up with an improved solution, instead of just complaining about it.

I'm going to leave this for a while.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think CSoundBase::ParseMIDIMessage is where the mapping from MIDI Controller Number to Jamulus Channel Number should happen. Keep the MIDI out of CClient entirely.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my general comment in the main thread.

@pljones
Copy link
Collaborator

pljones commented Nov 6, 2024

I'm not particularly happy with putting MIDI knowledge into CClient - we don't (maybe I should say "shouldn't") put JSON RPC knowledge in or UI widget knowledge in. MIDI control of the client should happen through signals to slots and the client shouldn't really know what caused the slot to be called.

Ideally, MIDI control, JSON RPC control and UI control would use the same slots on the client - i.e. they'd emit a signal that complied with the interface defined by the slot and they'd connect themselves to the slot (because the client doesn't know about them). But all three should use the same slot for the same purpose with the same arguments, without CClient having to know what called it.

@softins
Copy link
Member Author

softins commented Nov 7, 2024

I'm not particularly happy with putting MIDI knowledge into CClient

I can see where you're coming from, but I'm not convinced. At the moment, Soundbase doesn't know anything about Jamulus channels, and particularly not about which is our channel. All it does is pass MIDI numbers (CC offsets) to the client.

It's the client that know what our channel number is, and decides how to use and map those MIDI numbers.

In fact before this PR, it was only the Audio Mixer Board that knew about our channel. That meant decisions based on it could only be made at the GUI level, and precluded headless operation. I needed to move iMyChannelID down to the CClient so that it was also available for the mapping in headless mode.

You mentioned both MIDI and JSON-RPC. Should they all be responsible for knowing what our current channel number is, so that they can each do their own mapping? I'm not convinced. They can both just rest in the knowledge that virtual channel number 0 will always control our own channel, and rely on CClient to to the right thing. That isn't specific to MIDI.

So I would still argue in favour of what I put in this PR.

@pljones
Copy link
Collaborator

pljones commented Nov 7, 2024

If you look at my implementation, you'll see that soundbase.cpp continues to know nothing about Jamulus channels - all that changes is the parsing of the --ctrlmidich argument. The determination of channel remains localised in audiomixerboard.cpp, as it is now.

I think you're pulling into CClient concerns that shouldn't be brought in.

My implementation also removes CClientDlg needing to be involved in knowing about MIDI controls, so improving the separation rather than making it worse, like this.

@softins
Copy link
Member Author

softins commented Nov 7, 2024

If you look at my implementation, you'll see that soundbase.cpp continues to know nothing about Jamulus channels - all that changes is the parsing of the --ctrlmidich argument. The determination of channel remains localised in audiomixerboard.cpp, as it is now.

Except that you end up with two separate faders controlling the "own" channel, rather than having the "own" channel only being fader 0 and the others being arranged to suit.

And audiomixerboard is way to high up the hierarchy, as I found, which means the headless code can't use it.

I think you're pulling into CClient concerns that shouldn't be brought in.

I still disagree. I'm effectively virtualising the channel numbers so that own channel is always 0.

My implementation also removes CClientDlg needing to be involved in knowing about MIDI controls, so improving the separation rather than making it worse, like this.

CClientDlg is not involved. If you look at my changes, the only changes to it are to pass the client pointer up to the mixer board, and the removal of a couple of unneeded signal/slot connections.

@softins
Copy link
Member Author

softins commented Nov 7, 2024

This shouldn't be such hard work :(

@pljones
Copy link
Collaborator

pljones commented Nov 9, 2024

Except that you end up with two separate faders controlling the "own" channel, rather than having the "own" channel only being fader 0 and the others being arranged to suit.

Yes, that's to be expected:

  • assign self + four faders
  • join a server with no one on, you get self (first fader), plus self (second fader)
  • join a server with four people on, you get self (first fader) and four other people (assuming the server doesn't give you a lower fader number than four)
  • join a server with 150 other people on, same deal
  • join a server with three other people on, you get self (first fader), those three in 1 to 3 (probably) and self again

I don't see that as confusing or a problem.

EDIT: if the sort order is by Jamulus channel number. I've my "special" fader plus whoever (including me) is assigned to the normal channel order. Upsetting that means the visual cues between what I see on screen and what I've set up on my MIDI controller aren't congruent.

@pljones
Copy link
Collaborator

pljones commented Nov 9, 2024

And audiomixerboard is way to high up the hierarchy, as I found, which means the headless code can't use it.

Agreed. The "model-view-controller" concept torn into shreds. Only CClient should know about state (whether transient or persistent). The UI controls, JSON-RPC controls, MIDI controls, etc, shouldn't have to know anything - just send signals for "what just happened".

Maybe that should be what Jamulus 4 does...

This shouldn't be such hard work :(

Agreed, too.

@pljones
Copy link
Collaborator

pljones commented Nov 9, 2024

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.

@softins
Copy link
Member Author

softins commented Nov 9, 2024

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.

@softins softins marked this pull request as draft November 9, 2024 12:04
@pljones
Copy link
Collaborator

pljones commented Nov 9, 2024

OK -- maybe this approach to --ctrlmidich should force "Own Channel First" in the UI sort order (disabling the menu option). Maybe it should also force "Sort by Jamulus Channel" (again, disabling all the choices). This way the relationship between UI and MIDI hardware controls would be fixed. (I was thinking of doing this as a follow up to my original PR.)

@softins
Copy link
Member Author

softins commented Nov 9, 2024

I still think there is a better approach. I'm just writing up some notes to post in a while.

@softins
Copy link
Member Author

softins commented Nov 9, 2024

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 into clientChannels[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 or iChannelID 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 of CClientChannel* pointers integer 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 the CClientChannel array/vector by client channel ID and fetch iServerChannelID. Both of these operations should be local to the CClient.

  • 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.

In view of recent experience, I'm not going to waste a lot of time implementing the above until there is agreement about the approach.

@pljones
Copy link
Collaborator

pljones commented Nov 10, 2024

OK, from a GUI perspective - all the existing sort options would continue to work as is, except "Sort by Channel", where "My Channel" would automatically be first (and thus adding "Own channel first" would have no visible effect; still useful on the other options). --ctrlmidich would show "client channel" and those would always start in range. The client would no long "care" what server channel was used. So:

A server with one person on where they got server channel 10 allocated when they joined.
I join:

  • the server allocates me server channel 0 (as it's now free) and I store that in clientChannels[0].iServerChannelID
  • the server tells me there's someone else on server channel 10 and I store that in clientChannels[1].iServerChannelID (because that's my next free channel as I'm just joining)
  • someone else joins and gets server channel 1 (that's also now free) and I store that in clientChannels[2].iServerChannelID

Now two different scenarios - not problems, just to think through:

  • the person who was on leaves, freeing server channel 10 and I free clientChannels[1].
  • Scenario 1:
    • someone else new joins, gets server channel 2 and I store that in clientChannels[1].iServerChannelID because it's the lowest free
    • the person who was on and left rejoins almost immediately and gets server channel 3, that in clientChannels[3].iServerChannelID
  • Scenario 2:
    • the person who was on and left rejoins almost immediately and gets server channel 2, that goes in clientChannels[1].iServerChannelID
    • someone else new joins, gets server channel 3 and I store that in clientChannels[3].iServerChannelID because it's the lowest free

OK, I think that makes sense, too -- if you leave and rejoin, the likelihood is you'll get the same clientChannels index, right? If you leave and someone else joins before you get back, hard luck, you're in a different place on the desk now.


EDIT:

  • For "No User Sorting" (which probably shouldn't say "User" according to the Style guide), the definition is that we always add a newly entering person to the highest mixer position. This is achieved internally by assigning the display vector a sort count number. I'm not keen on the current implementation. If we could add "join sequence" to CClientChannel and have that automatically set when a channel is allocated to from a constantly incrementing number (per server session "I" join), then sort by that, I think it would make the View->Sort process easier, as it would always be getting channel information.

@pljones
Copy link
Collaborator

pljones commented Nov 10, 2024

From there, GUI, JSON-RPC and MIDI control of CClient messaging to the server to adjust the mix:

  • I think CClient needs to have the channel volume level stored (so the GUI fader just tells CClient to adjust that, and CClient knows to tell the server to adjust the mix, JSON-RPC and MIDI make the same call); if the value is changed, CClient emits a "volume changed" signal (the GUI fader tracks this to follow changes from JSON-RPC and MIDI but ignores it whilst doing its own update to avoid "stuttering").
  • Same for group, mute and solo settings -- currently these are embedded in the GUI but should be managed in CClient to allow JSON-RPC and MIDI control not to rely on the GUI.

So I think this is a good first step (and a discrete change from the above).

@pljones
Copy link
Collaborator

pljones commented Nov 10, 2024

I'm wondering if we need to avoid making CClient (or, rather, client.cpp) too complicated -- should the concept of the mixer (which spans audio I/O and network I/O conceptually) be handled by CClient? Should CClient get pared down to managing the client protocol message requests and responses?

That would mean the existing "GUI-only" mixing desk would be split into a class that was independent of CClient and the GUI that just managed all the interaction between CClient and the CClientChannel[]. The GUI would then be a visual presentation layer over that, and there would also be JSON-RPC and MIDI "presentation" layers.

I'd almost not mind all of that in one file with a bunch of #ifndef ... for each of GUI, JSON-RPC and MIDI exclusion options.

@ann0see
Copy link
Member

ann0see commented Nov 10, 2024

That would mean the existing "GUI-only" mixing desk would be split into a class that was independent of CClient and the GUI that just managed all the interaction between CClient and the CClientChannel[]. The GUI would then be a visual presentation layer over that, and there would also be JSON-RPC and MIDI "presentation" layers.

I was honestly also thinking about this for a while. From the perspective of good separation it would make sense:

  1. MIDI handling gets less messy
  2. JSON-RPC can get feature parity with the GUI
  3. Mobile GUI could be another "GUI Client" which is native to the mobile OS

The biggest downside would be that this may be hard to get through a review.

@softins
Copy link
Member Author

softins commented Nov 10, 2024

These are all good thoughts. But I think we should go incrementally, rather than for a big bang which might take ages to finish or not even get around to being completed.

So I would think of implementing what I suggested above within CClient and not yet making any changes to the GUI and Audio Mixer. That could then be done separately afterwards. I don't actually think the mixer is within CClient anyway. When running with a GUI, we have CClientDlg above it, and CAudioMixerBoard above that, with signals from below being passed to slots above. It should all work unchanged and won't care that iChannelIdx is now a client-side channel instead of a server-side channel.

I'm aware too that it will be necessary to translate from server channel IDs to client channel IDs within CChanInfo, when passing them up to the mixer.

@pljones
Copy link
Collaborator

pljones commented Nov 10, 2024

Yep, not suggesting doing it in one go. But having these goals laid out clearly as incremental planned steps would be useful, I think, so we can assess progress to a better implementation.

@softins
Copy link
Member Author

softins commented Nov 11, 2024

Please continue any discussion in Issue #3423, the result of which will be a PR in due course that will supersede the one here (and also supersede PR #3394)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants