QML Modifications. On today's menu: Double-Tap-Hold-Release Button

Sûlherokhh
Sûlherokhh Member, Traktor Mapping Mod Posts: 1,525 mod
edited February 27 in Mapping Traktor
  • On today's menu: Double-Tap-Hold-Release button (LINK)
  • Past menu 2: Loops of any Size (LINK)
  • Past menu 1: Double-Tap buttons (see this post).

...

Double-Tap buttons

Inspired by Patch & dj_estrela, i decided to publish the basic code i used for all my double-tap modifications i've done. Hopefully you can implement it if you need something like this. The button distinguishes between a single tap (function call in the first timer) and a double tap (function call in the ButtonScriptAdapter) that interrupts the first timer before it has run out of time and made it's call.

ButtonScriptAdapter {
 name: "BUTTON"
 onPress: {
   if (holdButton_countdown.running) {
     tapButton_countdown.stop()
     holdButton_countdown.stop()
     // PLACE DOUBLE-TAP FUNCTION HERE
   }
   else holdButton_countdown.restart()
 }
 onRelease: {
   if (holdButton_countdown.running) tapButton_countdown.restart()
 }
}

Timer { id: holdButton_countdown; interval: 250
 onTriggered: {
   if (tapButton_countdown.running) {
     // PLACE SINGLE-TAP FUNCTION HERE
   }
 }
}

Timer { id: tapButton_countdown; interval: 250 }

Wire { from: "%surface%.controllerButton"; to: "BUTTON" }

🦋

P.S: onTriggered executes when the timer reaches ZERO and doesn't execute if it gets stopped prematurely.

Edit: adjusted intro and title for new menus.

Comments

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,525 mod
    edited May 2023

    It's possible to easily mod your D2, S5, S8 to extend Loop Sizes from 1/64th beat up to any size beats.


    If you are using Supreme Edition Mod by @Aleix Jiménez or my EDIT of the mod, open the file "\Resources64\qml\CSI\S8\S8LoopEncoder.qml" (for D2/S8) or "\Resources64\qml\CSI\S5\S5LoopEncoder.qml" (for S5)

    replace the line

    Wire { from: "%surface%.encoder"; to: "loop.autoloop"; enabled: !shift }
    

    with these lines:

    // Wire { from: "%surface%.encoder"; to: "loop.autoloop"; enabled: !shift }
      // Loop Size from /64 to any Size via MoveLoopOut Mod
    WiresGroup {
      enabled: !shift
        // Loop Set
      Wire { from: "%surface%.encoder.push"; to: HoldPropertyAdapter { path: "app.traktor.decks." + deckId + ".loop.set.auto" } }
        // LoopOut Adjust
      Wire { enabled: !loopActive.value; from: "%surface%.encoder.turn"; to: RelativePropertyAdapter { path: "app.traktor.decks." + deckId + ".loop.size"; step: 1; mode: RelativeMode.Stepped } }
      Wire { enabled: loopActive.value; from: "%surface%.encoder.turn"; to: RelativePropertyAdapter { path: "app.traktor.decks." + deckId + ".move_internal"; step: 1; mode: RelativeMode.Stepped } }
      Wire { enabled: loopActive.value; from: "%surface%.encoder.is_turned"; to: SetPropertyAdapter { path: "app.traktor.decks." + deckId + ".move.mode"; value: 3 } }
      Wire { enabled: loopActive.value; from: "%surface%.encoder.is_turned"; to: SetPropertyAdapter { path: "app.traktor.decks." + deckId + ".move.size"; value: 12 } }
    }
    

    Nothing changes before you have set a loop. Once a loop is active though, turning the LoopEncoder will halve/double the size of the loop without constraint.

    Be aware that the Loop Size Display of the software or hardware will not reflect any changes to the size of an active loop.


    EDIT: If you are using the native qml files, you have to open the file "\Resources64\qml\CSI\Common\Deck_S8Style.qml".

    Look for the line:

    Wire { from: "%surface%.encoder";      to: "decks.1.loop.autoloop";    enabled: !module.shift }
    

    and replace it with the lines:

    // Wire { from: "%surface%.encoder";      to: "decks.1.loop.autoloop";    enabled: !module.shift }
      // Loop Size from /64 to any Size via MoveLoopOut Mod
    WiresGroup {
      enabled: !module.shift
        // Loop Set
      Wire { from: "%surface%.encoder.push"; to: HoldPropertyAdapter { path: "app.traktor.decks.1.loop.set.auto" } }
        // LoopOut Adjust
      Wire { enabled: !deckALoopActive.value; from: "%surface%.encoder.turn"; to: RelativePropertyAdapter { path: "app.traktor.decks.1.loop.size"; step: 1; mode: RelativeMode.Stepped } }
      Wire { enabled: deckALoopActive.value; from: "%surface%.encoder.turn"; to: RelativePropertyAdapter { path: "app.traktor.decks.1.move_internal"; step: 1; mode: RelativeMode.Stepped } }
      Wire { enabled: deckALoopActive.value; from: "%surface%.encoder.is_turned"; to: SetPropertyAdapter { path: "app.traktor.decks.1.move.mode"; value: 3 } }
      Wire { enabled: deckALoopActive.value; from: "%surface%.encoder.is_turned"; to: SetPropertyAdapter { path: "app.traktor.decks.1.move.size"; value: 12 } }
    }
    
    

    This does it only for deck A. To also do it for decks B, C and D you have to replace the other 3 lines containing

    • "decks.2.loop.autoloop"
    • "decks.3.loop.autoloop"
    • "decks.4.loop.autoloop"

    and replacing them with the above code, but change the ".1." occurrences with ".2.", ".3." and ".4." and the "deckALoopActive.value" occurrences with "deckBLoopActive.value", "deckCLoopActive.value" and "deckDLoopActive.value".


    Enjoy. 🦋

  • Warren Postma
    Warren Postma Member Posts: 43 Member

    I had no idea you could mod scripts and improve Traktor.

    It shocked me (first day playing with it) that its looping capability is so limited.

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

    NI introduced this open qml format with the arrival of the S8. Since then a widening circle of unfazable mappers and coders have cobbled together some awesome Traktor mods for hardware, giving 'vintage' controllers a new lease on being awesome.

    Expanding the loop control capabilities was one of the first things i did using the controller manager only, as it already provides all the tools needed for that (only way to do it for MIDI-only controllers). But i really like the code route, since it doesn't have the artificially small mapping limits regarding variables and functions.

    It would be best if the controller manager assignment table would be expanded, to make it more appealing for users to customize their gear with quicker results and less guesswork. But it's only hardcore modders that keep making those requests to Traktor developers.

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,525 mod
    edited May 2023

    I have uploaded the modified stock-qml folder of 3.9 Beta 3 that includes just three files. They adjust the functions of the Loop Knob and the pop-up LoopDisplayCircle for the D2/S5/S8 controllers.

    If you set a loop (either with the AutoLoop function or with LoopIn and LoopOut commands), the LoopEncoder doubles/halves the size of the loop without changing the AutoLoop size or being constrained by it, and the PopUpDisplay in the centre shows the actual length (including a couple of fractional values close to length 1). This also works with odd loop sizes. The smaller TopLoopDisplay shows the AutoLoop size; should you exit the loop and immediately set an AutoLoop then this is the size it will be set to.

    The S4Mk3 only has a single loop size display. I'm still considering how to approach it.

    Enjoy. 🦋


    EDIT: I updated the download when i realized that sample rates don't play into loop sizes, only BPM and cue length in seconds do.

  • Sûlherokhh
    Sûlherokhh Member, Traktor Mapping Mod Posts: 1,525 mod
    edited May 2023

    Double-Tap-Hold-Release Button

    (Re: Double-Tap buttons)

    This is the revised basic code i use for Double-Tap buttons, which includes a third trigger, Hold-Release, for which you have to hold the button for a quarter-second and trigger a third optional function by releasing it --- using only one hand.

    property bool doubleTapButton: false
    


    ButtonScriptAdapter {
     name: "GenericButton"
     onPress: {
       if (holdButton_countdown.running) {
         holdButton_countdown.stop()
         // PLACE DOUBLE-TAP FUNCTION HERE
         doubleTapButton = true
       }
       else holdButton_countdown.restart()
     }
     onRelease: {
       if (holdButton_countdown.running) {
         tapButton_countdown.restart()
       }
       else if (!doubleTapButton) {
         // PLACE HOLD-RELEASE FUNCTION HERE
         tapButton_countdown.stop()
       }
       else {
         doubleTapButton = false
         tapButton_countdown.stop()
       }
     }
    }
    


    Timer { id: holdButton_countdown; interval: 250
     onTriggered: {
       if (tapButton_countdown.running) {
         // PLACE SINGLE-TAP FUNCTION HERE
       }
     }
    }
    


    Timer { id: tapButton_countdown; interval: 250 }
    


    Wire { from: "%surface%.controllerButton"; to: "GenericButton" }
    

    As explained elsewhere, i used this for my EDIT's SyncButton. I hope this bare-bones version helps you implement it for anything you like. Don't forget to adjust the names of the id's and variables to a specific button. I personally now use this kind of button all the time.

    Enjoy. 🦋

  • pARty_bOy
    pARty_bOy Member Posts: 61 Advisor
    edited August 2023

    Hi! could you please make a mod for the Kontrol Z2 mapping to clone Decks with double click/tap on load button, I think the Sync button with the Hold+release function with be nice to reset pitch/tempo. thank you

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

    Only the last two lines of NI controllers (S8/S5/D2 + S2MK3/S3/S4MK3) use qml mapping, so sorry no. You would need someone with Z2 try overmapping the load button with that function.

Back To Top