Quick Sign In:  

Forum: VirtualDJ Technical Support

Topic: Live update encoder value on midi fighter twister - Page: 1
I got a Denon x1850 mixer and two sc6000 units and still was using the mixtrack platinum controllers as well for extra buttons and the eq knobs to control stems. It ends up being a lot of hardware on the table to manage, but the utility of it all is incredible and gives you a lot of control.

I have since replaced the mixtrack platinum fx controllers with one midi fighter twister. I created a custom device xml for it, but i am having an issue I don't know how to program. There doesn't seem to be a way to get current values to reset the encoders if you reset the controlled value of what the encoder controls via another method.

The encoder always displays the last value set by the encoder itself regardless if you changed that value using a different control, button, with the mouse, or whatever.

Is there a way to update the value displayed by the encoder based on the current value and moreover is there a way to have is displayed live as you adjust the value via other means. If I were to adjust the eq say using the mouse how do I display the value live on the midi fighter twister? Really what I want is to reset stem values via a button press (already have that) but then have the mft update the dots back to the default value so that when I use the encoder again it is adjusting from the default instead of the last adjusted value of the encoder itself.

Please let me know if I explained this well enough. Thanks.
 

Posted Tue 14 Dec 21 @ 11:55 am
There are two different things here:
1) Reading the encoder.
2) Setting the ring of the encoder.

I believe that you have done the first thing correctly (more on that later)
For the second, according to the user manual:
Midi Fighter User Manual wrote :
It is possible to sync the display value of the CC or note to the parameter it is controlling in your software of choice. Simply map the MIDI OUT for that parameter to the same MIDI number on channel 0.


So, let's say you have
<slider cc="0x00" channel="0" name="ENCODER_1" />

You need to define a LED for it:
<bar cc="0x00" channel="0" name="LED_ENCODER_1" default="ENCODER_1" sendstatic="true"/>


Therefore now you can control the "LED_ENCODER_1" key on your mapper to control the ring of encoder 1

PS: VirtualDJ has two different definitions for "encoders" (as meant here)
  • <slider /> element which is a knob, slider or encoder that sends absolute values.
    This means that the values sent from the control follow a linear structure, ranging from 0x00 (0) to 0x7F (127)
    According to the device manual, despite the fact that it has "encoders" on it, they act as SLIDERS since they sent absolute position messages ("...and the control change messages as CC’s 0 through 127.")
  • <encoder /> element which is used for encoders that send relative changes.
    Usually those controls send values as -1/+1 from previous position. According to device documentation it's "encoders" don't seem to fall in this case.


So, now you need to check your definition and make sure that all your "encoders" are actually defined as <slider /> elements like the example I gave you above.

Finally, you don't need to know the HEX value your "encoder" (slider) sends to software.
All you need to know is that VirtualDJ converts the 0-127 range to a float ranging from 0.0 to 1.0
And that's the values you need to use to send on the LED of the "encoder" (slider) as well. VirtualDJ will do the conversion to HEX based on the definition.

Also: For simple cases like "eq_high" you don't need to map both "ENCODER_X" and "LED_ENCODER_X" to the same action.
Because of the 'default="ENCODER_X"' attribute we used on the definition, the LED will use the same action as the "default" control.
You may need to map/remap the LED elements only if they don't work as expected on COMPLEX mappings (that the "update" of the ring may need different script from the one that controls the software)
 

Posted Tue 14 Dec 21 @ 12:36 pm
UPDATE: awesome explanation Phantom. (the Wizard of all )
I will add what I was typing during your post, in case it helps in any way.
__________________________________________

Don't know if I understand completely.

The MFT definition xml file needs

for encoders:
a) Slider elements to send data to VDJ using channel 0 (4 for secondary functions)

b) and Bar elements for VDJ to send its knob positions back to the MFT, also using channel 0 (4 for secondary functions) with the same naming used for both the Slider and Bar elements

possibly the definition file does not contain the bar elements to send VDJ's knob positions back to the MFT, so when you touch the MFT encoder it just sends its current position (value) of VDJ, since it has not changed based on changes to VDJ, adjusted by other switches (your button) or a mouse.

http://www.virtualdj.com/wiki/ControllerDefinitionMIDIv8.html

The Bar element, may look somewhat like this (for primary encoder function) and assuming the MFT is configured to use CC and not Note midi:

<bar cc="0x00" deck="XXXX" min="0x00" max="0x7F"  fill="no" name="SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT" channel="0" />
 

Posted Tue 14 Dec 21 @ 1:35 pm
The example I gave above is all that's needed to get going.
It is actually tailored against "ENCODER 1" (according to MFT documentation)
So, all someone needs to do is to copy it a few times and adjust the cc for each encoder

PS: NO, the <bar /> element must NOT have the same name as the encoder.
As it's shown on my example above its name is LED_SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT but it could be anything.
What binds the controls together is actually this:
default="SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT"
 

Posted Tue 14 Dec 21 @ 5:05 pm
I agree with everything you mentioned Phantom. as always you are Amazing.
PhantomDeejay wrote :
As it's shown on my example above its name is LED_SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT but it could be anything.

and yes it could be anything,as you mention, and using the same name eliminates the need for an additional mapping, in this simple case.
as you mention in your much more detailed explanation.
PhantomDeejay wrote :
Also: For simple cases like "eq_high" you don't need to map both "ENCODER_X" and "LED_ENCODER_X" to the same action.
Because of the 'default="ENCODER_X"' attribute we used on the definition, the LED will use the same action as the "default" control.
You may need to map/remap the LED elements only if they don't work as expected on COMPLEX mappings (that the "update" of the ring may need different script from the one that controls the software)


and l learned from your explanation.... the use of default.. a much more elegant way to set it up, so the name does not need to be the same for this simple case. (which I was unaware of)

Thank you again Phantom.

PS will not be trying to help on this issue as a novice :)

And would be Awesome if someday, the MFT was on the supported Hardware list :)
since it is an amazingly flexible, substantial, controller, if one needs encoders and buttons for Stems or FX.
 

Posted Tue 14 Dec 21 @ 5:57 pm
locoDogPRO InfinityModeratorMember since 2013
I ran in to a similar [ish] problem with a similar [ish] device, faderfox EC4.
Might just be this device, I've been meaning to ask twister users

the bar worked fine in most cases , except when the button of the encoder was scripted to cause a jump in the bar reading. [slider is filter, bar is filter, button is "filter 0.5 ? filter 0.0 : filter 0.5" ]
Is this the case with the twister?

it seemed that the button/slider and bar are some how linked internally [maybe something in the design to update faster, might just be my device & not the twister] I found a fix in adding a 50ms wait then refreshing the bar element

button
deck right level 0 ? deck right level 1 & wait 50ms & refresh_controller "Faderfox EC4" "I01E" : deck right level 0 & wait 50ms & refresh_controller "Faderfox EC4" "I01E"
 

Posted Tue 14 Dec 21 @ 7:00 pm
PhantomDeejay wrote :
There are two different things here:
1) Reading the encoder.
2) Setting the ring of the encoder.

Thank you so much for taking the time to help me out. I really appreciate it. I think the key might be with the sendstatic attribute? Here is what I have been using...

<slider cc="0x10" name="Enc17" channel="0"  />
<slider cc="0x11" name="Enc18" channel="0" />
<slider cc="0x12" name="Enc19" channel="0" />
<slider cc="0x13" name="Enc20" channel="0" />
<slider cc="0x14" name="Enc21" channel="0" />
<slider cc="0x15" name="Enc22" channel="0" />
<slider cc="0x16" name="Enc23" channel="0" />
<slider cc="0x17" name="Enc24" channel="0" />
<slider cc="0x18" name="Enc25" channel="0" />
<slider cc="0x19" name="Enc26" channel="0" />
<slider cc="0x1A" name="Enc27" channel="0" />
<slider cc="0x1B" name="Enc28" channel="0" />
<slider cc="0x1C" name="Enc29" channel="0" />
<slider cc="0x1D" name="Enc30" channel="0" />
<slider cc="0x1E" name="Enc31" channel="0" />
<slider cc="0x1F" name="Enc32" channel="0" />

<button cc="0x10" name="Btn17" channel="1" inverted="0x00" />
<button cc="0x11" name="Btn18" channel="1" inverted="0x00" />
<button cc="0x12" name="Btn19" channel="1" inverted="0x00" />
<button cc="0x13" name="Btn20" channel="1" inverted="0x00" />
<button cc="0x14" name="Btn21" channel="1" inverted="0x00" />
<button cc="0x15" name="Btn22" channel="1" inverted="0x00" />
<button cc="0x16" name="Btn23" channel="1" inverted="0x00" />
<button cc="0x17" name="Btn24" channel="1" inverted="0x00" />
<button cc="0x18" name="Btn25" channel="1" inverted="0x00" />
<button cc="0x19" name="Btn26" channel="1" inverted="0x00" />
<button cc="0x1A" name="Btn27" channel="1" inverted="0x00" />
<button cc="0x1B" name="Btn28" channel="1" inverted="0x00" />
<button cc="0x1C" name="Btn29" channel="1" inverted="0x00" />
<button cc="0x1D" name="Btn30" channel="1" inverted="0x00" />
<button cc="0x1E" name="Btn31" channel="1" inverted="0x00" />
<button cc="0x1F" name="Btn32" channel="1" inverted="0x00" />

<led cc="0x10" name="Led17" default="Btn17" channel="1" />
<led cc="0x11" name="Led18" default="Btn18" channel="1" />
<led cc="0x12" name="Led19" default="Btn19" channel="1" />
<led cc="0x13" name="Led20" default="Btn20" channel="1" />
<led cc="0x14" name="Led21" default="Btn21" channel="1" />
<led cc="0x15" name="Led22" default="Btn22" channel="1" />
<led cc="0x16" name="Led23" default="Btn23" channel="1" />
<led cc="0x17" name="Led24" default="Btn24" channel="1" />
<led cc="0x18" name="Led25" default="Btn25" channel="1" />
<led cc="0x19" name="Led26" default="Btn26" channel="1" />
<led cc="0x1A" name="Led27" default="Btn27" channel="1" />
<led cc="0x1B" name="Led28" default="Btn28" channel="1" />
<led cc="0x1C" name="Led29" default="Btn29" channel="1" />
<led cc="0x1D" name="Led30" default="Btn30" channel="1" />
<led cc="0x1E" name="Led31" default="Btn31" channel="1" />
<led cc="0x1F" name="Led32" default="Btn32" channel="1" />
 

Posted Tue 14 Dec 21 @ 9:39 pm
locodog wrote :
I ran in to a similar [ish] problem with a similar [ish] device, faderfox EC4.
Might just be this device, I've been meaning to ask twister users

the bar worked fine in most cases , except when the button of the encoder was scripted to cause a jump in the bar reading. [slider is filter, bar is filter, button is "filter 0.5 ? filter 0.0 : filter 0.5" ]
Is this the case with the twister?

This is interesting. I was thinking about getting that exact device as well.. so i'm glad you are here.
I believe that the solution is changing the resolution mode of the fader or knob. Not sure if this is possible on the faderfox, but that is what I made sure to have set within the mft firmware software utility.
 

Posted Tue 14 Dec 21 @ 9:45 pm
PhantomDeejay wrote :
The example I gave above is all that's needed to get going.
It is actually tailored against "ENCODER 1" (according to MFT documentation)
So, all someone needs to do is to copy it a few times and adjust the cc for each encoder

PS: NO, the <bar /> element must NOT have the same name as the encoder.
As it's shown on my example above its name is LED_SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT but it could be anything.
What binds the controls together is actually this:
default="SAME-NAME-USED-FOR-FIRST-ENCODER-IN-SLIDER-ELEMENT"

Ah i see, I do not have bar variables set. It looks like I need to go through and create those.
 

Posted Tue 14 Dec 21 @ 9:46 pm
locodog wrote :
the bar worked fine in most cases , except when the button of the encoder was scripted to cause a jump in the bar reading. [slider is filter, bar is filter, button is "filter 0.5 ? filter 0.0 : filter 0.5" ]
Is this the case with the twister?

Did the test for you Locodog,

does NOT seem to be an issue with the MFT.

To test I sent an encoder to change fader level continuously, and
the button on the same encoder to jump to preset levels with

level 0.5 ? level 0.0 : level 0.5

and all worked expected. (the VDJ fader positions and ring illuminations always matched)

will explain in more detail. the VDJ fader position changes correctly, the ring illuminations change and reflect the position of the VDJ fader position, the channel audio volume changes correctly. but leaves a fantom slider position on the skin which may not engage the VDJ slider till it is picked up (with, controllerTakeoverMode = Pickup) if one is then turning the encoder to change level .. but actual audio level is always correct for the ring illumination.

if VDJ slider is moved with mouse, then pickup is immediate. diff then when moved with Button.

is it the fantom slider position that you were asking about locodog ? (was not clear what the wait state was correcting.)

--------------------------
UPDATE: the more I think about it I don't understand why there is that fantom position for the slider.. when the encoder is turned.. since the encoder knows the position (the ring illumination) and the software Slider picture is also in the the correct position for the channel volume, (and an encoder is not a pot that has to do pickup).

Can you explain that locodog?

Maybe another "property" needs to be added to an element in the definitions?

This is first time I have changed a slider position (or aware of it) with script that is also being controlled by the MFT. Though many times controlling sliders with DJ Controller or with mouse, and as I mentioned it does not create this fantom slider situation with the MFT which requires pickup.
---------------------------


and thank you locodog, for sharing the trick that may come in handy for some future needed work around on the MFT.
 

Posted Tue 14 Dec 21 @ 9:47 pm
IIDEEJAYII wrote :

and thank you locodog, for sharing the trick that may come in handy for some future needed work around on the MFT.

Right? The refresh controller trick does indeed work. Lol. I'm looking for a way of resetting all eqs and stems with one button, but it doesn't look like that has been implemented yet.
Thanks again everyone for all your help.
Once I modify the xml for the MFT I'll update here to let you know if the bar does indeed update live for what I want to do. You guys are awesome!
 

Posted Tue 14 Dec 21 @ 9:58 pm
IIDEEJAYII wrote :
UPDATE: the more I think about it I don't understand why there is that fantom position for the slider.. when the encoder is turned.. since the encoder knows the position (the ring illumination) and the software Slider picture is also in the the correct position for the channel volume, (and an encoder is not a pot that has to do pickup).

Can you explain that locodog?

Maybe another "property" needs to be added to an element in the definitions?

This is first time I have changed a slider position (or aware of it) with script that is also being controlled by the MFT. Though many times controlling sliders with DJ Controller or with mouse, and as I mentioned it does not create this fantom slider situation with the MFT which requires pickup.

ran out of time to edit, and wanted to make that clearer...

the more I think about it I don't understand why there is that fantom position for the slider.. when the encoder is turned AFTER THE SLIDER IS MOVED WITH SCRIPT.. since the encoder knows the position (the ring illumination) and the software "Slider picture" is also in the the correct position for the channel volume, (and an encoder is not a pot that has to do pickup, as on a DJ controller)

Again there is NO fantom slider effect when making continuous adjustments with a mouse or with the DJ Controller.

and is independent of the source of the script that is changing the slider position: the same encoder button or a custom button .. (seems when not continuous motion)

a mystery to me !

can create a video if that is not clear.
 

Posted Tue 14 Dec 21 @ 11:09 pm
Some remarks:
When defining a device it's not a good or wise practice to use the same name for different elements as there's no way on mapping level to distinguish them. The only exception to this rule is when defining the same control among different decks.
While giving the same name on both a button and it's led will work under a lot of cases, it won't work properly on a lot of others. Hence the general rule of NOT giving the same name, but instead binding them together with "default".
If you look at any factory default mapper of any supported device, chances are that you will find some LED_ entries mapped, while others not.
The non mapped entries are the ones that the led get's it's on/off status from it's button. However on certain cases you will notice that the LED_ element of a button has a different action than the button.
If both the button and the led had the same name it would be impossible to map them separately.
Also keep in mind that some actions don't return status that can be used to LED's (like let's say loop_half or loop_double actions)

Another point:
In the MFT example where a button is mapped as
level 0.5 ? level 0.0 : level 0.5
and an encoder is mapped as
level

What happens is this:
  1. You press the button.
    When you do that, the button sets a desired volume (let's say 50%) via script. Since the position of the hardware fader is still at a different position (let's say 25%) a ghost slider appears.
  2. Once the volume changes to 50% VirtualDJ sends out the change on the LED (<bar />) element.
    Now the LED also shows 25%
  3. Magic stuff SHOULD happen here (see below)

What should happen on step 3 is that the encoder should send a new message reporting it's new position since it has now been changed due to the LED (<bar />) update. This would make the "hardware" slider (now appearing as ghost) to move the same location as the software slider.
But that does not seem to be the case.
If the encoder was sending a new message after the change, then the ghost slider would move to the location of the normal slider and both sliders would link again.
However it seems to me that the encoder just stores it's new position in memory so that it knows what value to send on the "next" click. Hence the "ghost" slider remains there.
In terms of how VirtualDJ sees data, the button you pressed changed the volume, but the "hardware" slider controlling it never moved.
If my theory is correct (since I don't have the unit) then one click of the encoder backwards followed by one click forward should make the ghost disappear. The first click should make the ghost slider jump just before the correct placement for the sliders to link, and the second should make them match/link.

Now, you may ask why this doesn't occur when adjusting the volume slider via mouse:
I can't be 100% certain, but it seems to me that it has something to do with the firmware of the device.
Maybe the device sends out the "position" of the encoder when the step is small, but not when it changes drastically. From this point on it's just speculation. However, knowing the internals of the program and how mappers work, it's certainly not due to VirtualDJ not understanding what's going on.

PS1: We refer to the controls of MFT all the time as "encoders" when they are actually "endless knobs"
As I explained above, an encoder sends RELATIVE messages, while a slider/knob sends linear data from 0 to 127.
For VirtualDJ there's no distinction between the "endless encoders" used in MFT and let's say a linear volume fader found on any MIDI device. They are the same. And therefore VirtualDJ safely assumes that the slider is still on the same position it was before until it receives a message from it.
Also setting the value of it via LED_ doesn't mean anything to VirtualDJ. The <bar /> element is just a MIDI output with an action attached to it. It doesn't mean that it control the "position" of a knob/fader. In fact, on the 99,999% of cases it doesn't.
VirtualDJ also has a <fullencoder /> element for encoders that send linear data, but I don't think the MFT encoders fall into this case too. Because a fullencoder wraps around when it reaches the end of it's value range. In other words, fullencoders act more or less as "jogs". If you keep turning a full encoder always in clockwise direction, you should get values like 0,1,2,3... 125,126,127,0,1,2,3...
In the MFT case I think if you keep turning the encoder clockwise it maxes out at 127 value.

PS2: The "complexity" of the device and it's firmware is one of the reasons there's no official mapper for it (yet).
While for several units we can come up with an official mapper just by reading it's user manual, that's not the case with MFT, and we don't own one in order to test it and map it.
However, if anyone is willing to do one or two remote sessions with me, we can pretty much set it up and then support it officially. In such case just drop me a PM to make the necessary arrangements.

PS3/Edit:
I also forgot to mention that it is possible on definition level to instruct VirtualDJ to "hide"/"ignore" ghost sliders. That can be done by adding the ghost="no" attribute on the <slider /> element.
However that's not an advised practice unless there's no other way to make the control work properly.
 

Posted Wed 15 Dec 21 @ 12:30 am
user22334547 wrote :

Thank you so much for taking the time to help me out. I really appreciate it. I think the key might be with the sendstatic attribute?

No. The sendstatic attribute just instructs VirtualDJ to update the LED (<bar />) element upon starting, even if the value is zero.
This means that with this attribute set when VirtualDJ starts it will update all the "encoders" of MFT to reflect the default values of the software.
Without that attribute, the "encoders" most likely will keep the values they had before starting VirtualDJ.
 

Posted Wed 15 Dec 21 @ 12:39 am
Thank you for an amazing explanation.. simply Amazing !

PhantomDeejay wrote :
If the encoder was sending a new message after the change, then the ghost slider would move to the location of the normal slider and both sliders would link again.

Yes you are right, appears that the MFT does not send back.

PhantomDeejay wrote :
However it seems to me that the encoder just stores it's new position in memory so that it knows what value to send on the "next" click. Hence the "ghost" slider remains there.
In terms of how VirtualDJ sees data, the button you pressed changed the volume, but the "hardware" slider controlling it never moved.
If my theory is correct (since I don't have the unit) then one click of the encoder backwards followed by one click forward should make the ghost disappear. The first click should make the ghost slider jump just before the correct placement for the sliders to link, and the second should make them match/link.

Yes Correct, actually any movement of the encoder, removes the ghost, since it is now to sending VDJ the position, which it didn't do before.

PhantomDeejay wrote :
Now, you may ask why this doesn't occur when adjusting the volume slider via mouse:
I can't be 100% certain, but it seems to me that it has something to do with the firmware of the device.
Maybe the device sends out the "position" of the encoder when the step is small, but not when it changes drastically.

The mouse and script movement of the fader level, both create the ghost which immediately disappears with the slightest adjustment to encoder. (my bad I let another known, issue creep in and reported incorrectly earlier)


PhantomDeejay wrote :
In the MFT case I think if you keep turning the encoder clockwise it maxes out at 127 value.

Yes that is correct. maxes out at 127 or 0.

Again thank you .. Phantom for the definitive explanation.

Love VDJ ! !
 

Posted Wed 15 Dec 21 @ 7:32 pm
I tried:
<bar cc="0x10" deck="3" min="0x10" max="0x13" fill="no" name="LED_Enc17" channel="0" default="Enc17" />

and i have the following for that encoder
<slider cc="0x10" name="Enc17" channel="0"  />
<button cc="0x10" name="Btn17" channel="1" inverted="0x00" />
<led cc="0x10" name="Led17" default="Btn17" channel="1" />

but it definitly does not update the current stem value with that unfortunately.
Not sure what I am doing wrong. :/
 

Posted Fri 17 Dec 21 @ 3:49 am
locoDogPRO InfinityModeratorMember since 2013
<bar cc="0x10" deck="3" min="0x00" max="0x7F" fill="no" name="LED_Enc17" channel="0" default="Enc17" />


<slider cc="0x10" deck="3" name="Enc17" min="0x00" max="0x7F" zero="0x40" channel="0" />


I think that's what you want
 

Posted Fri 17 Dec 21 @ 4:09 am
ok I got the dots to update back to the detent when i press the button to reset the value... it sometimes messes up about 1/8 of the time and doesn't return though. Not sure why.
Now I have the issue of the bottom color led going off if i move the encoder from the detent.
I took out the min and max to get this working.
<bar cc="0x10" deck="3"  fill="no" name="bar_Led17" channel="0" default="Enc17" />
 

Posted Fri 17 Dec 21 @ 4:13 am
Your min and max values were wrong.
By removing them you eventually instruct VirtualDJ to use min="0x00" and max="0x7F" (or if you prefer in decimal, min="0" max="127")
Which are the correct values as they represent the full range your "encoder" works when sending data.

Now, depending on how the firmware of the device is designed to work, there's a chance that sending 0x00 on the bar turns off it's led completely.
In that case (only) you can use min="0x01"
So let's define all elements of encoder 1 at bank 1:

<slider cc="0x00" name="ENC_B1_01" channel="0" />
<bar cc="0x00" min="0x00" max="0x7F" sendstatic="true" name="LED_ENC_B1_01" default="ENC_B1_01" channel="0" />
<button cc="0x00" name="BTN_B1_01" channel="1" />
<led cc="0x00" name="LED_BTN_B1_01" default="BTN_B1_01" channel="1" />

Encoder 1 at bank 2 is

<slider cc="0x10" name="ENC_B2_01" channel="0" />
<bar cc="0x10" min="0x00" max="0x7F" sendstatic="true" name="LED_ENC_B2_01" default="ENC_B2_01" channel="0" />
<button cc="0x10" name="BTN_B2_01" channel="1" />
<led cc="0x10" name="LED_BTN_B2_01" default="BTN_B2_01" channel="1" />

At bank 3:

<slider cc="0x20" name="ENC_B3_01" channel="0" />
<bar cc="0x20" min="0x00" max="0x7F" sendstatic="true" name="LED_ENC_B3_01" default="ENC_B3_01" channel="0" />
<button cc="0x20" name="BTN_B3_01" channel="1" />
<led cc="0x20" name="LED_BTN_B3_01" default="BTN_B3_01" channel="1" />

e.t.c.
I have not included "deck" attributes on the definitions above, but that's easy to add.
However if you add decks then it's preferable to group the elements.
What I mean is that instead of having ENC_B1_01 to ENC_B1_16 for first bank, you should have only ENC_B1_01 to ENC_B1_04 defined 4 times for 4 different decks.
This simplifies the mapper A LOT.
So you will either use this:

<slider cc="0x00" name="ENC_B1_01" channel="0" />
<slider cc="0x01" name="ENC_B1_02" channel="0" />
<slider cc="0x02" name="ENC_B1_03" channel="0" />
<slider cc="0x03" name="ENC_B1_04" channel="0" />
<slider cc="0x04" name="ENC_B1_05" channel="0" />
<slider cc="0x05" name="ENC_B1_06" channel="0" />
<slider cc="0x06" name="ENC_B1_07" channel="0" />
<slider cc="0x07" name="ENC_B1_08" channel="0" />
<slider cc="0x08" name="ENC_B1_09" channel="0" />
<slider cc="0x09" name="ENC_B1_10" channel="0" />
<slider cc="0x0A" name="ENC_B1_11" channel="0" />
<slider cc="0x0B" name="ENC_B1_12" channel="0" />
<slider cc="0x0C" name="ENC_B1_13" channel="0" />
<slider cc="0x0D" name="ENC_B1_14" channel="0" />
<slider cc="0x0E" name="ENC_B1_15" channel="0" />
<slider cc="0x0F" name="ENC_B1_16" channel="0" />

Or this:

<slider cc="0x00" name="ENC_B1_01" deck="1" channel="0" />
<slider cc="0x01" name="ENC_B1_02" deck="1" channel="0" />
<slider cc="0x02" name="ENC_B1_03" deck="1" channel="0" />
<slider cc="0x03" name="ENC_B1_04" deck="1" channel="0" />
<slider cc="0x04" name="ENC_B1_01" deck="2" channel="0" />
<slider cc="0x05" name="ENC_B1_02" deck="2" channel="0" />
<slider cc="0x06" name="ENC_B1_03" deck="2" channel="0" />
<slider cc="0x07" name="ENC_B1_04" deck="2" channel="0" />
<slider cc="0x08" name="ENC_B1_01" deck="3" channel="0" />
<slider cc="0x09" name="ENC_B1_02" deck="3" channel="0" />
<slider cc="0x0A" name="ENC_B1_03" deck="3" channel="0" />
<slider cc="0x0B" name="ENC_B1_04" deck="3" channel="0" />
<slider cc="0x0C" name="ENC_B1_01" deck="4" channel="0" />
<slider cc="0x0D" name="ENC_B1_02" deck="4" channel="0" />
<slider cc="0x0E" name="ENC_B1_03" deck="4" channel="0" />
<slider cc="0x0F" name="ENC_B1_04" deck="4" channel="0" />

But NOT this:

<slider cc="0x00" name="ENC_B1_01" deck="1" channel="0" />
<slider cc="0x01" name="ENC_B1_02" deck="1" channel="0" />
<slider cc="0x02" name="ENC_B1_03" deck="1" channel="0" />
<slider cc="0x03" name="ENC_B1_04" deck="1" channel="0" />
<slider cc="0x04" name="ENC_B1_05" deck="2" channel="0" />
<slider cc="0x05" name="ENC_B1_06" deck="2" channel="0" />
<slider cc="0x06" name="ENC_B1_07" deck="2" channel="0" />
<slider cc="0x07" name="ENC_B1_08" deck="2" channel="0" />
<slider cc="0x08" name="ENC_B1_09" deck="3" channel="0" />
<slider cc="0x09" name="ENC_B1_10" deck="3" channel="0" />
<slider cc="0x0A" name="ENC_B1_11" deck="3" channel="0" />
<slider cc="0x0B" name="ENC_B1_12" deck="3" channel="0" />
<slider cc="0x0C" name="ENC_B1_13" deck="4" channel="0" />
<slider cc="0x0D" name="ENC_B1_14" deck="4" channel="0" />
<slider cc="0x0E" name="ENC_B1_15" deck="4" channel="0" />
<slider cc="0x0F" name="ENC_B1_16" deck="4" channel="0" />


Finally: When you don't understand what an attribute means/does it's better to not use it all. For instance there's not need to use inverted="0x00" on your buttons.
It would be needed ONLY if the buttons required it and the correct syntax would be inverted="true"
Same thing applies for your bar.
You used min="0x10" max="0x13" fill="no"
This meant that the encoder was limited by you at only three values (the range 0x10 to 0x13) as VirtualDJ was resetting (via the bar) it's values all the time.
Also the fill="no" is the default behavior. There's no need to use it, and it DOES NOT control the appearance of the ring of your encoders. Remember, VirtualDJ knows nothing about those rings.
Fill="no" is a way to instruct VirtualDJ what MIDI values to send (what format of MIDI values if you like)
The appearance of the rings on your encoders on the MFT can only be controlled by it's software utility (according to documentation)
 

Posted Fri 17 Dec 21 @ 10:50 am
[quote=PhantomDeejay][/quote]
Thank you so much. This is really helpful! I really appreciate your help. You rock! Yeah, I was just trying different things according to the http://www.virtualdj.com/wiki/ControllerDefinitionMIDIv8.html page to see what happens and also try to learn. It is difficult though when you don't have someone to go through it with you. Again, I so appreciate it.
 

Posted Tue 21 Dec 21 @ 8:08 pm
87%