1. IMPORTANT:
    We launched a new online community and this space is now closed. This community will be available as a read-only resources until further notice.
    JOIN US HERE
NOTICE:

Our Traktor Pro Public Beta is available again in our new online community. Join us if you want to try new features.

MORE INFO

D2/S5/S8 mod - move active loop by 1 beat

Discussion in 'KONTROL S5/ KONTROL S8' started by Nick Moon, Sep 11, 2018.

  1. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    This mod facilitates via SHIFT LOOP encoder a "1 beat move" alternative to replace the NI provided "loop size move" for active loops.

    It will also move a loop that is not active; the existing "track seek" function that is available when SHIFT LOOP encoder is used and loop is not active should not be missed as there are 2 other methods to achieve that (shift touchstrip and beatjump buttons). Basically I felt it was illogical placed there, and argue there's benefit of moving the loop markers for a non-active loop as well - I found a new pastime of chasing the playhead a beat at a time to drop a loop exactly where I wanted it.

    Thought I'd chuck this out there now rather than my next mod release, as I've seen a few posts asking about feasibility. Tested on D2, am confident will be no issues on S8, and I've eyeballed the S5 code and think it will work ok... Jike - covers one off your wishlist and hopefully you can extend to cover the related requirement you had :)

    Solution wise this was not an obvious mod to actually implement. The existing function appears to be a super function that does the 3 equivalent calls that traditionally have done with MIDI, but also did a bit more - I found I'd broken SHIFT PUSH LOOP encoder to make the loop active/inactive so had to replace that as well. EncoderScriptAdapter {} was the right tool, but is hardly used elsewhere so not many examples to learn from, and the onIncrement: and onDecrement: event handlers are not used anywhere else and therefore undocumented (as I've said before I've looked underneath the covers as much as I can). The more we learn the more we can develop.

    This week's announcements for Traktor Pro 3 and new hardware are obviously of pleasant surprise and much interest. Will there be an update to the screens for our controllers? Will we be blocked from developing mods by NI? I assume someone on the product side reads the forums and has seen what we've been up to... If they do block us from making their software useable, pissing off users who are enthusiasts will really help their mess, er messier. So I'll wait and see, but I'm predicting there won't be a major update to the QML files, and I suspect the S8 will be dropped soon having seen the S3 Mk3 marketing. I see in years to come the D2/S5/S8 will become viewed a bit like the DeLorean DMC-12. I'll definitely be looking at TP3 as soon as available, and whilst it looks like a cosmetic stop gap, its a major release, the potential for bugs and compatibility issues must be high...

    All changes to be made in /qml/CSI/Common/Settings/Deck_S8Style.qml (D2 & S8), or /qml/CSI/S5/S5Deck.qml (S5)

    Don't forget to backup first etc!

    Step 1 - insert the following code block before function initializeModule()
    Code:
      // Properties/function to facilitate via SHIFT LOOP encoder a
      // "1 beat move" alternative to replace the NI provided "loop size move"
      // Note this mod will also move a loop that is not active; the existing
      // track seek function that is available when SHIFT LOOP encoder is used and
      // loop is not active should not be missed at there are 2 other methods to
      // achieve that (shift touchstrip and beatjump buttons)
      AppProperty { id: deckAMoveMode; path: "app.traktor.decks.1.move.mode" }
      AppProperty { id: deckAMoveSize; path: "app.traktor.decks.1.move.size" }
      AppProperty { id: deckAMove; path: "app.traktor.decks.1.move" }
      AppProperty { id: deckBMoveMode; path: "app.traktor.decks.2.move.mode" }
      AppProperty { id: deckBMoveSize; path: "app.traktor.decks.2.move.size" }
      AppProperty { id: deckBMove; path: "app.traktor.decks.2.move" }
      AppProperty { id: deckCMoveMode; path: "app.traktor.decks.3.move.mode" }
      AppProperty { id: deckCMoveSize; path: "app.traktor.decks.3.move.size" }
      AppProperty { id: deckCMove; path: "app.traktor.decks.3.move" }
      AppProperty { id: deckDMoveMode; path: "app.traktor.decks.4.move.mode" }
      AppProperty { id: deckDMoveSize; path: "app.traktor.decks.4.move.size" }
      AppProperty { id: deckDMove; path: "app.traktor.decks.4.move" }
      //
      function customLoopMove(_deckId, _direction ) {
        if (_deckId == 1) {
          deckAMoveMode.value = 1;        // Loop
          deckAMoveSize.value = 6;        // 6 = 1 beat 
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 1;        // Loop
          deckBMoveSize.value = 6;        // 6 = 1 beat 
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 1;        // Loop
          deckCMoveSize.value = 6;        // 6 = 1 beat 
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 1;        // Loop
          deckDMoveSize.value = 6;        // 6 = 1 beat 
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    
      function initializeModule()
      {
        updateFocusDependentDeckTypes();
        updateDeckPadsMode(topDeckType, topDeckPadsMode);
        updateDeckPadsMode(bottomDeckType, bottomDeckPadsMode);
      }
    
    Step 2 - insert the following code block before line containing decks.1.loop.move and delete line containing decks.1.loop.move
    Code:
                Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(1, 1); } onDecrement: { customLoopMove(1, -1); } } enabled: module.shift }
                Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.1.loop.active"; } enabled: module.shift }
    
    Before:
    Code:
                Wire { from: "%surface%.encoder";       to: "decks.1.loop.autoloop";     enabled: !module.shift }
                Wire { from: "%surface%.encoder";       to: "decks.1.loop.move";         enabled:  module.shift }
                Wire { from: "decks.1.loop.active";     to: "%surface%.encoder.leds";                              }
                Wire { from: "%surface%.encoder.touch"; to: "DeckA_ShowLoopSizeTouchTimer.input"                 }
    
    After:
    Code:
                Wire { from: "%surface%.encoder";       to: "decks.1.loop.autoloop";     enabled: !module.shift }
                Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(1, 1); } onDecrement: { customLoopMove(1, -1); } } enabled: module.shift }
                Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.1.loop.active"; } enabled: module.shift }
                Wire { from: "decks.1.loop.active";     to: "%surface%.encoder.leds";                              }
                Wire { from: "%surface%.encoder.touch"; to: "DeckA_ShowLoopSizeTouchTimer.input"                 }
    
    Step 3 - repeat above process for line containing decks.3.loop.move, using the following replacement code:
    Code:
                Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(3, 1); } onDecrement: { customLoopMove(3, -1); } } enabled: module.shift }
                Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.3.loop.active"; } enabled: module.shift }
    
    Step 4 - repeat above process for line containing decks.2.loop.move, using the following replacement code:
    Code:
                Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(2, 1); } onDecrement: { customLoopMove(2, -1); } } enabled: module.shift }
                Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.2.loop.active"; } enabled: module.shift }          
    Step 5 - repeat above process for line containing decks.4.loop.move, using the following replacement code:
    Code:
                Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(4, 1); } onDecrement: { customLoopMove(4, -1); } } enabled: module.shift }
                Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.4.loop.active"; } enabled: module.shift }
    
     
    • Informative Informative x 1
  2. Jike

    Jike NI Product Owner

    Messages:
    103
    Huge work considering that there is no "handbook" to learn the secrets of NI's qml code !!

    I understand that a non-active loop is also moved... can't we add a conditional test like enabled: module.shift && deckALoopActive ?

    The track seek function was useful for me with the Kontrol X1 and there is no beatjump buttons on the S5... On the X1, the track seek function uses the browse encoder, not the loop encoder (That was only for a 1 beat move with an active loop).

    On the S5, shift+browse.turn is not implemented, maybe we can use it to add the 8 beats track seek function...

    I'll test your code on my S5 and give you feedback ASAP.

    Many thanks !
     
  3. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Ah... I now see the relevance of Shift Loop Encoder for track seek on the S5 - just looked at the manual and realize S5 doesn't have the LOOP mode for the 8 performance pads. Apologies!

    Here's what I think I'll attempt:
    1) S5 - re-factor the code so if loop is inactive it does what you wanted :) and if you can validate it works then other S5 users can have the benefit of your insight.
    2) D2/S8 - make the number of beats it moves or beatjumps a preference (including loop size) for both modes, and also a preference to allow shift to carry out the move inactive loop option instead of beatjump (for me if nothing else!). Include this in my next release. The core code will remain the same for the S5/D2/S8 if other users want to take it as is.
     
  4. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    I think this should be ok on the S5 - works ok on my D2. No changes to the Wire {} code required...
    Code:
      // Properties/function to facilitate via SHIFT LOOP encoder a 
      // "1 beat move" alternative to replace the NI provided "loop size move" 
      // for where loop is active. Where loop is not active a "8 beat jump" will 
      // replace the NI provided "loop size beatjump"
      // function includes details of the beat size values so can be changed easily
      AppProperty { id: deckALoopEnabled; path: "app.traktor.decks.1.loop.active" }
      AppProperty { id: deckAMoveMode; path: "app.traktor.decks.1.move.mode" }
      AppProperty { id: deckAMoveSize; path: "app.traktor.decks.1.move.size" }
      AppProperty { id: deckAMove; path: "app.traktor.decks.1.move" }
      AppProperty { id: deckBLoopEnabled; path: "app.traktor.decks.2.loop.active" }
      AppProperty { id: deckBMoveMode; path: "app.traktor.decks.2.move.mode" }
      AppProperty { id: deckBMoveSize; path: "app.traktor.decks.2.move.size" }
      AppProperty { id: deckBMove; path: "app.traktor.decks.2.move" }
      AppProperty { id: deckCLoopEnabled; path: "app.traktor.decks.3.loop.active" }
      AppProperty { id: deckCMoveMode; path: "app.traktor.decks.3.move.mode" }
      AppProperty { id: deckCMoveSize; path: "app.traktor.decks.3.move.size" }
      AppProperty { id: deckCMove; path: "app.traktor.decks.3.move" }
      AppProperty { id: deckDLoopEnabled; path: "app.traktor.decks.4.loop.active" } 
      AppProperty { id: deckDMoveMode; path: "app.traktor.decks.4.move.mode" }
      AppProperty { id: deckDMoveSize; path: "app.traktor.decks.4.move.size" }
      AppProperty { id: deckDMove; path: "app.traktor.decks.4.move" }
      //
      function customLoopMove(_deckId, _direction) {
        //
        // Mode values - 2[Beatjump] 1[Loop] 
        // Size values - 0[ultrafine] 1[1/32 beat] 2[1/16 beat] 3[1/8 beat] 4[1/4 beat] 5[1/2 beat] 6[1 beat] 
        //               7[2 beats] 8[4 beats] 9[8 beats] 10[16 beats] 11[32 beats] 12[loop size] 
        //
        if (_deckId == 1) {
          deckAMoveMode.value = (deckALoopEnabled.value ? 1 : 0);   // 1 for loop move; 0 for beatjump
          deckAMoveSize.value = (deckALoopEnabled.value ? 6 : 9);   // default values of 1 beat for loopmove; 8 beats for beatjump
          deckAMove.value = _direction;                             // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = (deckBLoopEnabled.value ? 1 : 0);   // 1 for loop move; 0 for beatjump
          deckBMoveSize.value = (deckBLoopEnabled.value ? 6 : 9);   // default values of 1 beat for loopmove; 8 beats for beatjump
          deckBMove.value = _direction;                             // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = (deckCLoopEnabled.value ? 1 : 0);   // 1 for loop move; 0 for beatjump
          deckCMoveSize.value = (deckCLoopEnabled.value ? 6 : 9);   // default values of 1 beat for loopmove; 8 beats for beatjump
          deckCMove.value = _direction;                             // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = (deckDLoopEnabled.value ? 1 : 0);   // 1 for loop move; 0 for beatjump
          deckDMoveSize.value = (deckDLoopEnabled.value ? 6 : 9);   // default values of 1 beat for loopmove; 8 beats for beatjump
          deckDMove.value = _direction;                             // -1 = back +1 = forward
        }
      }
    
     
    • Like Like x 1
  5. Jike

    Jike NI Product Owner

    Messages:
    103
    Ok, i'll try your code this afternoon and tell you if it works on my S5.

    But i think we can keep your first code for the loop encoder and just add a "Shift+Browse Encoder" for track seek just to avoid the loop encoder to became multi-multi-purpose encoder.
     
  6. Jike

    Jike NI Product Owner

    Messages:
    103
    Late at work this morning because... i've tested the new code ;)

    Works fine on my S5 (The one for a 1 beat loop move - 8 beat seek when loop is inactive).
     
  7. Jike

    Jike NI Product Owner

    Messages:
    103
    Take a look at this :

    Code:
      // (NickMoon's mod) Properties/function to facilitate via SHIFT LOOP encoder a
      // "1 beat move" alternative to replace the NI provided "loop size move"
      // Note this mod will also move a loop that is not active; the existing
      // track seek function that is available when SHIFT LOOP encoder is used and
      // loop is not active should not be missed at there are 2 other methods to
      // achieve that (shift touchstrip and beatjump buttons).
      // (Jike's mod) Custom 8 beats TrackSeek for the Browse encoder.
    
      AppProperty { id: deckAMoveMode; path: "app.traktor.decks.1.move.mode" }
      AppProperty { id: deckAMoveSize; path: "app.traktor.decks.1.move.size" }
      AppProperty { id: deckAMove; path: "app.traktor.decks.1.move" }
    
      AppProperty { id: deckBMoveMode; path: "app.traktor.decks.2.move.mode" }
      AppProperty { id: deckBMoveSize; path: "app.traktor.decks.2.move.size" }
      AppProperty { id: deckBMove; path: "app.traktor.decks.2.move" }
    
      AppProperty { id: deckCMoveMode; path: "app.traktor.decks.3.move.mode" }
      AppProperty { id: deckCMoveSize; path: "app.traktor.decks.3.move.size" }
      AppProperty { id: deckCMove; path: "app.traktor.decks.3.move" }
    
      AppProperty { id: deckDMoveMode; path: "app.traktor.decks.4.move.mode" }
      AppProperty { id: deckDMoveSize; path: "app.traktor.decks.4.move.size" }
      AppProperty { id: deckDMove; path: "app.traktor.decks.4.move" }
    
      function customLoopMove(_deckId, _direction ) {
        if (_deckId == 1) {
          deckAMoveMode.value = 1;        // Loop
          deckAMoveSize.value = 6;        // 6 = 1 beat
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 1;        // Loop
          deckBMoveSize.value = 6;        // 6 = 1 beat
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 1;        // Loop
          deckCMoveSize.value = 6;        // 6 = 1 beat
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 1;        // Loop
          deckDMoveSize.value = 6;        // 6 = 1 beat
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    
      function customTrackSeek (_deckId, _direction) {
        if (_deckId == 1) {
          deckAMoveMode.value = 0;        // 0 for beatjump
          deckAMoveSize.value = 9;        // 8 beats for beatjump
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 0;        // 0 for beatjump
          deckBMoveSize.value = 9;        // 8 beats for beatjump
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 0;        // 0 for beatjump
          deckCMoveSize.value = 9;        // 8 beats for beatjump
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 0;        // 0 for beatjump
          deckDMoveSize.value = 9;        // 8 beats for beatjump
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    
      //----------------------------------------------------------------------------------
    
    Not yet tested (Not at home...) but i guess you can see what i mean : Keeping the loop encoder for loop stuff and the browse encoder for browsing/seeking.

    I've add a separate function to avoid mistakes.
     
    Last edited: Sep 12, 2018
    • Like Like x 1
  8. Jike

    Jike NI Product Owner

    Messages:
    103
    Ok, all working fine.

    Summary : LoopEncoder to move loops 1 beat by 1 beat and Browse encoder to 8 beat Track Seek.

    Co-working Nick Moon (90%) and I (10%).

    All changes to be made in /qml/CSI/Common/Settings/Deck_S8Style.qml (D2 & S8), or /qml/CSI/S5/S5Deck.qml (S5)

    1. Just before :

    Code:
    function initializeModule()
      {
        updateFocusDependentDeckTypes();
        updateDeckPadsMode(topDeckType, topDeckPadsMode);
        updateDeckPadsMode(bottomDeckType, bottomDeckPadsMode);
      }
    add :

    Code:
      // ----------------------------------------------------------------------------
    
      // (NickMoon's mod) Properties/function to facilitate via SHIFT LOOP encoder a
      // "1 beat move" alternative to replace the NI provided "loop size move"
      // Note this mod will also move a loop that is not active; the existing
      // track seek function that is available when SHIFT LOOP encoder is used and
      // loop is not active should not be missed at there are 2 other methods to
      // achieve that (shift touchstrip and beatjump buttons).
      // (Jike's mod) Custom 8 beats TrackSeek for the Browse encoder.
    
      AppProperty { id: deckAMoveMode; path: "app.traktor.decks.1.move.mode" }
      AppProperty { id: deckAMoveSize; path: "app.traktor.decks.1.move.size" }
      AppProperty { id: deckAMove; path: "app.traktor.decks.1.move" }
    
      AppProperty { id: deckBMoveMode; path: "app.traktor.decks.2.move.mode" }
      AppProperty { id: deckBMoveSize; path: "app.traktor.decks.2.move.size" }
      AppProperty { id: deckBMove; path: "app.traktor.decks.2.move" }
    
      AppProperty { id: deckCMoveMode; path: "app.traktor.decks.3.move.mode" }
      AppProperty { id: deckCMoveSize; path: "app.traktor.decks.3.move.size" }
      AppProperty { id: deckCMove; path: "app.traktor.decks.3.move" }
    
      AppProperty { id: deckDMoveMode; path: "app.traktor.decks.4.move.mode" }
      AppProperty { id: deckDMoveSize; path: "app.traktor.decks.4.move.size" }
      AppProperty { id: deckDMove; path: "app.traktor.decks.4.move" }
    
      function customLoopMove(_deckId, _direction ) {
        if (_deckId == 1) {
          deckAMoveMode.value = 1;        // Loop
          deckAMoveSize.value = 6;        // 6 = 1 beat
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 1;        // Loop
          deckBMoveSize.value = 6;        // 6 = 1 beat
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 1;        // Loop
          deckCMoveSize.value = 6;        // 6 = 1 beat
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 1;        // Loop
          deckDMoveSize.value = 6;        // 6 = 1 beat
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    
      function customTrackSeek (_deckId, _direction) {
        if (_deckId == 1) {
          deckAMoveMode.value = 0;        // 0 for beatjump
          deckAMoveSize.value = 9;        // 8 beats for beatjump
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 0;        // 0 for beatjump
          deckBMoveSize.value = 9;        // 8 beats for beatjump
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 0;        // 0 for beatjump
          deckCMoveSize.value = 9;        // 8 beats for beatjump
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 0;        // 0 for beatjump
          deckDMoveSize.value = 9;        // 8 beats for beatjump
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    
      // ----------------------------------------------------------------------------
    2. In the // LOOP ENCODER section, replace for each deck, the line :
    Code:
    Wire { from: "%surface%.encoder";       to: "decks.1.loop.move";         enabled:  module.shift }
    just under :
    Code:
    // Loop and Freeze modes
            WiresGroup
            {
              enabled: hasLoopMode(deckAType)
    
              WiresGroup
              {
                enabled: encoderMode.value == encoderLoopMode
    by 2 lines :
    Code:
    Wire { from: "%surface%.encoder.turn"; to: EncoderScriptAdapter { onIncrement: { customLoopMove(1, 1); } onDecrement: { customLoopMove(1, -1); } } enabled: module.shift }
    Wire { from: "%surface%.encoder.push"; to: TogglePropertyAdapter { path: "app.traktor.decks.1.loop.active"; } enabled: module.shift }
    Dont forget to change the deck number in "customLoopMove(1," and in "app.traktor.decks.1.loop.active" (1 for A, 2 for B, 3 for C and 4 for D) for each deck.

    3. In the TRANSPORT SECTION, add for each deck this new group :
    Code:
    WiresGroup // customTrackSeek
        {
          enabled: module.shift && !(isInEditMode || isInBrowser)
       
          Wire { from: "%surface%.browse.turn"; to: EncoderScriptAdapter { onIncrement: { customTrackSeek(1, 1); } onDecrement: { customTrackSeek(1, -1); } } }
        }
    just after the second WiresGroup, the one starting with :
    Code:
    WiresGroup
        {
          enabled: module.shift
    Dont forget to change the deck number in "customTrackSeek(1," (1 for A, 2 for B, 3 for C and 4 for D) for each deck.
     
    Last edited: Sep 12, 2018
  9. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Nice! Your take on using the Browse Encoder on the S5 for track seek is logical due to S5 layout; I'm still thinking through whether to leave things as is on my D2/S8 version, apart from adding in preferences, which who knows, may end up compassing seek function via Shift Browse. My thoughts are on the D2/S8 longer distance to stretch, and whether or not Shift Browse may be destined for something else :)
     
  10. Jike

    Jike NI Product Owner

    Messages:
    103
    Thank you :)

    And i've made another thing : using the two performance buttons (< and >) to move one beat, useful to re-sync two tracks if you miss your starting point... i often do that lol

    1. Add in the first block of code :
    Code:
    function customOneBeatBeatjump (_deckId, _direction) {
        if (_deckId == 1) {
          deckAMoveMode.value = 0;        // 0 for beatjump
          deckAMoveSize.value = 6;        // 1 beat for beatjump
          deckAMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 2) {
          deckBMoveMode.value = 0;        // 0 for beatjump
          deckBMoveSize.value = 6;        // 1 beat for beatjump
          deckBMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 3) {
          deckCMoveMode.value = 0;        // 0 for beatjump
          deckCMoveSize.value = 6;        // 1 beat for beatjump
          deckCMove.value = _direction;   // -1 = back +1 = forward
        }
        if (_deckId == 4) {
          deckDMoveMode.value = 0;        // 0 for beatjump
          deckDMoveSize.value = 6;        // 1 beat for beatjump
          deckDMove.value = _direction;   // -1 = back +1 = forward
        }
      }
    2. In the Zoom / Sample page / StemDeckStyle section, for each deck just after :
    Code:
    // Deck A
        WiresGroup
        {
          enabled: focusedDeckId == 1
    add :
    Code:
    WiresGroup
          {
            enabled: hasWaveform(deckDType) && !module.shift
            Wire { from: "%surface%.display.buttons.8"; to: ButtonScriptAdapter { onPress : customOneBeatBeatjump (1, 1);} }
            Wire { from: "%surface%.display.buttons.4"; to: ButtonScriptAdapter { onPress : customOneBeatBeatjump (1, -1);} }
          }
    Dont forget to change the deck number in "customOneBeatBeatjump(1," (1 for A, 2 for B, 3 for C and 4 for D) for each deck.
     
  11. Jike

    Jike NI Product Owner

    Messages:
    103
    Wow, my S5 is now more usable than a few weeks ago !

    In this post my S5Deck.qml file (S5Deck - Mod by Nick Moon and Jike.zip) with :

    - Flux button to activate/deactivate Loop Mode (Me),
    - Shift+Flux to activate/deactivate Flux Mode (Me and Nick Moon mod),
    - Shift+Loop encoder turn to move an active loop one beat by one beat (Nick Moon mod),
    - Shift+Browse encoder turn for an 8 beats Track Seek function (Me and Nick Moon mod),
    - Performance mode buttons ([<] and [>] under the displays) to move 1 beat (Me and Nick Moon mod).

    This first S5Deck.qml file may contain others stuffs because i'm also using the kokernuts mod.

    The second S5Deck.qml file (S5Deck - original + mod NM Jike.zip) is based on an original S5deck.qml with only
    the 5 mapping mods above.

    If you don't use any mod, you must try this second one.

    Don't forget to backup your actual S5Deck.qml file before testing the one in this post. Just in case...
     

    Attached Files:

    Last edited: Sep 15, 2018
    • Like Like x 1
  12. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Fantastic work, as you said great co-working. You've breathed some more life into the S5 that I'm sure many will appreciate by addressing some basic usability issues. I'll go back to my other mod investigations, some of which are a bit ambitious, but that's part of the fun...
     
  13. skymakai

    skymakai Member

    Messages:
    45
    Thanks, guys! It seems that all of the buttons are remappable? Do you have a mod to map the Key Lock function to a Shift+Button combo?
     
  14. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Most buttons can be remapped/made shiftable. Deciding which one and ensuring it would not impact other functions is the first step. Any thoughts on which button? And is this for S5 or D2/S8?
     
    • Like Like x 1
  15. skymakai

    skymakai Member

    Messages:
    45
    I'm currently using an S5 and considering getting a used S8 from some one nearby.

    As for which button, I think one of the arrow buttons next to the screens, that isn't otherwise used unless you're in a Grid/Key/Tempo shift mode would be good. Having to first press one of those arrows, then press the Load wheel below the screen in order to turn Key Lock on/off, is one more step than I'd like it to be. I use Key Lock for nearly every transition.
     
  16. Jike

    Jike NI Product Owner

    Messages:
    103
    Thank's too for your job that inspired me !! I'll keep an eye on your job of course, your screen mod is interresting.

    I think, one day, why not writing a Wiki with all what we learned about the functions, methods... and other stuff ?

    If QML programing is the new mapping standard (I hope not !!), it'll be very usefull.
     
  17. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Having looked at Qt/QML in quite a bit of depth now, including its roots and applications, I'm very impressed with its overall capabilities as a platform for user interfaces. But for non developers to pick up something in-between would be nice, but probably prohibitively too expensive to develop. And looking at the new hardware lineup, I suspect we won't see a new D2/S5/S8, or if we do will be a while and a stand alone unit, and maybe they'll deliver a decent set of screens. I'm predicting the mini screens on the new S4 will use Qt/QML for their functionality - if not then even less reason for NI to retain that development skillset and technology for other products in the Traktor product line.

    I think a full Wiki would be too much effort for the return anyone would get. I may publish the info I've eluded with the hope others add to it, but not until we see where NI are going with the hardware and ongoing ability for us to make mods. We'll have some idea in a couple of weeks time...
     
  18. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Ok, well on the S8 the arrow buttons are used extensively so you wouldn't want to remap them, but Shift and an arrow button may be a solution that is then usable on the S8 as well.

    My thoughts were Shift Filter on/off which would cover the S5 & S8 and giving instant access to Key on/off for all 4 decks, and then maybe Shift Filter knob to actually transition the Key (due to inaccessible code the popup would not be possible, unless a new one could be written from scratch). However, I've done some initial tests and not working as I'd expect - probably due to the mixer behaving slightly differently.
     
  19. Jike

    Jike NI Product Owner

    Messages:
    103
    I agree with you, too much efforts. Wait and see till the 25's of September...

    D2 and S5 are discontinued : https://djtechtools.com/2018/04/24/a-state-of-traktor-new-hardware-and-software-coming-in-2018/
     
  20. Nick Moon

    Nick Moon NI Product Owner

    Messages:
    162
    Hey Jike - I've managed to get the DECK button working as a second SHIFT button in the main module, so as well as SHIFT+Loop Encoder there's the possibility of additional options around loops and beat jumps...

    So you could use DECK+Loop Encoder for beat jumps and then SHIFT+Loop Encoder works whether loop is active or not. Having seen the location of the DECK button on the S5 could be quite handy... Also I don't know whether you use the popular mod so Browser Encoder is used to zoom the waveform in/out? Anyway, very easy to make that work also when doing SHIFT+Loop Encoder (or DECK+Loop Encoder) which has its uses when beat jumping :) Or could be used to adjust the beat jump size?!

    Currently have implemented DECK+ as secondary shift on D2 which is harder than S8/S5 as the DECK button is already multi-functional. Looking at the S8 & S5 code, the changes would be almost if not identical. Let me know if you are interested in what is needed :)