Possible to control one QML file from multiple controllers?

Options
kiki
kiki Member Posts: 9 Member
edited February 29 in Mapping Traktor

Context:

I own a Kontrol S8 with a dodgy Browser Encoder button and two CDJ350 connected to Traktor PRO. While I am able to modify the QML of Kontrol S8 to remap the loop button to act as the Browser button, I would prefer not to do so and retain all functionality of the loop encoder and control the browse functions through other means, it would also be more convenient to use the CDJs to do that.

I can use the two CDJ350s to browse through tracks (directly in Traktor, does not show up on the Kontrol S8 screens), but what I was thinking of is if it is possible to somehow map the encoders on CDJs (or any external midi device) to control the browser and functions displayed on the Kontrol S8 as if the Kontrol S8 encoder was used?

I am familiar with software development so reprogramming the Kontrol S8 QML file won't be an issue, I am just unsure whether you can even define another surface within the S8 QML file to also get and act upon events from other connected devices/controllers?

Thanks!

Comments

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,849 mod
    edited October 2023
    Options

    There are 12 global variables that can be addressed by any Traktor compatible controller: 4 knobs, 4 faders and 4 buttons (or maybe twice that, i am not sure at the moment).

    The point is that these can be read by the S8 qml code and you can wire their values directly to perform any of the S8 functions.

    All of them have values from 0.00 to 1.00 (or boolean in the case of the buttons), so you will need a bit of internal trickery to wrap them around to adapt them to the stepped encoder functions.

    Here is a link of a long thread doing this exactly the other way around to read the output of the S4MK3 jogwheels to send MIDI signals out of Traktor (to loopMIDI in this case) in collaboration with @Stevan. You should be able to extrapolate/reverse engineer:

    It's a long back and forth discussion interspersed with files and code snippets. You should find this interesting. Any questions, just ask away.

    Edit: Do the CDJ functions work with their own qml code? If so, it should be even easier.

  • kiki
    kiki Member Posts: 9 Member
    Options

    Thats is great info, and I think just what I needed! Will experiment with it and see what I can come up with. If someone is interested in something similar Ill be glad to share if i get anywhere with it! 🤓

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,849 mod
    Options
  • kiki
    kiki Member Posts: 9 Member
    Options

    I was experimenting a bit, but it seems like I am missing a step. I just want to get a proof of concept with the push action on the browser button on S8 to start with. What I imagined I could do is the following:

    1. Create a Global Midi IN mapping for Global -> MIDI -> Buttons -> 1, that has midi input set to a CDJs, and learns from its browser encoder being pushed (note learned succesfully).
    2. Wire Kontrol S8 QML code to the button in question, to trigger the push action

    How I imagined it to work is that CDJs button being pressed will trigger Traktor's global midi button 1 which could then be wired from S8 QML.

    What I tried for #2 is the following:

    > Wire { from: DirectPropertyAdapter { path: "app.traktor.midi.buttons.1" } to: "%surface%.browse.push" }

    Is this concept valid, or am I missing something (given that I can't get my S8 to budge 😂). I also tried replacing %surface% directly with s8.right.browse.push, and Toggle/Hold adapter etc. to no avail. Is this even a valid wiring scenario to directly call %surface%.browse.push, or should I be using something like a ButtonScriptAdapter and then use onPress to make changes to the variables manually?

    I am also not 100% sure how I could test if the global button 1 was actually responding to the CDJ being pressed, MIDI is definitely getting in though since the note can be learned.

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,849 mod
    Options

    I'll hunt for some code that will update the s8 browser variables directly from the MIDI button state.

    In the meanwhile, can you explain to me how the CDJ350 controls interact with Traktor (qml, mapping or what)? And which CDJ control element are you using for this? Are there native browsing/loading controls and what are they / what do they do exactly?

    I am curious as to how all this interacts.

  • kiki
    kiki Member Posts: 9 Member
    Options

    I’ve set up the CDJ as a midi controller and imported its .tsi mapping file, so when I connect it to traktor I can use it to play/cue, change pitch, scratch, etc. I can also use its encoder to browse through tracks(up/down) and push to load the track on the deck. This all happens inside Traktor by the way so it is not reflected in the screens of S8.

    What I would like to achieve is to have the browser button on the CDJ to act as the encoder on S8 and pop up the browser view on S8, so I guess that would be possible if the CDJ can set a global midi button as you proposed, and S8’s QML can react to it. I would prefer to have it just trigger surface.browser.push since then there would only be the need to wire the button, if that isnt possible I guess I would need to make a lot more modification to the QML code because the same encoder is also responsible for browsing through effects, etc. based on current state, which I would also want to control through the same CDJ button.

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,849 mod
    Options

    I never tried that. It would be really awesome, if you output to the S8 browse encoder. I never tried and will test if i can wire the loop encoder with the browse encoder on my D2 to test this.

    In addition there is also the matter of resolution (possible problem) and signal transfer/transform on the MIDIknob (functioning like all 0.00-1.00 knobs) vs the stepped browse encoder. Somehow i think we may have a problem using an EncoderScriptAdapter with a knob. But i haven't tested this either. In the discussion behind the link above i have implented an EncoderScriptAdapter to Adjust a MIDIknob's value upon turning an endless encoder (the jogwheel). But the task at hand may be a different matter altogether.

    The best thing would be the direct wiring as you described, so we should attempt that first.

  • kiki
    kiki Member Posts: 9 Member
    Options

    Regarding the encoder resolution etc. my initial thinking was to try using a button script adapter as well - I think the encoder on the CDJ sends a midi note for every step up on the encoder and a different one for every step down. My naive thinking is that if we get to the stage where we can map the two notes from the CDJ to trigger a script on the S8 we have the gates open to fiddle around with internal scripting to make it work.

    P.S. not sure if it helps but I also noticed that if I push the S8 browser button physically and navigate to the list of songs (on the S8 screen) I can scroll through tracks (inside S8 browser screen) using the CDJ encoder just by using the default CDJ mapping. I am guessing that works out of the box because the CDJ is mapped to Traktors scroll up/down and load which is transmitted to the S8 by default.

  • kiki
    kiki Member Posts: 9 Member
    Options

    Update: found this comment inside ErikMinekus' mod which explains why the CDJ browser list navigation works on S8 through default mapping:

    //  The Browser View is connected to traktors QBrowser from which it receives its data model. The navigation through the
    //  data is done by calling funcrtions invoked from QBrowser.
    


  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,849 mod
    Options

    For the first point, maybe there is a manual somewhere to be found.

    With the second you put the finger on it regarding your explanation.

  • kiki
    kiki Member Posts: 9 Member
    Options

    Update: I got the proof of concept working with the information you provided. It’s not exactly 100% as I wanted but I think it will do if I don’t find a better option.

    After some reverse engineering I was able to map an AppProperty’s onValueChanged to a global midi button, and pop up the browser view inside the S8’s QML code. The midi button is mapped to the CDJ so in essence now when I push the browse encoder on the CDJ, S8’s QML responds accordingly and opens up the browser view as I wanted.

    My original idea is to actually be able to include this as if I was wiring %surface%.browser.push to the screen actions or invoke them myself, so there would be less code to change - in the current approach I will also need to incorporate modifiers etc. which would work out of the box if I was able to emulate an actual push on the device. I still think it might be possible if I am able to reverse engineer the code that interacts with QML and does the wiring internally in Traktor but it might prove too time consuming to break out of QML to do this.

    So, proof of concept is working at least, thanks @Sûlherokhh!

Back To Top