Vendor helgoboss/helgobox (ReaLearn) as basis for custom UI fork
Stripped upstream git history; starting point for replacing the native SWELL/Win32 mapping UI with something more suited to bulk editing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+34
@@ -0,0 +1,34 @@
|
||||
--- name: APC Key 25 mk2 - Playtime
|
||||
--- realearn_version: 2.16.0-pre.8
|
||||
--- author: helgoboss
|
||||
--- device_manufacturer: Akai
|
||||
--- device_name: APC Key 25 mk2
|
||||
--- description: |
|
||||
--- This main preset turns the APC Key 25 mk2 into a capable device for controlling Playtime. Hold Shift
|
||||
--- to access advanced functions.
|
||||
--- used_schemes: [akai/apc-key-25-mk2]
|
||||
--- required_features: [playtime]
|
||||
|
||||
--!strict
|
||||
|
||||
|
||||
local commons = require("akai/apc-lib/playtime-commons")
|
||||
|
||||
return commons.create_compartment {
|
||||
use_column_stop_buttons = true,
|
||||
stop_column_if_slot_empty = true,
|
||||
mute_track_button_id = "row3/play",
|
||||
arm_track_button_id = "row4/play",
|
||||
column_count = 8,
|
||||
row_count = 5,
|
||||
up_button_id = "col1/stop",
|
||||
down_button_id = "col2/stop",
|
||||
left_button_id = "col3/stop",
|
||||
right_button_id = "col4/stop",
|
||||
volume_button_id = "col5/stop",
|
||||
pan_button_id = "col6/stop",
|
||||
send_button_id = "col7/stop",
|
||||
device_button_id = "col8/stop",
|
||||
stop_all_clips_button_id = "stop-all-clips",
|
||||
stop_all_clips_need_shift = false,
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
--- name: APC Key 25 - Playtime
|
||||
--- realearn_version: 2.16.0-pre.8
|
||||
--- author: helgoboss
|
||||
--- device_manufacturer: Akai
|
||||
--- device_name: APC Key 25
|
||||
--- description: |
|
||||
--- This main preset turns the APC Key 25 mk1 into a capable device for controlling Playtime. Hold Shift or Sustain
|
||||
--- to access advanced functions.
|
||||
--- used_schemes: [akai/apc-key-25]
|
||||
--- required_features: [playtime]
|
||||
|
||||
--!strict
|
||||
|
||||
local commons = require("akai/apc-lib/playtime-commons")
|
||||
|
||||
return commons.create_compartment {
|
||||
use_column_stop_buttons = true,
|
||||
stop_column_if_slot_empty = true,
|
||||
mute_track_button_id = "row4/play",
|
||||
arm_track_button_id = "row3/play",
|
||||
column_count = 8,
|
||||
row_count = 5,
|
||||
up_button_id = "col1/stop",
|
||||
down_button_id = "col2/stop",
|
||||
left_button_id = "col3/stop",
|
||||
right_button_id = "col4/stop",
|
||||
volume_button_id = "col5/stop",
|
||||
pan_button_id = "col6/stop",
|
||||
send_button_id = "col7/stop",
|
||||
device_button_id = "col8/stop",
|
||||
stop_all_clips_button_id = "stop-all-clips",
|
||||
stop_all_clips_need_shift = false,
|
||||
}
|
||||
+886
@@ -0,0 +1,886 @@
|
||||
--!strict
|
||||
|
||||
local util = require("util")
|
||||
local realearn = require("realearn")
|
||||
local playtime_util = require("playtime_util")
|
||||
|
||||
local module = {}
|
||||
|
||||
export type ApcPlaytimePresetConfig = {
|
||||
mute_track_button_id: string,
|
||||
arm_track_button_id: string,
|
||||
use_column_stop_buttons: boolean,
|
||||
stop_column_if_slot_empty: boolean,
|
||||
column_count: number,
|
||||
row_count: number,
|
||||
up_button_id: string,
|
||||
down_button_id: string,
|
||||
left_button_id: string,
|
||||
right_button_id: string,
|
||||
volume_button_id: string,
|
||||
pan_button_id: string,
|
||||
send_button_id: string,
|
||||
device_button_id: string,
|
||||
stop_all_clips_button_id: string,
|
||||
stop_all_clips_need_shift: boolean,
|
||||
}
|
||||
|
||||
function module.create_compartment(config: ApcPlaytimePresetConfig): realearn.Compartment
|
||||
-- Aliases
|
||||
|
||||
local partial_mapping = util.partial_mapping
|
||||
local turbo = playtime_util.turbo
|
||||
local scroll_vertically = playtime_util.scroll_vertically
|
||||
local scroll_horizontally = playtime_util.scroll_horizontally
|
||||
|
||||
-- Types
|
||||
|
||||
type Mode = {
|
||||
index: number,
|
||||
label: string,
|
||||
}
|
||||
|
||||
type ModeMap = { [string]: Mode }
|
||||
|
||||
type ParameterMap = { [string]: realearn.Parameter }
|
||||
|
||||
type GroupMap = { [string]: realearn.Group }
|
||||
|
||||
-- Constants
|
||||
|
||||
local column_mode_count = 100
|
||||
local knob_mode_count = 100
|
||||
|
||||
-- Column modes
|
||||
|
||||
local column_modes: ModeMap = {
|
||||
stop = {
|
||||
index = 0,
|
||||
label = "Stop clip",
|
||||
},
|
||||
solo = {
|
||||
index = 1,
|
||||
label = "Solo",
|
||||
},
|
||||
record_arm = {
|
||||
index = 2,
|
||||
label = "Record arm",
|
||||
},
|
||||
mute = {
|
||||
index = 3,
|
||||
label = "Mute",
|
||||
},
|
||||
select = {
|
||||
index = 4,
|
||||
label = "Track select",
|
||||
},
|
||||
}
|
||||
local sorted_column_modes = util.sorted_by_index(column_modes)
|
||||
|
||||
-- Knob modes
|
||||
local knob_modes: ModeMap = {
|
||||
volume = {
|
||||
index = 0,
|
||||
label = "Volume",
|
||||
},
|
||||
pan = {
|
||||
index = 1,
|
||||
label = "Pan",
|
||||
},
|
||||
sends = {
|
||||
index = 2,
|
||||
label = "Sends",
|
||||
},
|
||||
device = {
|
||||
index = 3,
|
||||
label = "Device",
|
||||
},
|
||||
}
|
||||
local sorted_knob_modes = util.sorted_by_index(knob_modes)
|
||||
|
||||
-- Parameters
|
||||
|
||||
local params: ParameterMap = {
|
||||
shift = {
|
||||
index = 0,
|
||||
name = "Shift modifier",
|
||||
},
|
||||
column_mode = {
|
||||
index = 1,
|
||||
name = "Column mode",
|
||||
value_count = column_mode_count,
|
||||
value_labels = util.extract_labels(sorted_column_modes),
|
||||
},
|
||||
knob_mode = {
|
||||
index = 2,
|
||||
name = "Knob mode",
|
||||
value_count = knob_mode_count,
|
||||
value_labels = util.extract_labels(sorted_knob_modes),
|
||||
},
|
||||
send = {
|
||||
index = 3,
|
||||
name = "Send",
|
||||
value_count = 2,
|
||||
},
|
||||
sustain = {
|
||||
index = 4,
|
||||
name = "Sustain modifier",
|
||||
},
|
||||
}
|
||||
|
||||
-- Domain functions
|
||||
|
||||
local function create_index_expression(variable_name: string, index: number): string
|
||||
return `{variable_name} + {index}`
|
||||
end
|
||||
|
||||
local function create_col_expression(col: number): string
|
||||
return create_index_expression("control_unit_column_index", col)
|
||||
end
|
||||
|
||||
local function create_row_expression(row: number): string
|
||||
return create_index_expression("control_unit_row_index", row)
|
||||
end
|
||||
|
||||
local function create_slot_selector(col: number, row: number): realearn.PlaytimeSlotDescriptor
|
||||
return realearn.PlaytimeSlotDescriptor.Dynamic {
|
||||
column_expression = create_col_expression(col),
|
||||
row_expression = create_row_expression(row),
|
||||
}
|
||||
end
|
||||
|
||||
local function create_column_selector(col: number): realearn.PlaytimeColumnDescriptor
|
||||
return realearn.PlaytimeColumnDescriptor.Dynamic {
|
||||
expression = create_col_expression(col),
|
||||
}
|
||||
end
|
||||
|
||||
local function create_row_selector(row: number): realearn.PlaytimeRowDescriptor
|
||||
return realearn.PlaytimeRowDescriptor.Dynamic {
|
||||
expression = create_row_expression(row),
|
||||
}
|
||||
end
|
||||
|
||||
local function knob(index: number)
|
||||
return partial_mapping {
|
||||
source = realearn.Source.Virtual {
|
||||
character = "Multi",
|
||||
id = index,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function button(id: string)
|
||||
return partial_mapping {
|
||||
source = realearn.Source.Virtual {
|
||||
character = "Button",
|
||||
id = id,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function column_stop_button(col: number)
|
||||
return button(`col{col + 1}/stop`)
|
||||
end
|
||||
|
||||
local function row_play_button(row: number)
|
||||
return button(`row{row + 1}/play`)
|
||||
end
|
||||
|
||||
local function slot_button(col: number, row: number)
|
||||
return partial_mapping {
|
||||
source = realearn.Source.Virtual {
|
||||
character = "Multi",
|
||||
id = `col{col + 1}/row{row + 1}/pad`,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function shift_pressed(on: boolean)
|
||||
return partial_mapping {
|
||||
activation_condition = realearn.ActivationCondition.Modifier {
|
||||
modifiers = {
|
||||
{
|
||||
parameter = params.shift.index,
|
||||
on = on,
|
||||
},
|
||||
{
|
||||
parameter = params.sustain.index,
|
||||
on = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function sustain_pressed(on: boolean)
|
||||
return partial_mapping {
|
||||
activation_condition = realearn.ActivationCondition.Modifier {
|
||||
modifiers = {
|
||||
{
|
||||
parameter = params.sustain.index,
|
||||
on = on,
|
||||
},
|
||||
{
|
||||
parameter = params.shift.index,
|
||||
on = false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function shift_or_sustain_pressed()
|
||||
return partial_mapping {
|
||||
activation_condition = realearn.ActivationCondition.Expression {
|
||||
condition = `p[{params.shift.index}] || p[{params.sustain.index}]`,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function shift_and_sustain_pressed()
|
||||
return partial_mapping {
|
||||
activation_condition = realearn.ActivationCondition.Modifier {
|
||||
modifiers = {
|
||||
{
|
||||
parameter = params.sustain.index,
|
||||
on = true,
|
||||
},
|
||||
{
|
||||
parameter = params.shift.index,
|
||||
on = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function fire_max(millis: number)
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
fire_mode = realearn.FireMode.Normal {
|
||||
press_duration_interval = { 0, millis },
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function fire_after_timeout(millis: number)
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
fire_mode = realearn.FireMode.AfterTimeout {
|
||||
timeout = millis,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function fire_on_single_press(max_duration: number)
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
fire_mode = realearn.FireMode.OnSinglePress {
|
||||
max_duration = max_duration,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function fire_on_double_press()
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
fire_mode = realearn.FireMode.OnDoublePress(),
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local no_mod = shift_pressed(false)
|
||||
local shift = shift_pressed(true)
|
||||
local sustain = sustain_pressed(true)
|
||||
local shift_or_sustain = shift_or_sustain_pressed()
|
||||
local short_press = fire_max(200)
|
||||
local long_press = fire_after_timeout(1000)
|
||||
local single_press = fire_on_single_press(200)
|
||||
local double_press = fire_on_double_press()
|
||||
|
||||
local function clip_matrix_action(action: realearn.PlaytimeMatrixAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.PlaytimeMatrixAction {
|
||||
action = action,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function clip_column_action(col: number, action: realearn.PlaytimeColumnAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.PlaytimeColumnAction {
|
||||
column = create_column_selector(col),
|
||||
action = action,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function clip_row_action(row: number, action: realearn.PlaytimeRowAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.PlaytimeRowAction {
|
||||
row = create_row_selector(row),
|
||||
action = action,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function clip_column_track(col: number): realearn.TrackDescriptor
|
||||
return realearn.TrackDescriptor.FromClipColumn {
|
||||
column = create_column_selector(col),
|
||||
context = "Playback",
|
||||
}
|
||||
end
|
||||
|
||||
local function column_track_target(col: number, track_target_kind: realearn.TargetKind, exclusive: boolean?)
|
||||
return partial_mapping {
|
||||
target = {
|
||||
kind = track_target_kind,
|
||||
track = clip_column_track(col),
|
||||
exclusivity = if exclusive then "WithinFolderOnOnly" else nil,
|
||||
} :: any,
|
||||
}
|
||||
end
|
||||
|
||||
local function route_target(col: number, route_target_kind: realearn.TargetKind)
|
||||
return partial_mapping {
|
||||
target = {
|
||||
kind = route_target_kind,
|
||||
route = realearn.RouteDescriptor.Dynamic {
|
||||
track = clip_column_track(col),
|
||||
expression = `p[{params.send.index}]`,
|
||||
},
|
||||
} :: any,
|
||||
}
|
||||
end
|
||||
|
||||
local function clip_transport_action(col: number, row: number, action: realearn.PlaytimeSlotTransportAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.PlaytimeSlotTransportAction {
|
||||
slot = create_slot_selector(col, row),
|
||||
action = action,
|
||||
stop_column_if_slot_empty = config.stop_column_if_slot_empty,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function clip_management_action(col: number, row: number, action: realearn.PlaytimeSlotManagementAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.PlaytimeSlotManagementAction {
|
||||
slot = create_slot_selector(col, row),
|
||||
action = action,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function transport_action(action: realearn.TransportAction)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.TransportAction {
|
||||
action = action,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function reaper_action(command: realearn.ReaperCommand)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.ReaperAction {
|
||||
command = command,
|
||||
invocation = "Trigger",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function toggle()
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
absolute_mode = "ToggleButton",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function pick_up()
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
takeover_mode = "PickUpTolerant",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function incremental()
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
absolute_mode = "IncrementalButton",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function wrap()
|
||||
return partial_mapping {
|
||||
glue = {
|
||||
wrap = true,
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function control_disabled()
|
||||
return partial_mapping {
|
||||
control_enabled = false,
|
||||
visible_in_projection = false,
|
||||
}
|
||||
end
|
||||
|
||||
local function feedback_disabled()
|
||||
return partial_mapping {
|
||||
feedback_enabled = false,
|
||||
}
|
||||
end
|
||||
|
||||
local function set_param(index: number)
|
||||
return partial_mapping {
|
||||
target = realearn.Target.CompartmentParameterValue {
|
||||
parameter = realearn.CompartmentParameterDescriptor.ById {
|
||||
index = index,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function name(n: string)
|
||||
return partial_mapping {
|
||||
name = n,
|
||||
}
|
||||
end
|
||||
|
||||
local function group(g: realearn.Group)
|
||||
return partial_mapping {
|
||||
group = g.id,
|
||||
}
|
||||
end
|
||||
|
||||
local function set_mode(mode: Mode, mode_count: number, mode_param_index: number)
|
||||
local target_value = mode.index / (mode_count - 1)
|
||||
return partial_mapping {
|
||||
name = mode.label,
|
||||
glue = {
|
||||
target_interval = { target_value, target_value },
|
||||
out_of_range_behavior = "Min",
|
||||
},
|
||||
target = realearn.Target.CompartmentParameterValue {
|
||||
parameter = realearn.CompartmentParameterDescriptor.ById {
|
||||
index = mode_param_index,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
local function set_column_mode(mode: Mode)
|
||||
return set_mode(mode, column_mode_count, params.column_mode.index)
|
||||
end
|
||||
|
||||
local function set_knob_mode(mode: Mode)
|
||||
return set_mode(mode, knob_mode_count, params.knob_mode.index)
|
||||
end
|
||||
|
||||
local function column_mode_is(column_mode: Mode)
|
||||
return realearn.ActivationCondition.Bank {
|
||||
parameter = params.column_mode.index,
|
||||
bank_index = column_mode.index,
|
||||
}
|
||||
end
|
||||
|
||||
local function knob_mode_is(knob_mode)
|
||||
return realearn.ActivationCondition.Bank {
|
||||
parameter = params.knob_mode.index,
|
||||
bank_index = knob_mode.index,
|
||||
}
|
||||
end
|
||||
|
||||
-- Groups
|
||||
|
||||
local groups: GroupMap = {
|
||||
slot_modes = {
|
||||
name = "Slot modes",
|
||||
},
|
||||
column_modes = {
|
||||
name = "Column modes",
|
||||
},
|
||||
record_settings = {
|
||||
name = "Record settings",
|
||||
},
|
||||
knob_modes = {
|
||||
name = "Knob modes",
|
||||
},
|
||||
slot_feedback = {
|
||||
name = "Slot feedback",
|
||||
},
|
||||
slot_play = {
|
||||
name = "Slot play",
|
||||
},
|
||||
slot_clear = {
|
||||
name = "Slot clear",
|
||||
},
|
||||
slot_quantize = {
|
||||
name = "Slot quantize",
|
||||
},
|
||||
slot_copy_or_paste = {
|
||||
name = "Slot copy or paste",
|
||||
},
|
||||
slot_double = {
|
||||
name = "Slot double section",
|
||||
},
|
||||
slot_halve = {
|
||||
name = "Slot halve section",
|
||||
},
|
||||
column_stop = {
|
||||
name = "Column stop",
|
||||
activation_condition = column_mode_is(column_modes.stop),
|
||||
},
|
||||
row_play_scene = {
|
||||
name = "Row play scene",
|
||||
},
|
||||
row_build_scene = {
|
||||
name = "Row build scene",
|
||||
},
|
||||
row_copy_or_paste_scene = {
|
||||
name = "Row copy or paste scene",
|
||||
},
|
||||
row_clear_scene = {
|
||||
name = "Row clear scene",
|
||||
},
|
||||
column_solo = {
|
||||
name = "Column solo",
|
||||
activation_condition = column_mode_is(column_modes.solo),
|
||||
},
|
||||
column_record_arm = {
|
||||
name = "Column record arm",
|
||||
activation_condition = column_mode_is(column_modes.record_arm),
|
||||
},
|
||||
column_mute = {
|
||||
name = "Column mute",
|
||||
activation_condition = column_mode_is(column_modes.mute),
|
||||
},
|
||||
column_select = {
|
||||
name = "Column select",
|
||||
activation_condition = column_mode_is(column_modes.select),
|
||||
},
|
||||
knob_volume = {
|
||||
name = "Knob volume",
|
||||
activation_condition = knob_mode_is(knob_modes.volume),
|
||||
},
|
||||
knob_pan = {
|
||||
name = "Knob pan",
|
||||
activation_condition = knob_mode_is(knob_modes.pan),
|
||||
},
|
||||
knob_sends = {
|
||||
name = "Knob sends",
|
||||
activation_condition = knob_mode_is(knob_modes.sends),
|
||||
},
|
||||
knob_device = {
|
||||
name = "Knob device",
|
||||
activation_condition = knob_mode_is(knob_modes.device),
|
||||
},
|
||||
}
|
||||
util.set_keys_as_ids(groups)
|
||||
|
||||
-- Mappings
|
||||
|
||||
local mappings = {
|
||||
name("Play/stop") + no_mod + button("play") + toggle() + clip_matrix_action("PlayIgnitedOrEnterSilenceMode"),
|
||||
name("Shift modifier") + button("shift") + set_param(params.shift.index),
|
||||
name("Sustain modifier") + button("sustain") + set_param(params.sustain.index),
|
||||
name("Undo") + shift + button("play") + clip_matrix_action("Undo"),
|
||||
name("Record") + no_mod + button("record") + clip_matrix_action("SmartRecord"),
|
||||
name("Redo") + shift + button("record") + clip_matrix_action("Redo"),
|
||||
name("Build scene") + sustain + button("record") + clip_matrix_action("BuildScene"),
|
||||
name("Switch send")
|
||||
+ group(groups.knob_sends)
|
||||
+ feedback_disabled()
|
||||
+ shift
|
||||
+ button("col7/stop")
|
||||
+ incremental()
|
||||
+ wrap()
|
||||
+ set_param(params.send.index),
|
||||
name("Column stop mode")
|
||||
+ group(groups.column_modes)
|
||||
+ shift
|
||||
+ button("row1/play")
|
||||
+ set_column_mode(column_modes.stop),
|
||||
name("Column solo mode")
|
||||
+ group(groups.column_modes)
|
||||
+ shift
|
||||
+ button("row2/play")
|
||||
+ set_column_mode(column_modes.solo),
|
||||
name("Column arm mode")
|
||||
+ group(groups.column_modes)
|
||||
+ shift
|
||||
+ button(config.arm_track_button_id)
|
||||
+ set_column_mode(column_modes.record_arm),
|
||||
name("Column mute mode")
|
||||
+ group(groups.column_modes)
|
||||
+ shift
|
||||
+ button(config.mute_track_button_id)
|
||||
+ set_column_mode(column_modes.mute),
|
||||
name("Column select mode")
|
||||
+ group(groups.column_modes)
|
||||
+ shift
|
||||
+ button("row5/play")
|
||||
+ set_column_mode(column_modes.select),
|
||||
}
|
||||
|
||||
if config.stop_all_clips_need_shift then
|
||||
-- We have a device that has a "Stop all clips" button but it needs shift to be pressed
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Stop all clips") + shift + button(config.stop_all_clips_button_id) + clip_matrix_action("Stop")
|
||||
)
|
||||
else
|
||||
-- We have a device with a dedicated "Stop all clips" button
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Stop all clips") + no_mod + button(config.stop_all_clips_button_id) + clip_matrix_action("Stop")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Click") + shift + button(config.stop_all_clips_button_id) + reaper_action(40364)
|
||||
)
|
||||
end
|
||||
|
||||
if config.use_column_stop_buttons then
|
||||
-- Scrolling
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Scroll up") + shift_or_sustain + button(config.up_button_id) + turbo() + scroll_vertically(-1)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Scroll down") + shift_or_sustain + button(config.down_button_id) + turbo() + scroll_vertically(1)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Scroll left") + shift_or_sustain + button(config.left_button_id) + turbo() + scroll_horizontally(-1)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Scroll right") + shift_or_sustain + button(config.right_button_id) + turbo() + scroll_horizontally(1)
|
||||
)
|
||||
-- Modes
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Knob volume mode")
|
||||
+ group(groups.knob_modes)
|
||||
+ shift
|
||||
+ button(config.volume_button_id)
|
||||
+ set_knob_mode(knob_modes.volume)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Knob pan mode")
|
||||
+ group(groups.knob_modes)
|
||||
+ shift
|
||||
+ button(config.pan_button_id)
|
||||
+ set_knob_mode(knob_modes.pan)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Knob send mode")
|
||||
+ group(groups.knob_modes)
|
||||
+ shift
|
||||
+ button(config.send_button_id)
|
||||
+ set_knob_mode(knob_modes.sends)
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Knob device mode")
|
||||
+ group(groups.knob_modes)
|
||||
+ shift
|
||||
+ button(config.device_button_id)
|
||||
+ set_knob_mode(knob_modes.device)
|
||||
)
|
||||
end
|
||||
|
||||
-- For each column
|
||||
for col = 0, config.column_count - 1 do
|
||||
-- Column stop button functions
|
||||
if config.use_column_stop_buttons then
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Stop column")
|
||||
+ group(groups.column_stop)
|
||||
+ no_mod
|
||||
+ column_stop_button(col)
|
||||
+ clip_column_action(col, "Stop")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Solo track")
|
||||
+ group(groups.column_solo)
|
||||
+ no_mod
|
||||
+ toggle()
|
||||
+ column_stop_button(col)
|
||||
+ column_track_target(col, "TrackSoloState")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Arm track")
|
||||
+ group(groups.column_record_arm)
|
||||
+ no_mod
|
||||
+ toggle()
|
||||
+ column_stop_button(col)
|
||||
+ clip_column_action(col, "ArmStateExclusive")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Mute track")
|
||||
+ group(groups.column_mute)
|
||||
+ no_mod
|
||||
+ toggle()
|
||||
+ column_stop_button(col)
|
||||
+ column_track_target(col, "TrackMuteState")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Select track")
|
||||
+ group(groups.column_select)
|
||||
+ no_mod
|
||||
+ toggle()
|
||||
+ column_stop_button(col)
|
||||
+ column_track_target(col, "TrackSelectionState", true)
|
||||
)
|
||||
end
|
||||
-- Knob functions
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Track volume") + group(groups.knob_volume) + knob(col) + pick_up() + column_track_target(col, "TrackVolume")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Track pan") + group(groups.knob_pan) + knob(col) + pick_up() + column_track_target(col, "TrackPan")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Track send volume") + group(groups.knob_sends) + knob(col) + pick_up() + route_target(col, "RouteVolume")
|
||||
)
|
||||
end
|
||||
|
||||
-- For each row
|
||||
for row = 0, config.row_count - 1 do
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Play scene")
|
||||
+ group(groups.row_play_scene)
|
||||
+ feedback_disabled()
|
||||
+ no_mod
|
||||
+ row_play_button(row)
|
||||
+ clip_row_action(row, "PlayScene")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Copy or paste")
|
||||
+ group(groups.row_copy_or_paste_scene)
|
||||
+ sustain
|
||||
+ short_press
|
||||
+ row_play_button(row)
|
||||
+ clip_row_action(row, "CopyOrPasteScene")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Long = Clear")
|
||||
+ group(groups.row_clear_scene)
|
||||
+ feedback_disabled()
|
||||
+ sustain
|
||||
+ long_press
|
||||
+ row_play_button(row)
|
||||
+ clip_row_action(row, "ClearScene")
|
||||
)
|
||||
end
|
||||
|
||||
-- For each slot
|
||||
for col = 0, config.column_count - 1 do
|
||||
for row = 0, config.row_count - 1 do
|
||||
-- Feedback
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Slot feedback")
|
||||
+ group(groups.slot_feedback)
|
||||
+ control_disabled()
|
||||
+ slot_button(col, row)
|
||||
+ playtime_util.slot_state_text_feedback()
|
||||
+ clip_transport_action(col, row, "Trigger")
|
||||
)
|
||||
-- Control
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Slot trigger")
|
||||
+ group(groups.slot_play)
|
||||
+ feedback_disabled()
|
||||
+ no_mod
|
||||
+ slot_button(col, row)
|
||||
+ clip_transport_action(col, row, "Trigger")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Copy or paste")
|
||||
+ group(groups.slot_copy_or_paste)
|
||||
+ feedback_disabled()
|
||||
+ sustain
|
||||
+ single_press
|
||||
+ slot_button(col, row)
|
||||
+ toggle()
|
||||
+ clip_management_action(col, row, "CopyOrPasteClip")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Long = Delete")
|
||||
+ group(groups.slot_clear)
|
||||
+ feedback_disabled()
|
||||
+ sustain
|
||||
+ long_press
|
||||
+ slot_button(col, row)
|
||||
+ clip_management_action(col, row, "ClearSlot")
|
||||
)
|
||||
table.insert(
|
||||
mappings,
|
||||
name("2x = Edit")
|
||||
+ group(groups.slot_quantize)
|
||||
+ feedback_disabled()
|
||||
+ sustain
|
||||
+ double_press
|
||||
+ slot_button(col, row)
|
||||
+ toggle()
|
||||
+ clip_management_action(col, row, "EditClip")
|
||||
)
|
||||
--table.insert(mappings, name("Overdub clip") + group(groups.slot_play) + feedback_disabled() + shift + single_press + slot_button(col, row) + toggle() + clip_transport_action(col, row, "RecordStop", false))
|
||||
--table.insert(mappings, name("2x = Double section") + group(groups.slot_double) + feedback_disabled() + shift + double_press + slot_button(col, row) + adjust_clip_section_length_action(col, row, 2))
|
||||
--table.insert(mappings, name("1x = Halve section") + group(groups.slot_double) + feedback_disabled() + shift + single_press + slot_button(col, row) + adjust_clip_section_length_action(col, row, 0.5))
|
||||
table.insert(
|
||||
mappings,
|
||||
name("Fill slot")
|
||||
+ group(groups.slot_quantize)
|
||||
+ feedback_disabled()
|
||||
+ shift
|
||||
+ single_press
|
||||
+ slot_button(col, row)
|
||||
+ clip_management_action(col, row, "FillSlotWithSelectedItem")
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
return realearn.Compartment {
|
||||
parameters = util.sorted_by_index(params),
|
||||
groups = util.to_array(groups),
|
||||
mappings = mappings :: any,
|
||||
custom_data = {
|
||||
playtime = {
|
||||
control_unit = {
|
||||
column_count = config.column_count,
|
||||
row_count = config.row_count,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
return module
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
--- name: APC mini mk2 - Playtime
|
||||
--- realearn_version: 2.16.0-pre.8
|
||||
--- author: helgoboss
|
||||
--- device_manufacturer: Akai
|
||||
--- device_name: APC mini mk2
|
||||
--- description: |
|
||||
--- This main preset turns the APC mini mk2 into a capable device for controlling Playtime. Hold Shift
|
||||
--- to access advanced functions.
|
||||
--- used_schemes: [akai/apc-mini-mk2]
|
||||
--- required_features: [playtime]
|
||||
|
||||
--!strict
|
||||
|
||||
|
||||
local commons = require("akai/apc-lib/playtime-commons")
|
||||
|
||||
return commons.create_compartment {
|
||||
use_column_stop_buttons = true,
|
||||
stop_column_if_slot_empty = true,
|
||||
mute_track_button_id = "row3/play",
|
||||
arm_track_button_id = "row4/play",
|
||||
column_count = 8,
|
||||
row_count = 8,
|
||||
up_button_id = "col5/stop",
|
||||
down_button_id = "col6/stop",
|
||||
left_button_id = "col7/stop",
|
||||
right_button_id = "col8/stop",
|
||||
volume_button_id = "col1/stop",
|
||||
pan_button_id = "col2/stop",
|
||||
send_button_id = "col3/stop",
|
||||
device_button_id = "col4/stop",
|
||||
stop_all_clips_button_id = "row8/play",
|
||||
stop_all_clips_need_shift = true,
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
--- name: APC mini - Playtime
|
||||
--- realearn_version: 2.16.0-pre.8
|
||||
--- author: helgoboss
|
||||
--- device_manufacturer: Akai
|
||||
--- device_name: APC mini
|
||||
--- description: |
|
||||
--- This main preset turns the APC mini into a capable device for controlling Playtime. Hold Shift
|
||||
--- to access advanced functions.
|
||||
--- used_schemes: [akai/apc-mini]
|
||||
--- required_features: [playtime]
|
||||
|
||||
--!strict
|
||||
|
||||
|
||||
local commons = require("akai/apc-lib/playtime-commons")
|
||||
|
||||
return commons.create_compartment {
|
||||
use_column_stop_buttons = true,
|
||||
stop_column_if_slot_empty = true,
|
||||
mute_track_button_id = "row4/play",
|
||||
arm_track_button_id = "row3/play",
|
||||
column_count = 8,
|
||||
row_count = 8,
|
||||
up_button_id = "col1/stop",
|
||||
down_button_id = "col2/stop",
|
||||
left_button_id = "col3/stop",
|
||||
right_button_id = "col4/stop",
|
||||
volume_button_id = "col5/stop",
|
||||
pan_button_id = "col6/stop",
|
||||
send_button_id = "col7/stop",
|
||||
device_button_id = "col8/stop",
|
||||
stop_all_clips_button_id = "row8/play",
|
||||
stop_all_clips_need_shift = true,
|
||||
}
|
||||
Reference in New Issue
Block a user