-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PakettiKeyBindings.lua
1443 lines (1287 loc) · 54 KB
/
PakettiKeyBindings.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
-- Function to extract and print MIDI mappings from required files
function extract_midi_mappings()
-- Define a list of required Lua files (replace with your actual files)
local required_files = {
"Coluga/PakettiColuga.lua",
"Paketti0G01_Loader.lua",
"PakettiAudioProcessing.lua",
"PakettiAutomation.lua",
"PakettiControls.lua",
"PakettiDeviceChains.lua",
"PakettiDynamicViews.lua",
"PakettieSpeak.lua",
"PakettiExperimental_Verify.lua",
"PakettiGater.lua",
"PakettiImpulseTracker.lua",
"PakettiInstrumentBox.lua",
"PakettiLoadDevices.lua",
"PakettiLoaders.lua",
"PakettiLoadPlugins.lua",
"PakettiMainMenuEntries.lua",
"PakettiMidi.lua",
"PakettiOctaMEDSuite.lua",
"PakettiPatternEditor.lua",
"PakettiPatternEditorCheatSheet.lua",
"PakettiPatternMatrix.lua",
"PakettiPatternSequencer.lua",
"PakettiPhraseEditor.lua",
"PakettiPlayerProSuite.lua",
"PakettiRecorder.lua",
"PakettiRequests.lua",
"PakettiSamples.lua",
"PakettiThemeSelector.lua",
"PakettiTkna.lua",
}
-- Table to store extracted midi mappings
local midi_mappings = {}
-- Function to read a file and extract midi mappings
local function read_file_and_extract_midi_mappings(file)
local f = io.open(file, "r")
if f then
for line in f:lines() do
-- Match lines that contain "renoise.tool():add_midi_mapping"
local mapping = line:match('renoise.tool%(%):add_midi_mapping{name="([^"]+)"')
if mapping then
table.insert(midi_mappings, mapping)
end
end
f:close()
else
print("Could not open file: " .. file)
end
end
-- Iterate through each required file and extract midi mappings
for _, file in ipairs(required_files) do
read_file_and_extract_midi_mappings(file)
end
-- Print the midi mappings in a format ready for pasting into the list
print("\nPasteable Midi Mappings:\n")
for _, mapping in ipairs(midi_mappings) do
print(' "' .. mapping .. '",')
end
end
-- Call the function to extract and print MIDI mappings
--extract_midi_mappings()
-- Define the original table of all MIDI mappings
local PakettiMidiMappings = {
"Paketti:Cycle Sample Editor Tabs",
"Paketti:Toggle Mute Tracks",
"Paketti:Shift Sample Buffer Up x[Trigger]",
"Paketti:Shift Sample Buffer Down x[Trigger]",
"Paketti:Shift Sample Buffer Up x[Knob]",
"Paketti:Shift Sample Buffer Down x[Knob]",
"Paketti:Shift Sample Buffer Up/Down x[Knob]",
"Paketti:Toggle Solo Tracks",
"Paketti:Slide Selected Column Content Down",
"Paketti:Slide Selected Column Content Up",
"Paketti:Slide Selected Track Content Up",
"Paketti:Slide Selected Track Content Down",
"Paketti:Rotate Sample Buffer Content Forward [Set]",
"Paketti:Rotate Sample Buffer Content Backward [Set]",
"Paketti:Move to Next Track (Wrap) [Knob]",
"Paketti:Move to Previous Track (Wrap) [Knob]",
"Paketti:Move to Next Track [Knob]",
"Paketti:Move to Previous Track [Knob]",
"Track Devices:Paketti:Load DC Offset",
"Paketti:Hide Track DSP Device External Editors for All Tracks",
"Paketti:Set Beatsync Value x[Knob]",
"Paketti:Groove Settings Groove #1 x[Knob]",
"Paketti:Groove Settings Groove #2 x[Knob]",
"Paketti:Groove Settings Groove #3 x[Knob]",
"Paketti:Groove Settings Groove #4 x[Knob]",
"Paketti:Computer Keyboard Velocity Slider x[Knob]",
"Paketti:Change Selected Sample Volume x[Slider]",
"Paketti:Delay Column (DEPRECATED) x[Slider]",
"Paketti:Metronome On/Off x[Toggle]",
"Paketti:Uncollapser",
"Paketti:Collapser",
"Paketti:Show/Hide Pattern Matrix x[Toggle]",
"Paketti:Record and Follow x[Toggle]",
"Paketti:Record and Follow On/Off x[Knob]",
"Paketti:Record Quantize On/Off x[Toggle]",
"Paketti:Impulse Tracker F5 Start Playback x[Toggle]",
"Paketti:Impulse Tracker F8 Stop Playback (Panic) x[Toggle]",
"Paketti:Impulse Tracker F7 Start Playback from Cursor Row x[Toggle]",
"Paketti:Stop Playback (Panic) x[Toggle]",
"Paketti:Play Current Line & Advance by EditStep x[Toggle]",
"Paketti:Impulse Tracker Pattern (Next) x[Toggle]",
"Paketti:Impulse Tracker Pattern (Previous) x[Toggle]",
"Paketti:Switch to Automation",
"Paketti:Save Sample Range .WAV",
"Paketti:Save Sample Range .FLAC",
"Paketti:Wipe&Slice (004) x[Toggle]",
"Paketti:Wipe&Slice (008) x[Toggle]",
"Paketti:Wipe&Slice (016) x[Toggle]",
"Paketti:Wipe&Slice (032) x[Toggle]",
"Paketti:Wipe&Slice (064) x[Toggle]",
"Paketti:Wipe&Slice (128) x[Toggle]",
"Paketti:Set Delay (+1) x[Toggle]",
"Paketti:Set Delay (-1) x[Toggle]",
"Paketti:Numpad SelectPlay 0 x[Toggle]",
"Paketti:Numpad SelectPlay 1 x[Toggle]",
"Paketti:Numpad SelectPlay 2 x[Toggle]",
"Paketti:Numpad SelectPlay 3 x[Toggle]",
"Paketti:Numpad SelectPlay 4 x[Toggle]",
"Paketti:Numpad SelectPlay 5 x[Toggle]",
"Paketti:Numpad SelectPlay 6 x[Toggle]",
"Paketti:Numpad SelectPlay 7 x[Toggle]",
"Paketti:Numpad SelectPlay 8 x[Toggle]",
"Paketti:Capture Nearest Instrument and Octave",
"Paketti:Simple Play",
"Paketti:Columnizer Delay Increase (+1) x[Toggle]",
"Paketti:Columnizer Delay Decrease (-1) x[Toggle]",
"Paketti:Columnizer Panning Increase (+1) x[Toggle]",
"Paketti:Columnizer Panning Decrease (-1) x[Toggle]",
"Paketti:Columnizer Volume Increase (+1) x[Toggle]",
"Paketti:Columnizer Volume Decrease (-1) x[Toggle]",
"Paketti:Columnizer Effect Number Increase (+1) x[Toggle]",
"Paketti:Columnizer Effect Number Decrease (-1) x[Toggle]",
"Paketti:Columnizer Effect Amount Increase (+1) x[Toggle]",
"Paketti:Columnizer Effect Amount Decrease (-1) x[Toggle]",
"Sample Editor:Paketti:Disk Browser Focus",
"Pattern Editor:Paketti:Disk Browser Focus",
"Paketti:Change Selected Sample Loop Mode x[Knob]",
"Paketti:Selected Sample Loop to 1 No Loop x[On]",
"Paketti:Selected Sample Loop to 2 Forward x[On]",
"Paketti:Selected Sample Loop to 3 Backward x[On]",
"Paketti:Selected Sample Loop to 4 PingPong x[On]",
"Paketti:Selected Sample Loop to 1 No Loop x[Toggle]",
"Paketti:Selected Sample Loop to 2 Forward x[Toggle]",
"Paketti:Selected Sample Loop to 3 Backward x[Toggle]",
"Paketti:Selected Sample Loop to 4 PingPong x[Toggle]",
"Paketti:Record to Current Track x[Toggle]",
"Paketti:Simple Play Record Follow",
"Paketti:Midi Change EditStep 1-64 x[Knob]",
"Paketti:Midi Select Group (Previous)",
"Paketti:Midi Select Group (Next)",
"Paketti:Midi Select Track (Previous)",
"Paketti:Midi Select Track (Next)",
"Paketti:Midi Select Group Tracks x[Knob]",
"Paketti:Midi Change Octave x[Knob]",
"Paketti:Midi Change Selected Track x[Knob]",
"Paketti:Midi Change Selected Track DSP Device x[Knob]",
"Paketti:Midi Change Selected Instrument x[Knob]",
"Paketti:Midi Change Selected Sample Loop 01 Start x[Knob]",
"Paketti:Midi Change Selected Sample Loop 02 End x[Knob]",
"Sample Editor:Paketti:Sample Buffer Selection 01 Start x[Knob]",
"Sample Editor:Paketti:Sample Buffer Selection 02 End x[Knob]",
"Track Automation:Paketti:Midi Automation Curve Draw Selection x[Knob]",
"Paketti:Midi Automation Selection 01 Start x[Knob]",
"Paketti:Midi Automation Selection 02 End x[Knob]",
"Paketti:Create New Instrument & Loop from Selection",
"Paketti:Midi Change Sample Modulation Set Filter",
"Paketti:Selected Instrument Midi Program +1 (Next)",
"Paketti:Selected Instrument Midi Program -1 (Previous)",
"Paketti:Midi Change 01 Volume Column Value x[Knob]",
"Paketti:Midi Change 02 Panning Column Value x[Knob]",
"Paketti:Midi Change 03 Delay Column Value x[Knob]",
"Paketti:Midi Change 04 Effect Column Value x[Knob]",
"Paketti:EditStep Double x[Button]",
"Paketti:EditStep Halve x[Button]",
"Paketti:Set Pattern Length to 001",
"Paketti:Set Pattern Length to 004",
"Paketti:Set Pattern Length to 008",
"Paketti:Set Pattern Length to 016",
"Paketti:Set Pattern Length to 032",
"Paketti:Set Pattern Length to 048",
"Paketti:Set Pattern Length to 064",
"Paketti:Set Pattern Length to 096",
"Paketti:Set Pattern Length to 128",
"Paketti:Set Pattern Length to 192",
"Paketti:Set Pattern Length to 256",
"Paketti:Set Pattern Length to 384",
"Paketti:Set Pattern Length to 512",
"Paketti:Effect Column B00 Reverse Sample Effect On/Off",
"Paketti:Toggle Edit Mode and Tint Track",
"Paketti:Duplicate Effect Column Content to Pattern or Selection",
"Paketti:Randomize Effect Column Parameters",
"Paketti:Interpolate Effect Column Parameters",
"Paketti:Flood Fill Note and Instrument",
"Paketti:Flood Fill Note and Instrument with EditStep",
"Paketti:Paketti Track Renamer",
"Paketti:Clone Current Sequence",
"Sample Editor:Paketti:Sample Buffer Selection Halve",
"Sample Editor:Paketti:Sample Buffer Selection Double",
"Pattern Editor:Paketti:Adjust Selection ",
"Pattern Editor:Paketti:Wipe Selection ",
"Sample Editor:Paketti:Mono to Right with Blank Left",
"Sample Editor:Paketti:Mono to Left with Blank Right",
"Sample Editor:Paketti:Convert Mono to Stereo",
"Paketti:Note Interpolation",
"Paketti:Jump to First Track in Next Group",
"Paketti:Jump to First Track in Previous Group",
"Paketti:Bypass All Other Track DSP Devices (Toggle)",
"Paketti:Isolate Slices or Samples to New Instruments",
"Paketti:Octave Basenote Up",
"Paketti:Octave Basenote Down",
"Paketti:Midi Paketti PitchBend Drumkit Sample Loader",
"Paketti:Midi Paketti PitchBend Multiple Sample Loader",
"Paketti:Midi Paketti Save Selected Sample .WAV",
"Paketti:Midi Paketti Save Selected Sample .FLAC",
"Paketti:Midi Select Padded Slice (Next)",
"Paketti:Midi Select Padded Slice (Previous)",
"Paketti:Duplicate and Reverse Instrument [Trigger]",
"Paketti:Strip Silence",
"Paketti:Move Beginning Silence to End",
"Paketti:Continue Sequence From Same Line [Set Sequence]",
"Paketti:Set Current Section as Scheduled Sequence",
"Paketti:Add Current Section to Scheduled Sequences",
"Paketti:Section Loop (Next)",
"Paketti:Section Loop (Previous)",
"Paketti:Sequence Selection (Next)",
"Paketti:Sequence Selection (Previous)",
"Paketti:Sequence Loop Selection (Next)",
"Paketti:Sequence Loop Selection (Previous)",
"Paketti:Set Section Loop and Schedule Section [Knob]",
}
-- Example grouped structure with direct paths
local grouped_mappings = {
["Groove Settings"] = {
"Paketti:Groove Settings Groove #1 x[Knob]",
"Paketti:Groove Settings Groove #2 x[Knob]",
"Paketti:Groove Settings Groove #3 x[Knob]",
"Paketti:Groove Settings Groove #4 x[Knob]"
},
["Loading/Saving Samples/Instruments"] = {
"Paketti:Midi Paketti PitchBend Multiple Sample Loader",
"Paketti:Midi Paketti PitchBend Drumkit Sample Loader",
"Paketti:Midi Paketti Save Selected Sample .WAV",
"Paketti:Midi Paketti Save Selected Sample .FLAC",
"Paketti:Save Sample Range .WAV",
"Paketti:Save Sample Range .FLAC",
"Paketti:Send Selected Sample to AppSelection1",
"Paketti:Send Selected Sample to AppSelection2",
"Paketti:Send Selected Sample to AppSelection3",
"Paketti:Send Selected Sample to AppSelection4",
"Paketti:Send Selected Sample to AppSelection5",
"Paketti:Send Selected Sample to AppSelection6",
"Paketti:Save Sample to Smart/Backup Folder 1",
"Paketti:Save Sample to Smart/Backup Folder 2",
"Paketti:Save Sample to Smart/Backup Folder 3",
"Paketti:Save All Samples to Smart/Backup Folder 1",
"Paketti:Save All Samples to Smart/Backup Folder 2",
"Paketti:Save All Samples to Smart/Backup Folder 3"
},
["Sample Editor"] = {
"Paketti:Shift Sample Buffer Up x[Trigger]",
"Paketti:Shift Sample Buffer Down x[Trigger]",
"Paketti:Shift Sample Buffer Up x[Knob]",
"Paketti:Shift Sample Buffer Down x[Knob]",
"Paketti:Shift Sample Buffer Up/Down x[Knob]",
"Paketti:Strip Silence",
"Paketti:Move Beginning Silence to End",
"Paketti:Set Beatsync Value x[Knob]",
"Paketti:Midi Change Sample Modulation Set Filter",
"Paketti:Duplicate and Reverse Instrument [Trigger]",
"Paketti:Isolate Slices or Samples to New Instruments",
"Paketti:Change Selected Sample Volume x[Slider]",
"Paketti:Change Selected Sample Loop Mode [x]Knob",
"Paketti:Selected Sample Loop to 1 No Loop x[On]",
"Paketti:Selected Sample Loop to 2 Forward x[On]",
"Paketti:Selected Sample Loop to 3 Backward x[On]",
"Paketti:Selected Sample Loop to 4 PingPong x[On]",
"Paketti:Selected Sample Loop to 1 No Loop x[Toggle]",
"Paketti:Selected Sample Loop to 2 Forward x[Toggle]",
"Paketti:Selected Sample Loop to 3 Backward x[Toggle]",
"Paketti:Selected Sample Loop to 4 PingPong x[Toggle]",
"Paketti:Cycle Sample Editor Tabs",
"Paketti:Create New Instrument & Loop from Selection",
"Paketti:Midi Change Selected Sample Loop 01 Start x[Knob]",
"Sample Editor:Paketti:Sample Buffer Selection 01 Start x[Knob]",
"Sample Editor:Paketti:Sample Buffer Selection 02 End x[Knob]",
"Sample Editor:Paketti:Sample Buffer Selection Halve",
"Sample Editor:Paketti:Sample Buffer Selection Double",
"Sample Editor:Paketti:Mono to Right with Blank Left",
"Sample Editor:Paketti:Mono to Left with Blank Right",
"Sample Editor:Paketti:Convert Mono to Stereo",
"Paketti:Midi Select Padded Slice (Next)",
"Paketti:Midi Select Padded Slice (Previous)",
"Paketti:Rotate Sample Buffer Content Forward [Set]",
"Paketti:Rotate Sample Buffer Content Backward [Set]",
"Sample Editor:Paketti:Disk Browser Focus"
},
["Playback Control"] = {
"Paketti:Impulse Tracker F5 Start Playback x[Toggle]",
"Paketti:Impulse Tracker F8 Stop Playback (Panic) x[Toggle]",
"Paketti:Impulse Tracker F7 Start Playback from Cursor Row x[Toggle]",
"Paketti:Simple Play",
"Paketti:Simple Play Record Follow",
"Paketti:Stop Playback (Panic) x[Toggle]",
"Paketti:Play Current Line & Advance by EditStep x[Toggle]",
"Paketti:Impulse Tracker F8 Stop Playback (Panic) x[Toggle]"
},
["Pattern Editor"] = {
"Paketti:Record to Current Track x[Toggle]",
"Paketti:Jump to First Track in Next Group",
"Paketti:Jump to First Track in Previous Group",
"Paketti:Slide Selected Column Content Down",
"Paketti:Slide Selected Column Content Up",
"Paketti:Slide Selected Track Content Up",
"Paketti:Slide Selected Track Content Down",
"Paketti:Capture Nearest Instrument and Octave",
"Paketti:Flood Fill Note and Instrument",
"Paketti:Flood Fill Note and Instrument with EditStep",
"Paketti:Paketti Track Renamer",
"Paketti:Duplicate Effect Column Content to Pattern or Selection",
"Paketti:Randomize Effect Column Parameters",
"Paketti:Note Interpolation",
"Paketti:Interpolate Effect Column Parameters",
"Paketti:Effect Column B00 Reverse Sample Effect On/Off",
"Paketti:Delay Column (DEPRECATED) x[Slider]",
"Paketti:Set Delay (+1) x[Toggle]",
"Paketti:Set Delay (-1) x[Toggle]",
"Paketti:Toggle Mute Tracks",
"Paketti:Toggle Solo Tracks",
"Paketti:Uncollapser",
"Paketti:Collapser",
"Paketti:Midi Change 01 Volume Column Value x[Knob]",
"Paketti:Midi Change 02 Panning Column Value x[Knob]",
"Paketti:Midi Change 03 Delay Column Value x[Knob]",
"Paketti:Midi Change 04 Effect Column Value x[Knob]",
"Paketti:Impulse Tracker Pattern (Next) x[Toggle]",
"Paketti:Impulse Tracker Pattern (Previous) x[Toggle]",
"Pattern Editor:Paketti:Disk Browser Focus",
"Paketti:Columnizer Delay Increase (+1) x[Toggle]",
"Paketti:Columnizer Delay Decrease (-1) x[Toggle]",
"Paketti:Columnizer Panning Increase (+1) x[Toggle]",
"Paketti:Columnizer Panning Decrease (-1) x[Toggle]",
"Paketti:Columnizer Volume Increase (+1) x[Toggle]",
"Paketti:Columnizer Volume Decrease (-1) x[Toggle]",
"Paketti:Columnizer Effect Number Increase (+1) x[Toggle]",
"Paketti:Columnizer Effect Number Decrease (-1) x[Toggle]",
"Paketti:Columnizer Effect Amount Increase (+1) x[Toggle]",
"Paketti:Columnizer Effect Amount Decrease (-1) x[Toggle]",
"Paketti:Set Pattern Length to 001",
"Paketti:Set Pattern Length to 004",
"Paketti:Set Pattern Length to 008",
"Paketti:Set Pattern Length to 016",
"Paketti:Set Pattern Length to 032",
"Paketti:Set Pattern Length to 048",
"Paketti:Set Pattern Length to 064",
"Paketti:Set Pattern Length to 096",
"Paketti:Set Pattern Length to 128",
"Paketti:Set Pattern Length to 192",
"Paketti:Set Pattern Length to 256",
"Paketti:Set Pattern Length to 384",
"Paketti:Set Pattern Length to 512"
},
["Automation"] = {
"Paketti:Switch to Automation",
"Track Automation:Paketti:Midi Automation Curve Draw Selection x[Knob]",
"Paketti:Midi Automation Selection 01 Start x[Knob]",
"Paketti:Midi Automation Selection 02 End x[Knob]"
},
["Pattern Sequencer/Matrix"] = {
"Paketti:Show/Hide Pattern Matrix x[Toggle]",
"Paketti:Continue Sequence From Same Line [Set Sequence]",
"Paketti:Set Current Section as Scheduled Sequence",
"Paketti:Add Current Section to Scheduled Sequences",
"Paketti:Section Loop (Next)",
"Paketti:Section Loop (Previous)",
"Paketti:Sequence Selection (Next)",
"Paketti:Sequence Selection (Previous)",
"Paketti:Sequence Loop Selection (Next)",
"Paketti:Sequence Loop Selection (Previous)",
"Paketti:Set Section Loop and Schedule Section [Knob]",
"Paketti:Clone Current Sequence"
},
["Controls"] = {
"Paketti:Set EditStep to 00",
"Paketti:Midi Change EditStep 1-64 x[Knob]",
"Paketti:Midi Change EditStep 0-64 x[Knob]",
"Paketti:EditStep Double x[Button]",
"Paketti:EditStep Halve x[Button]",
"Paketti:Midi Select Group (Next)",
"Paketti:Midi Select Group (Previous)",
"Paketti:Midi Select Track (Next)",
"Paketti:Midi Select Track (Previous)",
"Paketti:Midi Select Group Tracks x[Knob]",
"Paketti:Move to Next Track (Wrap) [Knob]",
"Paketti:Move to Previous Track (Wrap) [Knob]",
"Paketti:Numpad SelectPlay 0 x[Toggle]",
"Paketti:Numpad SelectPlay 1 x[Toggle]",
"Paketti:Numpad SelectPlay 2 x[Toggle]",
"Paketti:Numpad SelectPlay 3 x[Toggle]",
"Paketti:Numpad SelectPlay 4 x[Toggle]",
"Paketti:Numpad SelectPlay 5 x[Toggle]",
"Paketti:Numpad SelectPlay 6 x[Toggle]",
"Paketti:Numpad SelectPlay 7 x[Toggle]",
"Paketti:Numpad SelectPlay 8 x[Toggle]",
"Paketti:Computer Keyboard Velocity Slider x[Knob]",
"Paketti:Move to Next Track [Knob]",
"Paketti:Move to Previous Track [Knob]",
"Paketti:Metronome On/Off x[Toggle]",
"Paketti:Record and Follow x[Toggle]",
"Paketti:Record and Follow On/Off x[Knob]",
"Paketti:Record Quantize On/Off x[Toggle]",
"Paketti:Toggle Edit Mode and Tint Track",
"Paketti:Paketti Track Renamer",
"Paketti:Octave Basenote Up",
"Paketti:Octave Basenote Down",
"Paketti:Midi Change Octave x[Knob]",
"Paketti:Midi Change Selected Track x[Knob]",
"Paketti:Midi Change Selected Track DSP Device x[Knob]",
"Paketti:Midi Change Selected Instrument x[Knob]",
},
["Wipe&Slice"] = {
"Paketti:Wipe&Slice (004) x[Toggle]",
"Paketti:Wipe&Slice (008) x[Toggle]",
"Paketti:Wipe&Slice (016) x[Toggle]",
"Paketti:Wipe&Slice (032) x[Toggle]",
"Paketti:Wipe&Slice (064) x[Toggle]",
"Paketti:Wipe&Slice (128) x[Toggle]",
},
["Track DSP Control"] = {
"Paketti:Bypass All Other Track DSP Devices (Toggle)",
"Paketti:Hide Track DSP Device External Editors for All Tracks",
"Track Devices:Paketti:Load DC Offset",
"Paketti:Midi Change Selected Track DSP Device x[Knob]"
}
}
-- Determine the "Unused Mappings" by filtering out used mappings
local used_mappings = {}
for _, group in pairs(grouped_mappings) do
for _, mapping in ipairs(group) do
used_mappings[mapping] = true
end
end
-- Collect unused mappings
local unused_mappings = {}
for _, mapping in ipairs(PakettiMidiMappings) do
if not used_mappings[mapping] then
table.insert(unused_mappings, mapping)
end
end
-- Add "Unused Mappings" to grouped_mappings
grouped_mappings["Unused Mappings"] = unused_mappings
-- Variable to store the dialog reference
local PakettiMidiMappingDialog = nil
-- Function to handle key events
function my_MidiMappingkeyhandler_func(dialog, key)
local closer = preferences.pakettiDialogClose.value
if key.modifiers == "" and key.name == closer then
dialog:close()
PakettiMidiMappingDialog = nil
return nil
else
return key
end
end
-- Function to create and show the MIDI mappings dialog
function show_midi_mappings_dialog()
-- Close the dialog if it's already open
if PakettiMidiMappingDialog and PakettiMidiMappingDialog.visible then
PakettiMidiMappingDialog:close()
PakettiMidiMappingDialog = nil
return
end
-- Initialize the ViewBuilder
local vb = renoise.ViewBuilder()
-- Define dialog properties
local DIALOG_MARGIN = renoise.ViewBuilder.DEFAULT_DIALOG_MARGIN
local CONTENT_SPACING = renoise.ViewBuilder.DEFAULT_CONTROL_SPACING
local MAX_ITEMS_PER_COLUMN = 41
local COLUMN_WIDTH = 220
local buttonWidth = 200 -- Adjustable global button width
-- Create the main column for the dialog
local dialog_content = vb:column {
margin = DIALOG_MARGIN,
spacing = CONTENT_SPACING,
}
-- Add introductory note
local note = vb:text {
text = "NOTE: Open up the Renoise Midi Mappings dialog (CMD-M on macOS), click on the arrow down to show list + searchbar, then click on a button in this dialog to display it.",
style = "strong",
font="bold"
}
dialog_content:add_child(note)
-- Function to create a new column
local function create_new_column()
return vb:column {
spacing = CONTENT_SPACING,
width = COLUMN_WIDTH,
}
end
local current_row = vb:row {}
dialog_content:add_child(current_row)
local current_column = create_new_column()
current_row:add_child(current_column)
local item_count = 0
-- Optimized sorted group titles
local sorted_group_titles = {
"Playback Control",
"Wipe&Slice",
"Groove Settings",
"Loading/Saving Samples/Instruments",
"Automation",
"Track DSP Control",
"Controls",
"Sample Editor",
"Pattern Editor"
}
-- Add "Unused Mappings" to the list if there are any
if #grouped_mappings["Unused Mappings"] > 0 then
table.insert(sorted_group_titles, "Unused Mappings")
end
-- Iterate over the sorted grouped mappings and create GUI elements
for _, group_title in ipairs(sorted_group_titles) do
local mappings = grouped_mappings[group_title]
if mappings then
-- Calculate total items including the title
local total_items = #mappings + 1
-- Check if adding this group would exceed the max items per column
if item_count + total_items > MAX_ITEMS_PER_COLUMN then
-- Create a new column
current_column = create_new_column()
current_row:add_child(current_column)
item_count = 0
end
-- Add the group title
local group_title_text = vb:text {
text = group_title,
font = "bold",
style = "strong",
}
current_column:add_child(group_title_text)
item_count = item_count + 1
-- Add buttons for each mapping in the group
for _, mapping in ipairs(mappings) do
local button_text = mapping:gsub("Paketti:", ""):gsub("Track Automation:", ""):gsub("Sample Editor:", "Sample Editor:")
current_column:add_child(vb:button {
width = buttonWidth,
text = button_text,
midi_mapping = mapping
})
item_count = item_count + 1
-- Check if we need to start a new column
if item_count >= MAX_ITEMS_PER_COLUMN then
current_column = create_new_column()
current_row:add_child(current_column)
item_count = 0
end
end
end
end
-- Show the custom dialog with key handler
PakettiMidiMappingDialog = renoise.app():show_custom_dialog(
"Paketti MIDI Mappings",
dialog_content,
function(dialog, key) return my_MidiMappingkeyhandler_func(dialog, key) end
)
end
-- Function to generate and print Paketti MIDI Mappings to console
function generate_paketti_midi_mappings()
print("Paketti MIDI Mappings:")
for group_title, mappings in pairs(grouped_mappings) do
print("\n" .. group_title)
for _, mapping in ipairs(mappings) do
print(" " .. mapping)
end
end
end
renoise.tool():add_keybinding{name="Global:Paketti:Paketti MIDI Mappings...",
invoke = function() show_midi_mappings_dialog() end}
renoise.tool():add_menu_entry{name="--Main Menu:Tools:Paketti..:!Preferences..:Paketti MIDI Mappings...",
invoke = function() show_midi_mappings_dialog() end}
renoise.tool():add_keybinding{name="Global:Paketti:Generate Paketti Midi Mappings to Console",
invoke = function() generate_paketti_midi_mappings() end}
renoise.tool():add_menu_entry{name="Main Menu:Tools:Paketti..:!Preferences..:Debug..:Generate Paketti Midi Mappings to Console",
invoke = function() generate_paketti_midi_mappings() end}
----
local vb = renoise.ViewBuilder()
local dialog
local debug_log = ""
local suppress_debug_log
local pakettiKeybindings = {}
local identifier_switch
local keybinding_list
local total_shortcuts_text
local selected_shortcuts_text
local show_shortcuts_switch
local search_text
local search_textfield
local padding_number_identifier = 5 -- Padding between number and identifier
local padding_identifier_topic = 25 -- Padding between identifier and topic
local padding_topic_binding = 25 -- Padding between topic and binding
-- Function to detect OS and construct the KeyBindings.xml path
function detectOSAndGetKeyBindingsPath()
local os_name = os.platform()
local renoise_version = renoise.RENOISE_VERSION
local key_bindings_path
if os_name == "WINDOWS" then
local home = os.getenv("USERPROFILE") or os.getenv("HOME")
key_bindings_path = home .. "\\AppData\\Roaming\\Renoise\\V" .. renoise_version .. "\\KeyBindings.xml"
elseif os_name == "MACINTOSH" then
local home = os.getenv("HOME")
key_bindings_path = home .. "/Library/Preferences/Renoise/V" .. renoise_version .. "/KeyBindings.xml"
else -- Assume Linux
local home = os.getenv("HOME")
key_bindings_path = home .. "/.config/Renoise/V" .. renoise_version .. "/KeyBindings.xml"
end
return key_bindings_path
end
-- Function to replace XML encoded entities with their corresponding characters
local function decodeXMLString(value)
local replacements = {
["&"] = "&",
-- Add more replacements if needed
}
return value:gsub("(&)", replacements)
end
-- Function to parse XML and find Paketti content
function pakettiKeyBindingsParseXML(filePath)
local fileHandle = io.open(filePath, "r")
if not fileHandle then
debug_log = debug_log .. "Debug: Failed to open the file - " .. filePath .. "\n"
return {}
end
local content = fileHandle:read("*all")
fileHandle:close()
local pakettiKeybindings = {}
local currentIdentifier = "nil"
for categorySection in content:gmatch("<Category>(.-)</Category>") do
local identifier = categorySection:match("<Identifier>(.-)</Identifier>") or "nil"
if identifier ~= "nil" then
currentIdentifier = identifier
end
for keyBindingSection in categorySection:gmatch("<KeyBinding>(.-)</KeyBinding>") do
local topic = keyBindingSection:match("<Topic>(.-)</Topic>")
if topic and topic:find("Paketti") then
local binding = keyBindingSection:match("<Binding>(.-)</Binding>") or "<No Binding>"
local key = keyBindingSection:match("<Key>(.-)</Key>") or "<Shortcut not Assigned>"
-- Decode XML entities
topic = decodeXMLString(topic)
binding = decodeXMLString(binding)
key = decodeXMLString(key)
table.insert(pakettiKeybindings, { Identifier = currentIdentifier, Topic = topic, Binding = binding, Key = key })
debug_log = debug_log .. "Debug: Found Paketti keybinding - " .. currentIdentifier .. ":" .. topic .. ":" .. binding .. ":" .. key .. "\n"
end
end
end
return pakettiKeybindings
end
-- Function to save the debug log
function pakettiKeyBindingsSaveDebugLog(filteredKeybindings, showUnassignedOnly)
if not pakettiKeybindings then return end -- Ensure pakettiKeybindings is not nil
local filePath = "KeyBindings/Debug_Paketti_KeyBindings.log"
local fileHandle = io.open(filePath, "w")
if fileHandle then
local log_content = "Debug: Total Paketti keybindings found - " .. #pakettiKeybindings .. "\n"
local count = 0
for index, binding in ipairs(filteredKeybindings) do
if not showUnassignedOnly or (showUnassignedOnly and binding.Key == "<Shortcut not Assigned>") then
count = count + 1
log_content = log_content .. string.format("%04d", count) .. ":" .. binding.Identifier .. ":" .. binding.Topic .. ": " .. binding.Binding .. ": " .. binding.Key .. "\n"
end
end
fileHandle:write(log_content)
fileHandle:close()
renoise.app():show_status("Debug log saved to: " .. filePath)
else
renoise.app():show_status("Failed to save debug log.")
end
end
-- Function to calculate the maximum length for entries
function pakettiCalculateMaxLength(entries)
local max_length = 0
for _, entry in ipairs(entries) do
-- Account for the visual difference caused by the squiggle character
local length_adjustment = entry.Binding:find("∿") and 2 or 0
local length = #(string.format("%04d", 0) .. ":" .. entry.Identifier .. ":" .. entry.Topic .. ": " .. entry.Binding) - length_adjustment
max_length = math.max(max_length, length)
end
return max_length
end
-- Function to update the list view based on the filter
function pakettiKeyBindingsUpdateList()
if not identifier_switch then return end -- Ensure the switch is initialized
local showUnassignedOnly = (show_shortcuts_switch.value == 2)
local showAssignedOnly = (show_shortcuts_switch.value == 3)
local selectedIdentifier = identifier_switch.items[identifier_switch.value]
local searchQuery = search_textfield.value:lower()
local content = ""
local count = 0
local unassigned_count = 0
local selected_count = 0
local selected_unassigned_count = 0
local filteredKeybindings = {}
for _, binding in ipairs(pakettiKeybindings) do
local isSelected = (selectedIdentifier == "All") or (binding.Identifier == selectedIdentifier)
-- Normalize to lowercase for case-insensitive search
local topic_lower = binding.Topic:lower()
local binding_lower = binding.Binding:lower()
local identifier_lower = binding.Identifier:lower()
-- Display all entries if searchQuery is empty, otherwise match the query
local matchesSearch = true
for word in searchQuery:gmatch("%S+") do
if not (topic_lower:find(word) or binding_lower:find(word) or identifier_lower:find(word) or binding.Key:lower():find(word)) then
matchesSearch = false
break
end
end
if isSelected and matchesSearch then
-- Count unassigned regardless of show_unassigned_only
if binding.Key == "<Shortcut not Assigned>" then
unassigned_count = unassigned_count + 1
end
-- Filter based on the selected option (Show All, Show without Shortcuts, Show with Shortcuts)
if (showUnassignedOnly and binding.Key == "<Shortcut not Assigned>") or
(showAssignedOnly and binding.Key ~= "<Shortcut not Assigned>") or
(not showUnassignedOnly and not showAssignedOnly) then
table.insert(filteredKeybindings, binding)
if binding.Key == "<Shortcut not Assigned>" then
selected_unassigned_count = selected_unassigned_count + 1
end
selected_count = selected_count + 1
end
end
count = count + 1
end
-- Sort filteredKeybindings by Identifier first, then by Binding
table.sort(filteredKeybindings, function(a, b)
if a.Identifier == b.Identifier then
return a.Binding < b.Binding
else
return a.Identifier < b.Identifier
end
end)
if #filteredKeybindings == 0 then
content = "No KeyBindings available for this filter."
else
-- Calculate max length across all entries
local max_length = pakettiCalculateMaxLength(pakettiKeybindings) + 35
-- Append the key, aligned right
for index, binding in ipairs(filteredKeybindings) do
local entry = string.format("%04d", index)
.. string.rep(" ", padding_number_identifier) .. binding.Identifier
.. string.rep(" ", padding_identifier_topic - #binding.Identifier)
.. binding.Topic
.. string.rep(" ", padding_topic_binding - #binding.Topic)
.. binding.Binding
-- Adjust the visual difference caused by the squiggle character
local length_adjustment = binding.Binding:find("∿") and 2 or 0
local padded_entry = entry .. string.rep(" ", max_length - #entry + length_adjustment) .. " " .. binding.Key
content = content .. padded_entry .. "\n"
end
end
keybinding_list.text = content
local selectedText = ""
if selectedIdentifier == "All" then
selectedText = "For all sections, there are " .. selected_count .. " shortcuts and " .. selected_unassigned_count .. " are unassigned."
else
selectedText = "For " .. selectedIdentifier .. ", there are " .. selected_count .. " shortcuts and " .. selected_unassigned_count .. " are unassigned."
end
selected_shortcuts_text.text = selectedText
total_shortcuts_text.text = "Total: " .. count .. " shortcuts, " .. unassigned_count .. " unassigned."
if not suppress_debug_log then
pakettiKeyBindingsSaveDebugLog(filteredKeybindings, showUnassignedOnly)
end
end
-- Function to handle key events
function my_PakettiKeybindingskeyhandler_func(dialog, key)
local closer = preferences.pakettiDialogClose.value
if key.modifiers == "" and key.name == closer then
dialog:close()
dialog = nil
return nil
else
return key
end
end
-- Main function to display the Paketti keybindings dialog
function showPakettiKeyBindingsDialog()
-- Check if the dialog is already visible and close it
if dialog and dialog.visible then
dialog:close()
return
end
local keyBindingsPath = detectOSAndGetKeyBindingsPath()
if not keyBindingsPath then
renoise.app():show_status("Failed to detect OS and find KeyBindings.xml path.")
return
end
debug_log = debug_log .. "Debug: Using KeyBindings path - " .. keyBindingsPath .. "\n"
pakettiKeybindings = pakettiKeyBindingsParseXML(keyBindingsPath)
if not pakettiKeybindings or #pakettiKeybindings == 0 then
renoise.app():show_status("No Paketti keybindings found.")
debug_log = debug_log .. "Debug: Total Paketti keybindings found - 0\n"
pakettiKeyBindingsSaveDebugLog(pakettiKeybindings, false)
return
end
-- Print total found count at the start
debug_log = "Debug: Total Paketti keybindings found - " .. #pakettiKeybindings .. "\n" .. debug_log
-- Collect all unique Identifiers and sort them alphabetically
local identifier_items = { "All" }
local unique_identifiers = {}
for _, binding in ipairs(pakettiKeybindings) do
if not unique_identifiers[binding.Identifier] then
unique_identifiers[binding.Identifier] = true
table.insert(identifier_items, binding.Identifier)
end
end
table.sort(identifier_items)
-- Create the switch for identifier selection
identifier_switch = vb:switch {
items = identifier_items,
width = 1100,
value = 1, -- Default to "All"
notifier = pakettiKeyBindingsUpdateList
}
-- Create the switch for showing/hiding shortcuts
show_shortcuts_switch = vb:switch {
items = { "Show All", "Show KeyBindings without Shortcuts", "Show KeyBindings with Shortcuts" },
width = 1100,
value = 1, -- Default to "Show All"
notifier = pakettiKeyBindingsUpdateList
}
-- UI Elements
search_textfield = vb:textfield {
width = 300,
notifier = pakettiKeyBindingsUpdateList
}
total_shortcuts_text = vb:text {
text = "Total: 0 shortcuts, 0 unassigned",
font = "bold",
width = 1100, -- Adjusted width to fit the dialog
align = "left"
}
selected_shortcuts_text = vb:text {
text = "For selected sections, there are 0 shortcuts and 0 are unassigned.",
font = "bold",
width = 1100, -- Adjusted width to fit the dialog
align = "left"
}
search_text = vb:text{text="Filter with"}
keybinding_list = vb:multiline_textfield { width = 1100, height = 600, font = "mono" }
-- Dialog title including Renoise version
local dialog_title = "Paketti KeyBindings for Renoise Version " .. renoise.RENOISE_VERSION
dialog = renoise.app():show_custom_dialog(
dialog_title,
vb:column {
margin = 10,
vb:text {
text = "NOTE: KeyBindings.xml is only saved when Renoise is closed - so this is not a realtime / updatable Dialog. Make changes, quit Renoise, and relaunch this Dialog.",
font = "bold"
},
identifier_switch,
show_shortcuts_switch,
vb:row{vb:button{text="Save as Textfile", notifier = function()
local filename = renoise.app():prompt_for_filename_to_write(".txt", "Available Plugins Saver")
if filename then
local file, err = io.open(filename, "w")
if file then
file:write(keybinding_list.text) -- Correct reference to multiline_field's text
file:close()
renoise.app():show_status("File saved successfully")
else
renoise.app():show_status("Error saving file: " .. err)
end
end
end}},
search_text,
search_textfield,
keybinding_list,
selected_shortcuts_text,
total_shortcuts_text
},
my_PakettiKeybindingskeyhandler_func -- Key handler function
)
-- Initial list update
pakettiKeyBindingsUpdateList()
-- Print total found count at the end
debug_log = debug_log .. "Debug: Total Paketti keybindings found - " .. #pakettiKeybindings .. "\n"
pakettiKeyBindingsSaveDebugLog(pakettiKeybindings, false)
end
-- Add main menu entry for Paketti keybindings dialog
renoise.tool():add_menu_entry{name="Main Menu:Tools:Paketti..:!Preferences..:Paketti KeyBindings...",invoke = function() showPakettiKeyBindingsDialog() end}
-- Add specific menu entries under corresponding identifiers
local identifiers = {
"Sample Editor",
"Instrument Box",
"Mixer",
"Pattern Editor",
"Pattern Sequencer",
"Pattern Matrix",
"Phrase Editor",
"Sample Keyzones"
}
for _, identifier in ipairs(identifiers) do
renoise.tool():add_menu_entry {name = identifier .. ":Paketti..:Show Paketti KeyBindings...",