Closed nicolopozzato closed 3 years ago
Only the faders are supported.
The MIDI control is just experimental. Not really an end-user feature right now. Right now it is implemented for the Behringer X-Touch, see https://github.com/corrados/jamulus/blob/master/src/soundbase.cpp#L289 There is some offset of 70 to support that device.
Ok, could some sort of midi lerning interface be inserted? In order to make all devices compatible.
I imagine a settings page where you select a fader and then physically move it, in this way going to check which channel moves on MIDI you map it to the first channel of the mixer. So on for the next ones.
@nicolopozzato Dunno if this is relevant, but there's something in the docs on enabling MIDI on this page (scroll down, GH wiki doesn't do anchors).
I'm working on trying to change the MIDI support... This is a test to begin to help this incredible software!
Now channel70 is fader0 in jamulus
I was thinking about a new midi mapping... 1-20 General Purpuse command example:
1 -> Mute Stream (button)
2 -> Reverb Slider
Then group of 3 midi channel for every Jamulus Channel, so:
21 -> Channel Fader 0
22 -> Mute Button 0
23 -> Solo Button 0
24 -> Channel Fader 1
25 -> Mute Button 0
. . . . . . .
In this way everyone can map the note nedded in their MIDI Controller... (my friend has a Korg NanoKontroller2)
Does anyone know a midi program for linux that simulate midi presses? I don't have a midi controller, and my friend has a mac and we can't compile in his pc because we get error after following the guide in the wiki.
If anyone have idea how to integrate the midi support also for windows would be very nice!
Would be awesome to have MIDI support to control faders, solos and mutes integrated with a user friendly interface .
I attached some mockups to show some interface and functionalities ideas:
I need to find a way to be able to test my code without a real midi controller...
For the moment I'm trying to connect to midi the mute button, I find the code a little bit messy so I need time to be able to understand the big picture.
As a first step I was thinking about a static channel mapping, the in the future to update to a "MIDI Mapping" window
I'm not a experienced developer, unfortunately I cannot help you much. For the sake of future reference, maybe you already know this better than me, I stumbled on this some time ago: https://www.music.mcgill.ca/~gary/rtmidi/ https://github.com/thestk/rtmidi Thank you @nicolopozzato
I believe that this issue addresses three topics which are only loosely coupled:
Regarding 1: I am aware of the following basic ideas:
The order of the Jamulus strips should be in sync with the order of the physical faders. If a client leaves, her strip disappears and the other strips will move to the left, changing their CC channel numbers. (corrados had this idea)
It might be desirable to persistently assign a physical fader to a specific client. This could be achieved by moving the strip of this client to the according position in the mixer. (Idea from dcocharro) This interferes a bit with the first idea. For example, if a client is assigned to fader 4, but there are currently only two clients, the 2nd Jamulus strip would be controlled by fader 4 (not 2). To me, that seems acceptable: the next two clients will be placed between the two existing ones and be controlled by faders 2 and 3.
The controls could support a learning function (like in Ardour): You activate the learn mode for a control, then move the physical fader a bit, and you're done. But I don't know how to combine that with the above ideas.
Regarding 2: I would definitely prefer a MIDI channel Jamulus --> Controller, so the motorfaders (or LED indicators, or whatever) can be controlled by Jamulus. However, for controllers which do not support this (are there any?), the suggestion from dcocharro is cool: Wait for MIDI CC to pickup the current value, then move the Jamulus fader.
I am rehearsing with a big band in Jamulus (17+ strips) We definitely need to be a way to map a CC numbers to the strip to a specific user. (using client name ) (some text config file is totally ok, no GUI needed). So I always will have ten1 Esa at the same position.
the things we want to set is: volume, stereo panning, mute, solo
the config file should also default values.
we could then create such a file and send to the entire band.
we could then create such a file and send to the entire band.
Wow, all in your band of 17 members have a MIDI control hardware available for usage with Jamulus?
The MIDI control is just experimental. Not really an end-user feature right now. Right now it is implemented for the Behringer X-Touch, see https://github.com/corrados/jamulus/blob/master/src/soundbase.cpp#L289 There is some offset of 70 to support that device.
What about reading the value of the offset from the settings (with a default of 70)? This should be relatively quick to implement and would enable a user to change the number by editing the settings file, i.e. without recompiling.
This is something I'm very interested in too.
The Mute Myself being on a midi controller is probably the one I'd use the most: the ability to have a foot pedal controller toggle that on and off.
I like the idea of MVP being able to configure the midi setup in a config/ini file on startup. Although a learn midi controller idea, and then it being tied to a user, wherever they end up in the fader list with sorting etc, would be amazing.
The Mute Myself being on a midi controller is probably the one I'd use the most: the ability to have a foot pedal controller toggle that on and off.
There are some solutions out there for this request, see, e.g.: https://sourceforge.net/p/llcon/discussion/533517/thread/f3252db0f5
I would like to implement saving the MIDI control offset in the settings as proposed in my comment from 29th June. The simplest way I see is as follows:
iCtrlMIDIOffset
in CSoundBase
and add it as parameter to the constructor for initialization.iCtrlMIDIOffset
in soundbase.cpp:256.iCtrlMIDIOffset
in CClientSettings
.iCtrlMIDIOffset
as member variable in CClient
and add it as parameter to the constructor for initialization.iCtrlMIDIOffset
from Client
to Sound
and further to SoundBase
similar as done for iCtrlMIDIChannel
.Client
and hand Settings.iCtrlMIDIOffset
to Client
on initialization.Please comment.
Hm, maybe a quick hack is even simpler? We already have iCtrlMIDIChannel. The allowed channels are from 0-16 as far as I know. Integer has 2^31 values. So a lot to play with ;-). So we could define: if --ctrlmidich is in range 0-16 we do the same as before. If it is > 16 we could apply some math which extracts the MIDI channel number plus the offset. Ideas?
16 channels total 0..15 or 1..16 depending on storage, only 4 bits required.
On Sun 15 Nov 2020 at 21:20, Volker Fischer notifications@github.com wrote:
Hm, maybe a quick hack is even simpler? We already have iCtrlMIDIChannel. The allowed channels are from 0-16 as far as I know. Integer has 2^31 values. So a lot to play with ;-). So we could define: if --ctrlmidich is in range 0-16 we do the same as before. If it is > 16 we could apply some math which extracts the MIDI channel number plus the offset. Ideas?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/corrados/jamulus/issues/95#issuecomment-727638680, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIJSQL6BTONKHH7Q4FKTXDSQBAYXANCNFSM4MLNSA7A .
One could use the first byte of iCtrlMIDIChannel for the channel and the rest for the offset. But maybe it's more clean to use two separate variables. iCtrlMIDIChannel could be reduced to an unsigned 8bit variable if you want to save space.
EDIT: One could also replace iCtrlMIDIChannel with a MIDISettings structure which contains the variables iCtrlMIDIChannel and iCtrlMIDIOffset. This is more clean and more flexible for potential future enhancements. If the size of both variables is small, e.g. 8 bit or 16 bit, the overall size does not increase.
It's not about saving space. We are talking about a functionality which less than 0.5 % of the Jamulus users use. So I want to keep the code added to Jamulus as small as possible. Extending the existing --ctrlmidich makes it possible that only the CSoundBase class must be changed slightly and nothing else.
What range do you need for the offset?
A very simple definition would be: --ctrlmidich [offset 3 digits][channel 2 digits]
, so e.g. for MIDI channel 11 and an offset of 723 you would use:
--ctrlmidich 72311
If the channel would be, e.g., 7, you would use:
--ctrlmidich 72307
For compatibility:
--ctrlmidich 7
would result in MIDI channel 7 and an offset of 70 (offset which is hard coded right now).
My master keyboard needs an offset of 20. As far as I know, the number has a range between 0 and 127, i.e. 7 bits.
Do you mean that you don't want to replace iCtrlMIDIChannel with a structure? That would enable to extend the functionality e.g. to buttons on the (hardware) fader strip (with the functionality to mute channels) or knobs on the fader strip (with functionality to pan) in a second step. This is useful e.g. when using the Jamulus client on a Raspberry Pie.
Ok, we could change iCtrlMIDIChannel to a string instead of an integer. Then you could do something like this:
--ctrlmidich [MIDI channel];[offset for level];[offset for mute];[offset for solo];[offset for pan]
So you could configure everything with just one command line argument.
That's a good idea. Then the constructor of CSoundBase can parse the string and set member variables for channel, level offset, etc., but the other classes remain agnostic of the structure.
Exactly, that was my intention to keep the implementation simple. We already have a similar parser for the server properties:
// split the different parameter strings
slServInfoSeparateParams = strServerInfo.split ( ";" );
[...]
// parse the server info string according to definition:
// [this server name];[this server city]; ...
// [this server country as QLocale ID]; ...
// per definition, we expect at least three parameters
if ( iServInfoNumSplitItems >= 3 )
{
// [this server name]
ThisServerListEntry.strName = slServInfoSeparateParams[0].left ( MAX_LEN_SERVER_NAME );
// [this server city]
ThisServerListEntry.strCity = slServInfoSeparateParams[1].left ( MAX_LEN_SERVER_CITY );
// [this server country as QLocale ID]
const int iCountry = slServInfoSeparateParams[2].toInt();
if ( !slServInfoSeparateParams[2].isEmpty() && ( iCountry >= 0 ) && ( iCountry <= QLocale::LastCountry ) )
{
ThisServerListEntry.eCountry = static_cast<QLocale::Country> ( iCountry );
}
}
I have just setup a branch where I did some initial implementation: https://github.com/corrados/jamulus/compare/feature_MIDI_parameters
I cannot test the new code. Are you able to compile and test the code?
Thank you very much for the implementation. I found a small bug in soundbase.cpp:236 (CSoundBase::ParseCommandLineArgument): due to the else
the second part is never parsed (since count >= 2 implies count >= 1). Fixing that, it works fine with my hardware.
Using a colon as separator is a little bit cumbersome because it has to be escaped from the shell. Maybe a separator that doesn't have to be escaped is handier.
due to the else the second part is never parsed
Thanks for testing. I just fixed this problem on the branch.
Maybe a separator that doesn't have to be escaped is handier
As we have a ";" as separator for --listfilter and --serverinfo, I want to keep it consistent for --ctrlmidich
I understand that you want to keep it consistent.
To be able to listen to multiple input types (faders, buttons, knobs), the length of the fader strip has to be known, because all inputs send on the same channel. I would use the second argument (after the channel and before the offset) for the fader strip length and set the default to 8, the length of both the Behringer X-Touch (excluding the master fader) and my master keyboard. All messages with CC number ranging from offset to offset + fader_strip_length - 1 would then be identified with a specific type (e.g. fader).
Can you please give me a hint which function I should trigger to mute/unmute and to set the pan level? I found the code not so easy to follow and couldn't spot the right function. Thank you.
Ok, I have some interest in this as well, particularly so since I have a Korg nanoKONTROL2 controller that is pretty much a spitting image of the usual mixer strips: It has a number of operating modes: an outdated "HUD" mode, a number of "Mackie control" interface modes where various controls are mapped to note on/off and other items, presumably to make for shorter MIDI messages than actual controller manipulations, and a native mode.
There is a simple controller definition program on the KORG homepage that can be made to work under Linux and Wine (counterintuitive to get its device selection to work under Wine). With that program you can reconfigure the used controls, whether the lights (all buttons except "Marker" and "Track" buttons can be lit) reflect the respective controller state ("internal") or follow what is being sent them ("external") and whether buttons are momentary (controller is 7F while button is pressed and becomes 0 again when released) or toggle, on a per-button basis. The default mode after reset, namely "internal" and "everything is momentary" does not make a whole lot of sense. Switching to "external" is achieved easily and is what should probably be considered the default way of operating since stuff can be changed in the Jamulus GUI, too.
My idea for a commandline interface would have been extending the --ctrlmidich
spec from its current ch; fader0ctl
spec to ch; fader0ctl; pan0ctl; s0ctl; m0ctl
syntax. When preceding any of the controller specs with '+', Jamulus also provides a midi channel it writes to and it will write controller settings changed inside of Jamulus out to the controller. You'd likely want to write out values for fader/panner if you have motor faders and/or endless rotary controllers with position display (Behringer offers either). For the case of the nanoKONTROL2, you'd be writing just the S and M button values.
That does not yet give a good idea what to make of the transport controls (record button is obviously the inverse of the "Mute self" control, play button could be "connect", 'Track < >' buttons tend to be used for jumping the controller over 8 channel to the left/right (when more than 8 channels are actually available). But the main thing would be providing lit S/M controls. A note aside: Not sure what to do about R buttons. Make them read-only and indicate everyone who has not muted their channel? Use it to speak privately to one party (sort of the converse of the S button)?
At any rate: does that sound like a reasonable starting plan, or is it tomfoolery to overload the --ctrlmidich
option in that manner?
I need to find a way to be able to test my code without a real midi controller...
I can pitch in for the Korg nanoKONTROL2 here: it offers a "native" mode implemented with Midi controllers, and an application where you can define the controller numbers for every button/slider/pot and whether they act as one-shot buttons (events on both push and release) or as toggles (events on push). It can light most of the buttons via Midi commands, and it can also (by holding buttons while powering up) go into various non-native modes working mostly via note on/off events that include the Mackie control interface and HUD (some older interface used with a particular DAW). The application runs under WINE (it doesn't get the MIDI devices for both read and write right, you need to explicitly configure them in the settings menu, then manually select the nanoKONTROL2 as the device to configure, but then it works). Reasonably affordable second hand, runs via USB. Has no motor faders or "infinite" rotary controls, but at least feedback for the buttons.
So at a comparatively moderate price point, it's good for testing a whole lot of functionality of different more expensive controllers. And is quite convenient, actually.
With regard to syntax: for more than one controller type it becomes important to figure out the count. I mulled through a number of schemes for figuring out the actual counts, but I think that this kind of second-guessing is likely not helping a lot.
So how about (for a nanoKontrol2)
-ctrlmidich 'v0-7;s32-39!;m48-55!;p16-23'
Those are ranges for volume, solo (with writeback), mute (with writeback), pan.
Alternatively
-ctrlmidich 'v0*8;s32*8!;m48*8!;p16*8'
Or maybe
-ctrlmidich 'v0*8;s+32*8;m+48*8;p16*8'
Requiring ranges to be specified explicity allows avoiding to employ some magic for figuring out which function a particular controller belongs to.
Since the length of the fader strip can be considered constant (i.e. the number of faders, pan knobs, mute buttons, etc. is the same), it is redundant to give it for each parameter. Thus, I suggest to give the parameters in the order channel, length of the fader strip, offset for faders, offset for pan, offset for mute, offset for solo. For your example for the nanoKontrol2 that would be
--ctrlmidich "0;8;32;48;16"
where 0 is the MIDI channel, 8 the length of the fader strip, 32 the offset for the faders, 48 the offset for pan, and 16 the offset for the mute buttons.
andreassch notifications@github.com writes:
Since the length of the fader strip can be considered constant (i.e. the number of faders, pan knobs, mute buttons, etc. is the same), it is redundant to give it for each parameter. Thus, I suggest to give the parameters in the order channel, length of the fader strip, offset for faders, offset for pan, offset for mute, offset for solo. For your example for the nanoKontrol2 that would be
--ctrlmidich "0;8;32;48;16"
where 0 is the MIDI channel, 8 the length of the fader strip, 32 the offset for the faders, 48 the offset for pan, and 16 the offset for the mute buttons.
The scheme with a prefix letter and given count will also work for non-strip buttons like "mute transmission" (could be on the general "record" button). For generic controllers, the organisation might not always be in strips: one might use non-dedicated rotary controllers for pan. Also one can specify one but not the other, like if you don't use "mute" buttons.
That was sort of the rationale behind my proposal: doing something that does not use an artificial order one needs to remember and that we won't need to overhaul time and again.
-- David Kastrup
I agree that your approach is more versatile. And letters as identifies make it easier to use.
Since the PR was merged, I'll close this now. If it needs to be re opened, please re open it.
I have read that from the 3.4.4 (2020-03-25) version there is MIDI support.
- added support for controlling the audio mixer faders with a MIDI controller (MacOS and Linux)
How can i map my MIDI Controller to the mixer fader, solo and mute button? Also there is a way to map the rever effect and the mute my input?
I don't have find anything about it. Only some thing about it in the source code...
For info i have a Korg NanoKontrol2