This project is in progess, and not still finished

dnttalo.cluster029.hosting.ovh.net_pictures_p2toakf.jpg

I think the best / easier usage with force is to use prime2 or primeGo. Below i will explain / provide a template for Prime2.

Prime use QML from QT to do assignments and map functions. You can write your own javascript / qml code to suit your needs.

Qml below allow to map these functions :

Back , Forward, load Right & Left , Rotary button are mapped like this : (Load R/L is mapped below)

dnttalo.cluster029.hosting.ovh.net_pictures_backforward.jpg

### Code Header with Air Imports ###

import airAssignments 1.0
import ControlSurfaceModules 0.1
import InputAssignment 0.1
import OutputAssignment 0.1
import Planck 1.0
import QtQuick 2.12

### Then assignment begin for global parameters ###


MidiAssignment {
	objectName: 'PRIME 2 Controller Assignment'

	Utility {
		id: util
	}

	GlobalAssignmentConfig {
		id: globalConfig
		midiChannel: 0
	}

	GlobalAction {
		id: globalAction
	}

	Back {
		note: 67
		ledType: LedType.Simple
	}

	Forward {
		//note: 115
		shiftAction: Action.Quantize
		ledType: LedType.Simple
	}

	BrowseEncoder {
		pushNote: 111
		turnCC: 100
		ledType: LedType.Simple
	}


	View {
		note: 0
		holdAction: Action.ToggleControlCenter
		shiftAction: Action.SwitchMainViewLayout
		ledType: LedType.Simple
	}

	Shift {
		note: 49
		ledType: LedType.Simple
	}

	Media {
		mediaButtonsModel: ListModel {
			ListElement {
				name: 'Eject'
				shiftName: 'Source'
				note: 20
				hasLed: true
			}
		}
	}

	Mixer {
		cueMixCC: 12
		cueGainCC: 13
		crossfaderCC: 32
	}

	MicSettings {}

	Mics {
		mic1Note: 36
		mic2Note: 37
		mic1ShiftAction: Action.ToggleMicTalkover
	}

Then we create one repeater bloc for deck1 and further, another for deck2

DeckMidiChannel is 9 on the force when you press the sensitive pads in the middle.

dnttalo.cluster029.hosting.ovh.net_pictures_akaifpadchannel.jpg

that's why i use deckMidiChannel: 9 , which will be assigned to my whole repeater bloc section

### Repeater 1 for Deck Left ###

	Repeater {
		model: ListModel {
			ListElement {
				deckName: 'Left'
				deckMidiChannel: 9
				loadNote: 123
			}
		}

		Item {
			DeckAssignmentConfig {
				id: deckConfig
				name: model.deckName
				midiChannel: model.deckMidiChannel
			}

			DeckAction {
				id: deckAction
			}

			Bank {}

			Load {
				note: model.loadNote
				ledType: LedType.Simple
			}


			PerformanceModes {
				ledType: LedType.RGB
				modesModel: ListModel {
					ListElement {
						note: 78
						view: 'CUES'
					}
					ListElement {

						note: 79
						view: 'LOOPS'
						altView: 'AUTO'
					}
					ListElement {
						note: 80
						view: 'ROLL'
					}
					ListElement {				
					note: 81
					view: "SLICER"
					altView: "FIXED"
				}
									
				}
			}

Here In PerformanceModes section , we define where we want the function pad assignment. I've done it on note 78,79,80,81 for deck 1

By using LedType.RGB option, I suspect Engine send a sendcolor function through the Device Assignement file . However this property is not assignable to each functions.

dnttalo.cluster029.hosting.ovh.net_pictures_akf_funcktionpaddeck1.jpg

The we defined ActionPads , they are for the pads when you will press one of the pad upper :

  1. Press 78 you'll have CUES mode
  2. Press 79 you'll have LOOPS mode
  3. Press 80 you'll have AUTOLOOPS mode
  4. Press 81 you'll have SLICER mode
			ActionPads {
				firstPadNote: 70
				ledType: LedType.RGB
			}

As prime 2 has 8 pads, when putting 70, it will assign pads from 70 to 77 ( 70, 70+1 , 70+2 ,70+3, etc… to 70+7) (0 to 7 = 8 pads )

dnttalo.cluster029.hosting.ovh.net_pictures_akf_functionpads2_deck1.jpg

As an exemple, when you'll press the pad for the cue ( pad number 78 ) . it will send a Sysex message to the pad via sendcolor function, defined in the Device Assignment File. And then you'll have all the cue for this track

dnttalo.cluster029.hosting.ovh.net_pictures_akf_deck1_cuemapping.jpg

You can trigger you cue, by pushing the colored pad , create new on the no colored one or remove them by press shift of the AKF + your colored pad. Shift button has been mapped upper with Shift keyword ( see upper ) to note 49, which is the midi note that shift button send on AKF.

It will work the same for loops (press key 79 ) , quick auto loops (key 80) , and slicer (key 81 ) Below some pics of these functions.

Cues

dnttalo.cluster029.hosting.ovh.net_pictures_akf_cues.jpg

Loops

dnttalo.cluster029.hosting.ovh.net_pictures_akf_loops.jpg

** Slicer

dnttalo.cluster029.hosting.ovh.net_pictures_akf_slice1.jpg dnttalo.cluster029.hosting.ovh.net_pictures_akf_slice2.jpg

			Sync {
				syncNote: 83
				syncHoldAction: Action.KeySync
			}

			PlayCue {
				cueNote: 37
				cueShiftAction: Action.SetCuePoint
				playNote: 82
	
			}

			PitchBend {
				minusNote: 29
				plusNote: 30
			}

			JogWheel {
				touchNote: 33
				ccUpper: 0x37
				ccLower: 0x4D
				jogSensitivity: 1638.7 * 10.08
				hasTrackSearch: true
			}

			Vinyl {
				note: 35
				holdAction: Action.GridCueEdit
			}

			AutoLoop {
				pushNote: 116
				turnCC: 16
				loopInactiveShiftTurnAction: Action.BeatJump
				ledType: LedType.Simple
			}

			SpeedSlider {
				ccUpper: 0x1F
				ccLower: 0x4B
				invert: true
			}
			
		
		}
	}

Same thing for deck Right

 

### Repeater 2 for Deck Right ###

Repeater {
		model: ListModel {
			ListElement {
				deckName: 'Right'
				deckMidiChannel: 9
				loadNote: 124
			}
		}

		Item {
			DeckAssignmentConfig {
				id: deckConfig
				name: model.deckName
				midiChannel: model.deckMidiChannel
			}

			DeckAction {
				id: deckAction
			}

			Bank {}

			Load {
				note: model.loadNote
				ledType: LedType.Simple
			}

			PerformanceModes {
				ledType: LedType.RGB
				modesModel: ListModel {
					ListElement {
						note: 110
						view: 'CUES'
					}
					ListElement {
						note: 111
						view: 'LOOPS'
						altView: 'AUTO'
					}
					ListElement {
						note: 112
						view: 'ROLL'
					}
					ListElement {					
					note: 113
					view: "SLICER"
					altView: "FIXED"
				}
				}
			}

			ActionPads {
				firstPadNote: 102
				ledType: LedType.RGB
			}

			Sync {
				syncNote: 115
				syncHoldAction: Action.KeySync
			}

			PlayCue {
				cueNote: 9
				cueShiftAction: Action.SetCuePoint
				playNote: 114
			}

			PitchBend {
				minusNote: 29
				plusNote: 30
			}

			JogWheel {
				touchNote: 33
				ccUpper: 0x37
				ccLower: 0x4D
				jogSensitivity: 1638.7 * 10.08
				hasTrackSearch: true
			}

			Vinyl {
				note: 35
				holdAction: Action.GridCueEdit
			}

			AutoLoop {
				pushNote: 56
				turnCC: 23
				loopInactiveShiftTurnAction: Action.BeatJump
				ledType: LedType.Simple
			}

			SpeedSlider {
				ccUpper: 0x1F
				ccLower: 0x4B
				invert: true
			}
		}
	}

Code below allow to map functions on the pic below dnttalo.cluster029.hosting.ovh.net_pictures_prime2layout.jpg

Repeater {
		model: ListModel {
			ListElement {
				deckName: "Left"
				deckMidiChannel: 0
			}
			
			ListElement {
				deckName: "Right"
				deckMidiChannel: 0
			}
			
			
		}

		Item {
			id: deckmixer
			
// Internal properties for Deck 1 


			readonly property QObjProperty padsView1: Planck.getProperty("/Engine/Deck%1/Pads/View".arg(1))
			
			property string padsMode1: padsView1.translator.string
			
			readonly property bool padsModeIsAutoLoop1: padsMode1 === "AUTO"
			readonly property bool padsModeIsLoop1: padsMode1 === "LOOPS"
			readonly property bool padsModeIsLoopRoll1: padsMode1 === "ROLL"
			readonly property bool padsModeIsSlicerContinuous1: padsMode1 === "SLICER"
			readonly property bool padsModeIsSlicer1: padsModeIsSlicerContinuous1 || padsMode1 === "FIXED"
			
			readonly property bool loopEnabled1: Planck.getProperty("/Engine/Deck%1/Track/LoopEnableState".arg(1)).translator.state
			readonly property bool loopEditable1: Planck.getProperty("/Engine/Deck%1/Track/LoopEnableState".arg(1)).translator.editable
			

// Internal properties for Deck 2			
			
			
		readonly property QObjProperty padsView2: Planck.getProperty("/Engine/Deck%1/Pads/View".arg(2))
			
		property string padsMode2: padsView2.translator.string
			
		readonly property bool padsModeIsAutoLoop2: padsMode2 === "AUTO"
		readonly property bool padsModeIsLoop2: padsMode2 === "LOOPS"
		readonly property bool padsModeIsLoopRoll2: padsMode2 === "ROLL"
		readonly property bool padsModeIsSlicerContinuous2: padsMode2 === "SLICER"
		readonly property bool padsModeIsSlicer2: padsModeIsSlicerContinuous2 || padsMode2 === "FIXED"
			
		readonly property bool loopEnabled2: Planck.getProperty("/Engine/Deck%1/Track/LoopEnableState".arg(2)).translator.state
		readonly property bool loopEditable2: Planck.getProperty("/Engine/Deck%1/Track/LoopEnableState".arg(2)).translator.editable


			
// Sweep Filter for Deck 1 

ValueCCAssignment {
				objectName: "Dual Filter Cutoff Deck%1".arg(1)
				cc: 16
				channel: deckMidiChannel
				
						output: JogOutput {
							jogAcceleration: 1.5;
							jogSensitivity: 0.5;
							type: 0
							target: PropertyTarget { path: "/Engine/Mixer/Channel%1/SweepFx/Value".arg(1) }					
						}
				
			}



// Sweep Filter for deck 2 

ValueCCAssignment {
				objectName: "Dual Filter Cutoff Deck%1".arg(2)
				cc: 23
				channel: deckMidiChannel
								

						output: JogOutput {
							jogAcceleration: 1.5;
							jogSensitivity: 0.5;
							type: 0
							target: PropertyTarget { path: "/Engine/Mixer/Channel%1/SweepFx/Value".arg(2) }
						
							
						}
		
			}

Then we will map Parameters buttons, used when you are in slice or loop modes


//
//			PARAMETERS DECK RIGHT & LEFT 
//
			
					
			
			ValueNoteAssignment {
				objectName: "Parameter Left Deck%1".arg(1)
				note: 58
				channel: 0
				output: QtObject {
					readonly property QObjProperty pHalveLoop1: Planck.getProperty("/Engine/Deck%1/Track/HalveLoop".arg(1))
					readonly property QObjProperty pShiftLoopLeft1: Planck.getProperty("/Engine/Deck%1/Track/ShiftLoopLeft".arg(1))
					readonly property QObjProperty pHalve1: Planck.getProperty("/Engine/Deck%1/Track/Slicer/Halve".arg(1))

					function setValue(channel, value, assignmentEnabled) {
						console.log("SVVal:",value)
						console.log("SVChan:",assignmentEnabled)
						if(assignmentEnabled && value) {
							if(padsModeIsSlicer1) {
								pHalve1.translator.state = true
							}
							else if(loopEnabled1) {
								if(device.shift) {
									pShiftLoopLeft1.translator.state = true
								}
								else {
									pHalveLoop1.translator.state = true
								}
							}
						}
					}
				}
			}
		
		
			ValueNoteAssignment {
				objectName: "Parameter Right Deck%1".arg(1)
				note: 59
				channel: 0
				output: QtObject {
					readonly property QObjProperty pDoubleLoop1: Planck.getProperty("/Engine/Deck%1/Track/DoubleLoop".arg(1))
					readonly property QObjProperty pShiftLoopRight1: Planck.getProperty("/Engine/Deck%1/Track/ShiftLoopRight".arg(1))
					readonly property QObjProperty pDouble1: Planck.getProperty("/Engine/Deck%1/Track/Slicer/Double".arg(1))

					function setValue(channel, value, assignmentEnabled) {
						if(assignmentEnabled && value) {
							if(padsModeIsSlicer1) {
								pDouble1.translator.state = true
							}
							else if(loopEnabled) {
								if(device.shift) {
									pShiftLoopRight1.translator.state = true
								}
								else {
									pDoubleLoop1.translator.state = true
								}
							}
						}
					}
				}
			}
		
		
		
		
			ValueNoteAssignment {
				objectName: "Parameter Left Deck%1".arg(2)
				note: 62
				channel: 0
				output: QtObject {
					readonly property QObjProperty pHalveLoop2: Planck.getProperty("/Engine/Deck%1/Track/HalveLoop".arg(2))
					readonly property QObjProperty pShiftLoopLeft2: Planck.getProperty("/Engine/Deck%1/Track/ShiftLoopLeft".arg(2))
					readonly property QObjProperty pHalve2: Planck.getProperty("/Engine/Deck%1/Track/Slicer/Halve".arg(2))

					function setValue(channel, value, assignmentEnabled) {
						//console.log("SVVal:",value)
						//console.log("SVChan:",assignmentEnabled)
						//device.sendColorButton(1,59)
						if(assignmentEnabled && value) {
							if(padsModeIsSlicer2) {
								pHalve2.translator.state = true
							}
							else if(loopEnabled2) {
								if(device.shift) {
									pShiftLoopLeft2.translator.state = true
								}
								else {
									pHalveLoop2.translator.state = true
								}
							}
						}
					}
				}
		}
		
		
			ValueNoteAssignment {
				objectName: "Parameter Right Deck%1".arg(2)
				note: 63
				channel: 0
				output: QtObject {
					readonly property QObjProperty pDoubleLoop2: Planck.getProperty("/Engine/Deck%1/Track/DoubleLoop".arg(2))
					readonly property QObjProperty pShiftLoopRight2: Planck.getProperty("/Engine/Deck%1/Track/ShiftLoopRight".arg(2))
					readonly property QObjProperty pDouble2: Planck.getProperty("/Engine/Deck%1/Track/Slicer/Double".arg(2))

					function setValue(channel, value, assignmentEnabled) {
						if(assignmentEnabled && value) {
							if(padsModeIsSlicer2) {
								pDouble2.translator.state = true
							}
							else if(loopEnabled2) {
								if(device.shift) {
									pShiftLoopRight2.translator.state = true
								}
								else {
									pDoubleLoop2.translator.state = true
								}
							}
						}
					}
				}
			}
		
		
            /*
			ValueCCAssignment {
				objectName: "Volume Deck%1".arg(deckName)
				cc: 14
				normalizeValue: false
				channel: deckMidiChannel
				output: ValueOutput {
					useSoftTakeover: false
					target: PropertyTarget { path: "/Engine/Mixer/Channel%1/Volume/Level".arg(index + 1)}
				}
			}
            */

            ValueNoteAssignment {
				objectName: "Cue Deck%1".arg(deckName)
				note: 13
				channel: deckMidiChannel
				output: ActionOutput {
					target: PropertyTarget {
						path: "/Engine/Mixer/Channel%1/PFL".arg(index + 1)
					}
				}
			}

			ValueOutputAssignment {
				objectName: "Channnel Cue LED %1".arg(deckName)
				enabled: !device.isInitializing
				messageType: type.note
				midiIndex: 13
				channel: deckMidiChannel
				minimum: 1
				path: "/Engine/Mixer/Channel%1/PFL".arg(index + 1)
			}

			ValueNoteAssignment {
				objectName: "CrossfaderSendleft" + index
				note: 15
				channel: deckMidiChannel
				valueTransform: QtObject {
					function transformValue(in_val) {
						var leftVal = 0.0
						if (in_val === leftVal) {
							return 1.0
						}
						else {
							return 0.0
						}
					}
				}
				output: ActionOutput {
					behaviour: force.hold
					target: PropertyTarget { path: "/Engine/Mixer/Channel%1/Crossfader/SendLeft".arg(index + 1); }
				}
			}

			ValueNoteAssignment {
				objectName: "CrossfaderSendRight" + index
				note: 15
				channel: deckMidiChannel
				valueTransform: QtObject {
					function transformValue(in_val) {
						var rightVal = 0.0156 // A little bit less than 2/127 to make comparing easier
						if (in_val >= rightVal) {
							return 1.0
						}
						else {
							return 0.0
						}
					}
				}
				output: ActionOutput {
					behaviour: force.hold
					target: PropertyTarget { path: "/Engine/Mixer/Channel%1/Crossfader/SendRight".arg(index + 1); }
				}
			}
			

		}
	}




	Repeater {
		model: ListModel {

			ListElement {
				mixerChannelName: '2'
				mixerChannelMidiChannel: 0
			}
		}

		Item {
			objectName: 'Mixer Channel %1'.arg(model.mixerChannelName)

			MixerChannelAssignmentConfig {
				id: mixerChannelConfig
				name: model.mixerChannelName
				midiChannel: model.mixerChannelMidiChannel
			}

			MixerChannelCore {
				pflNote: 116
				trimCC: 117
				trebleCC:31 
				midCC: 6
				bassCC: 30
				faderCC: 230
			}

			//SweepFxKnob {
			//	cc: 23
			//}

			SweepFxSelect {
				channelNames: [model.mixerChannelName]
				buttonsModel: ListModel {
					ListElement {
						note: 58
						fxIndex: SweepEffect.DualFilter
					}
					ListElement {
						note: 590
						fxIndex: SweepEffect.Wash
					}
				}
			}
		}
	}



     ///////////////////////////////////////////////////////////////////////////
	// Effect Controls
	 
	 
	 Repeater {
			model: ListModel {

                ListElement {
					deckName: "Left"
					deckMidiChannel: 0
				}

                ListElement {
                    deckName: "Right"
                    deckMidiChannel: 1
                    }

			}
			
			Item {
            id: deckFx
			
				readonly property string activeDeckIndex: 
				
				Planck.getProperty("/GUI/Decks/Decks").translator.entries[index]
				onActiveDeckIndexChanged: {
				pGridEdit.translator.state = false
				pShowCueEdit.translator.state = false
				}

                readonly property bool cueLEDState1: Planck.getProperty("/Engine/Deck%1/Track/CueLEDState".arg(1)).translator.state

                readonly property bool cueLEDFlashing1: Planck.getProperty("/Engine/Deck%1/Track/CueLEDState".arg(1)).translator.flashing

                readonly property QObjProperty pTempoSyncedFlashState1: Planck.getProperty("/Engine/Deck%1/TempoSyncedFlashState".arg(1))
                readonly property bool tempoSyncedFlashState1: pTempoSyncedFlashState1.translator.state



                readonly property string syncMode1: Planck.getProperty("/Engine/Deck%1/SyncMode".arg(1)).translator.string

                readonly property string syncMode2: Planck.getProperty("/Engine/Deck%1/SyncMode".arg(2)).translator.string



            // Fx Activation Deck1
            ValueNoteAssignment {
				objectName: "FX%1 Active Button".arg(1)
				note: 93
                channel: deckMidiChannel
				enabled: !device.shift
				output: ActionOutput {
					target: PropertyTarget {
                        path: "/Engine/Mixer/Channel%1/DJFx/Active".arg(1)
						function setValue(deckMidiChannel)
						{
						console.log("chan",deckMidiChannel)					
						}					
					}					
				}
				}
				
            // Fx Selection Deck1
            ValueCCAssignment {
				objectName: "FX%1 Selection".arg(1)
				cc: 17
				channel: deckMidiChannel

				enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
				output: QtObject {
					readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(1))
					function setValue(channel, value, assignmentEnabled) {
						if(assignmentEnabled) {
							if(value > 0.5) { // turn counter clockwise, value normalized
								pSelectionIndex.translator.unnormalized = pSelectionIndex.translator.unnormalized - 1
							}
							else {
								pSelectionIndex.translator.unnormalized = pSelectionIndex.translator.unnormalized + 1
							}
						}
					}
				}
			}

            // Fx Selecting Deck1
            ValueCCAssignment {
				objectName: "FX%1 Selecting".arg(1)
				cc: 17
				channel: deckMidiChannel
				enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)
                        }
                    }
                }

            // FxAmount Deck1
            ValueCCAssignment {
				objectName: "FX%1 Amount".arg(1)
				cc: 18
				channel: deckMidiChannel
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Knob2Target".arg(1)).translator.string === "Amount"

                  output: JogOutput {

                      jogAcceleration: 1.5;
                        jogSensitivity: 0.5;
                        type: 0
                        target: PropertyTarget { path: "/Engine/Mixer/Channel%1/DJFx/Amount".arg(1) }
                        property bool debug:true

                        // You can comment below, i let it as an example. Its documented in Engine binary.
                        // Open Engine Binary with 7zip, extract .rodata , open with np++ and search for "MidiAssignment".

                        function setValue(channel, value, assignmentEnabled, timestamp) {

                            if(!assignmentEnabled) {
                                privateData.oldJogValue = -1.0
                                return;
                            }
                            //console.log("out",value)
                            var t = target.get(channel, value);

                            // result[0]: bool indicating whether the value needs decreasing
                            // result[1]: float amount by which to decrease / increase
                            var result = [false, 0.0];
                            switch(type)
                            {
                            case 0:
                            case 3:
                                calcValueTypeA(value, result);
                                break;
                            case 1:
                                calcValueTypeB(value, result);
                                break;
                            case 2:
                                calcValueTypeC(value, result);
                                break;
                            default:
                                console.warn("Incorrect output type.")
                                break;
                            }

                            if(!t || (t.editable !== undefined && !t.editable))
                                return;

                            if(invert === result[0])
                            {
                                t.incValue(result[1], rangeMax, rangeMin, roundRobin, false, timestamp);
                            }
                            else
                            {
                                t.decValue(result[1], rangeMin, rangeMax, roundRobin, false, timestamp);
                            }
                        }

                        function calcValueTypeA(value, result) {

                            var v = value * 127.0
                            //console.log("val:",v)
                            result[0] = v >= 64.0

                            if(result[0]) {
                                v = 128 - v
                            }

                            // Now v is in [0...63]
                            v /= 63.0;

                            result[1] = jogSensitivity * v;
                        }

                  }
				}

            // FxMix Deck1
            ValueCCAssignment {
				objectName: "FX%1 Mix".arg(1)
				cc: 19
				channel: deckMidiChannel								
						output: JogOutput {
							jogAcceleration: 1.5;
							jogSensitivity: 0.5;
							type: 0
							target: PropertyTarget { path: "/Engine/Mixer/Channel%1/DJFx/Mix".arg(1) }								
						}												
               }
			
            // Fx Rate Deck1 ( mapped to Inexistant CC)
            ValueCCAssignment {
                objectName: "FX%1 Rate".arg(1)
                cc: 1001
                channel: deckMidiChannel
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Knob2Target".arg(1)).translator.string === "Rate"
                    output: QtObject {
                        readonly property QObjProperty pTarget: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Rate".arg(1))
                        function setValue(channel, value, assignmentEnabled) {
                            if(assignmentEnabled) {
                                var counterClock = value > 0.5
                                var changeIndex = counterClock ? -1 : 1
                                pTarget.translator.index = pTarget.translator.index + changeIndex
                            }
                        }
                    }
               }
										

/////////////// DECK 2 ( RIGHT )
			
            // Fx Activation Deck2
			ValueNoteAssignment {
				objectName: "FX%1 Active Button".arg(2)
				note: 05
				channel: deckMidiChannel
				enabled: !device.shift								
                    output: ActionOutput {
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Active".arg(2)
                    }
				}				
			}
			
            // Fx Selection Deck2
			ValueCCAssignment {
				objectName: "FX%1 Selection".arg(2)
				cc: 20
				channel: deckMidiChannel
				enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(2))
                        function setValue(channel, value, assignmentEnabled) {
                            if(assignmentEnabled) {
                                if(value > 0.5) { // turn counter clockwise, value normalized
                                    pSelectionIndex.translator.unnormalized = pSelectionIndex.translator.unnormalized - 1
                                }
                                else {
                                    pSelectionIndex.translator.unnormalized = pSelectionIndex.translator.unnormalized + 1
                                }
                            }
                        }
                    }
			}

            // Fx Selecting Deck2
			ValueCCAssignment {
				objectName: "FX%1 Selecting".arg(2)
				cc: 20
				channel: deckMidiChannel
				enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)
                        }
				}
			}
			
            // Fx Rate Deck2 ( mapped to Inexistant CC)
            ValueCCAssignment {
                objectName: "FX%1 Rate".arg(2)
                cc: 1000
                channel: deckMidiChannel
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Knob2Target".arg(2)).translator.string === "Rate"
                    output: QtObject {
                        readonly property QObjProperty pTarget: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Rate".arg(2))
                        function setValue(channel, value, assignmentEnabled) {
                            if(assignmentEnabled) {
                                var counterClock = value > 0.5
                                var changeIndex = counterClock ? -1 : 1
                                pTarget.translator.index = pTarget.translator.index + changeIndex
                            }
                        }
                    }
            }
	
            // FxAmount Deck2
			ValueCCAssignment {
				objectName: "FX%1 Amount".arg(2)
				cc: 21
				channel: deckMidiChannel
				enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Knob2Target".arg(2)).translator.string === "Amount"
                    output: EndlessKnobOutput {
                        smallestIncrement: 0.01
                        biggestIncrement: 0.1
                        target: PropertyTarget { path: "/Engine/Mixer/Channel%1/DJFx/Amount".arg(2) }
                    }
			}		
				
            // FxMix Deck2
			ValueCCAssignment {
				objectName: "FX%1 Mix".arg(2)
				cc: 22
				channel: deckMidiChannel
                    output: ValueOutput {
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Mix".arg(2)
                        }
                    }
			}	

            // In test
            ValueNoteAssignment {
            objectName: "Cue-Split"
            channel: 0
            note: 59
                output: ActionOutput {
                    behaviour: force.hold
                    target: PropertyTarget { path: "/Engine/Mixer/Cue/CueMix/Split"; }
                }
            }

            // SyncLed Deck1
			OutputAssignment {
				objectName: "Sync LED Deck%1".arg(1)
				properties: { 'ledValue': '' }
				
				readonly property int ledValue: {
					if(syncMode1 === "TempoSync") {
						globalSyncMode === "Tempo" || tempoSyncedFlashState ? 127 : 0
					}
					else if(syncMode1 === "BeatOrBarSync") {
						127
					}
					else {
						1
					}
				}

				function send() {
					//device.sendSimpleColor(deckMidiChannel, 8, ledValue)
					device.sendColorSyncd1(ledValue,"Deck1Sync")
					//console.log("simpecolor",ledValue)
				}

				Component.onCompleted: send()
			}
			
            // SyncLed Deck2
			OutputAssignment {
				objectName: "Sync LED Deck%1".arg(2)
				properties: { 'ledValue': '' }
				
				readonly property int ledValue: {
					if(syncMode2 === "TempoSync") {
						globalSyncMode === "Tempo" || tempoSyncedFlashState ? 127 : 0
					}
					else if(syncMode2 === "BeatOrBarSync") {
						127
					}
					else {
						1
					}
				}

				function send() {
					//device.sendSimpleColor(deckMidiChannel, 8, ledValue)
					device.sendColorSyncd2(ledValue,"Deck2Sync")
					//console.log("simpecolor",ledValue)
				}

				Component.onCompleted: send()
			}
						
            // Cue Led Deck1
			OutputAssignment {
				objectName: "Cue LED Deck%1".arg(1)
				properties: { 'ledValue': '' }
				
				readonly property int ledValue: {
					if(cueLEDState1) {
						127
					}
					else if(cueLEDFlashing1) {
						tempoSyncedFlashState1 ? 127 : 0
					}
					else {
						1
					}
				}

				function send() {
					device.sendColorLedd1(ledValue,"led")
				}
				
				Component.onCompleted: send()
			}


//////////// FX ASSIGNMENTS TO RED PADS NOTE 54 to 57
//////////// Fx index goes from (0) to (12) in order below
//////////// Echo (0), Delayn Hall, PingPong, AutoGate, Flanger, LFO Filter, Phaser, Crush, Roll, RevRoll, Scratch, Reverb (12)

            // RED PAD 1
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(1)
                note: 54
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(1))
                        function setValue(channel, value, assignmentEnabled) {
                            if(value > 0) { // turn counter clockwise, value normalized
                                pSelectionIndex.translator.unnormalized = 3
                                //console.log("idx:",pSelectionIndex.translator.unnormalized )
                                // Send to device - look at device file
                                device.sendFxColorbutton(0)
                            }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(1)
                note: 54
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)
                        }
                    }
                }

            // RED PAD 2
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(1)
                note: 55
                channel: 9

                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(1))
                        readonly property QObjProperty pFx1Active: Planck.getProperty("/Engine/Mixer/Channel1/DJFx/Active")
                        function setValue(channel, value, assignmentEnabled) {

                            if(value > 0) { // turn counter clockwise, value normalized
                                pSelectionIndex.translator.unnormalized = 4
                                //console.log("idx:",pSelectionIndex.translator.unnormalized )
                                //console.log("pFx1Active:",pFx1Active.translator.state)
                                device.sendFxColorbutton(1)
                            }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(1)
                note: 55
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)
                        }
                    }
                }

            // RED PAD 3
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(1)
                note: 56
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(1))
                        function setValue(channel, value, assignmentEnabled) {
                                if(value > 0) { // turn counter clockwise, value normalized
                                    pSelectionIndex.translator.unnormalized = 6
                                    console.log("idx:",pSelectionIndex.translator.unnormalized )
                                    device.sendFxColorbutton(2)
                                }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(1)
                note: 56
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)
                        }
                    }
                }

            // RED PAD 4
            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(1)
                note: 57
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(1)
                note: 57
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(1)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(1))
                        function setValue(channel, value, assignmentEnabled) {
                                if(value > 0) { // turn counter clockwise, value normalized
                                    pSelectionIndex.translator.unnormalized = 8
                                    console.log("idx:",pSelectionIndex.translator.unnormalized )
                                    device.sendFxColorbutton(3)
                                }
                        }
                    }
                }

//////////// END FX ASSIGNMENTS TO RED PADS


//////////// FX ASSIGNMENTS TO GREEN PADS NOTE 58 to 61
//////////// Fx index goes from (0) to (12) in order below
//////////// Echo (0), Delayn Hall, PingPong, AutoGate, Flanger, LFO Filter, Phaser, Crush, Roll, RevRoll, Scratch, Reverb (12)

            // GREEN PAD 1
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(2)
                note: 58
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(2))
                        function setValue(channel, value, assignmentEnabled) {
                            if(value > 0) { // turn counter clockwise, value normalized
                                pSelectionIndex.translator.unnormalized = 3
                                //console.log("idx:",pSelectionIndex.translator.unnormalized )
                                // Send to device - look at device file
                                device.sendFxColorbuttonD2(4)
                            }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(2)
                note: 58
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)
                        }
                    }
                }

            // GREEN PAD 2
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(2)
                note: 59
                channel: 9

                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(2))
                        readonly property QObjProperty pFx1Active: Planck.getProperty("/Engine/Mixer/Channel1/DJFx/Active")
                        function setValue(channel, value, assignmentEnabled) {

                            if(value > 0) { // turn counter clockwise, value normalized
                                pSelectionIndex.translator.unnormalized = 4
                                //console.log("idx:",pSelectionIndex.translator.unnormalized )
                                //console.log("pFx1Active:",pFx1Active.translator.state)
                                device.sendFxColorbuttonD2(5)
                            }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(2)
                note: 59
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)
                        }
                    }
                }

            // GREEN PAD 3
            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(2)
                note: 60
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(2))
                        function setValue(channel, value, assignmentEnabled) {
                                if(value > 0) { // turn counter clockwise, value normalized
                                    pSelectionIndex.translator.unnormalized = 6
                                    console.log("idx:",pSelectionIndex.translator.unnormalized )
                                    device.sendFxColorbuttonD2(6)
                                }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(1)
                note: 60
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)
                        }
                    }
                }

            // GREEN PAD 4

            ValueNoteAssignment {
                objectName: "FX%1 Selection".arg(2)
                note: 61
                channel: 9
                enabled: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: QtObject {
                        readonly property QObjProperty pSelectionIndex: Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/PreselectIndex".arg(2))
                        function setValue(channel, value, assignmentEnabled) {
                                if(value > 0) { // turn counter clockwise, value normalized
                                    pSelectionIndex.translator.unnormalized = 8
                                    console.log("idx:",pSelectionIndex.translator.unnormalized )
                                    device.sendFxColorbuttonD2(7)
                                }
                        }
                    }
                }


            ValueNoteAssignment {
                objectName: "FX%1 Selecting".arg(2)
                note: 61
                channel: 9
                enabled: !Planck.getProperty("/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)).translator.state
                    output: ActionOutput {
                        behaviour: force.action
                        target: PropertyTarget {
                            path: "/Engine/Mixer/Channel%1/DJFx/Selecting".arg(2)
                        }
                    }
                }


//////////// END FX ASSIGNMENTS TO RED PADS



        } //Closing Item
    } // Closing Repeater

} // Closing assignment


Files for this project are available there :

Akai Prime2 Files