ReaScripts (скрипты для Reaper) - делимся

@Денис Фет, все вами описанное можно реализовать =) скажу сразу - скрипты писать не умею, но я вышел в интернет с этим вопросом, полчасика попинал ИИ и он, надо сказать, довольно неплохо справился =)
Проблема только в том, что я не знаю ваших задач и привычек - а надо ли вам называть регион при создании? А надо ли выбирать цвет или у вас настроена автопокраска и достаточно только назвать?; а курсор после создания региона надо в конец созданного региона перебросить и т.д., и т.д. =)
Вы можете или сами сделать то же самое, что и я - т.е. пойти путем любого доступного вам ИИ, либо максимально детально уточните ТЗ: жму кнопку на тулбаре со скриптом и хочу, чтоб от курсора вправо создался регион рандомного цвета, длиной 10 сек, без названия.
Или наоборот: надо чтоб после запуска скрипта предложило ввести название и отрыло палитру для покраски региона =)
И тогда я скину вам то, что у меня получилось с учетом пожеланий =)
 
  • Like
Реакции: Antonio
Друзья, а как можно скриптом создавать регионы нужной мне длительности? Ну например хотелось бы вывести кнопки на панель для создания региона длительностью 6 сек, 15 сек, и с возможностью свободного выбора длительности. Так же хотелось бы иметь какую-то возможность автоматизированно редактировать длительность уже существующих в проекте регионов.
Возможное частичное решение одной из ваших задач:

Одиночный регион заданной длины недолго сделать, создав произвольный регион и задав ему нужную длину в табличке "edit region". А дальше копируем его через ctrl-alt-leftclick-drag - при этом копируется только "оболочка" региона (длина, цвет, имя и т. д.), содержимое не дублируется и на треках не происходит никакого движения.
 
  • Like
Реакции: LogicS
@Денис Фет, все вами описанное можно реализовать =) скажу сразу - скрипты писать не умею, но я вышел в интернет с этим вопросом, полчасика попинал ИИ и он, надо сказать, довольно неплохо справился =)
Проблема только в том, что я не знаю ваших задач и привычек - а надо ли вам называть регион при создании? А надо ли выбирать цвет или у вас настроена автопокраска и достаточно только назвать?; а курсор после создания региона надо в конец созданного региона перебросить и т.д., и т.д. =)
Вы можете или сами сделать то же самое, что и я - т.е. пойти путем любого доступного вам ИИ, либо максимально детально уточните ТЗ: жму кнопку на тулбаре со скриптом и хочу, чтоб от курсора вправо создался регион рандомного цвета, длиной 10 сек, без названия.
Или наоборот: надо чтоб после запуска скрипта предложило ввести название и отрыло палитру для покраски региона =)
И тогда я скину вам то, что у меня получилось с учетом пожеланий =)

А понял. Буду пробовать.
 
@Денис Фет, тогда держите мои наброски- прикрепил архивом к посту, может пригодится ;)
Внутри 6 скриптов, краткое описание:
Главное преимущество этих инструментов в том, что они не просто создают регионы,
а раздвигают проект (insert space), чтобы новые блоки не накладывались на старые.

1. Region 10s (Auto Color)
ЧТО ДЕЛАЕТ: Мгновенно создает регион длиной 10 секунд от позиции курсора. Проект раздвигается на 10 секунд вправо. Цвет выбирается случайно, название не запрашивается.
КАК ИЗМЕНИТЬ ДЛИНУ: Найди строку "local region_len = 10.0".
Просто поменяй 10.0 на 15.0, и скрипт всегда будет создавать 15 секунд.

2. Region 10s (Name + Auto Color)
ЧТО ДЕЛАЕТ: То же самое, что и первый, но перед созданием выскочит окошко: "Enter Name". Цвет будет случайным.
КАК ИЗМЕНИТЬ ДЛИНУ: Аналогично - меняй "local region_len = 10.0" в начале кода.
КНОПКА CANCEL: Если нажать Esc или Cancel в окне ввода имени, скрипт просто ничего не сделает.

3. Region 10s (Name + Palette)
ЧТО ДЕЛАЕТ: Для работы с фиксированными блоками (например, шоты по 10 сек). Длину не спрашивает, только Имя + Палитра.
КАК ИЗМЕНИТЬ ДЛИНУ: Строка "local region_len = 10.0".
ПРО ПАЛИТРУ: Тут тоже работает правило: не хочешь выбирать цвет - жми Esc, и сработает рандом.

4. Region Custom (Length + Name + Auto Color)
ЧТО ДЕЛАЕТ: Спрашивает длину и имя, но цвет всегда выбирает сам (рандом).
УДОБСТВО: Подходит для быстрой разметки блоков, когда выбор цвета не важен.

5. Region Custom (Length + Name + Palette)
ЧТО ДЕЛАЕТ: Самый гибкий. Сначала спрашивает длину и имя, а затем сразу открывает палитру цветов.
ПРО ПАЛИТРУ: Если нажать Esc или Cancel в окне палитры -скрипт не прервется, а назначит РАНДОМНЫЙ цвет, чтобы не оставлять регион серым.
ПО УМОЛЧАНИЮ: В коде стоит default_len = "10.0". Если хочешь другие цифры в окошке при запуске - меняй это значение.

6. Region Resize (Smart Shift)
ЧТО ДЕЛАЕТ: Поставь курсор ВНУТРЬ уже созданного региона и запусти его. Он увидит текущую длину и спросит новую.
МАГИЯ:
- Если увеличишь длину (с 10 до 15) - он допишет 5 сек пустоты и раздвинет проект.
- Если уменьшишь - он "подрежет" время, подтянув остальной проект влево.
БЕЗОПАСНОСТЬ: Если курсор будет вне региона, скрипт выдаст ошибку "Place cursor inside a region!"
Чисто на всякий случай напомню- скрипты можно просто кинуть в C:\Users\UserName\AppData\Roaming\REAPER\Scripts, в самом Рипере пойти Actions => Show action list => New action => Load ReaScript и выбрать прям пачкой все нужные скрипты по теме и нажать "Открыть"
Править скрипты удобно в редакторе типа Notepad++, но можно и в обычном блокноте - переименовать в .txt, внести изменения (например, вам надо 10, 15, 20 сек. - вносите правки и сохраняете отдельно каждый вариант), сохранить и переименовать в .lua обратно
Как выносить в тулбар кнопку, думаю, знаете =)
P.S. добавил еще архив со скриптами, которые реагируют на SWS autocolor:
1) Region 10s Name + Smart Color
Описание: Создает регион фиксированной длины (10 секунд) в позиции курсора, раздвигая проект. Запрашивает только имя (Name). Цвет выбирает SWS Auto Color на основе введенного имени. Если совпадений в SWS нет, регион остается дефолтного цвета (серым).

2) Region 10s Name + Smart Color Random
Описание: Создает регион фиксированной длины (10 секунд) в позиции курсора с раздвижкой проекта. Запрашивает имя (Name). Сначала пытается применить цвет через SWS. Если имя не найдено в списке SWS, скрипт автоматически назначает случайный (Random) цвет.

3) Region Custom (Name + Smart color Default)
Описание: Универсальный скрипт, запрашивает и длину (Length), и имя (Name). Раздвигает проект на указанное время. Цвет назначается только через SWS Auto Color. Если для введенного имени нет правила, регион остается стандартного цвета (Default).

4) Region Custom (Name + Smart Color Random)
Описание: Запрашивает длину (Length) и имя (Name). Раздвигает проект и создает регион. Использует «умную» логику цвета: если SWS не покрасил регион по имени, скрипт принудительно выбирает случайный (Random) цвет.

Как изменить длительность
Чтобы изменить фиксированную длину региона, открой скрипт в редакторе и найди в самом начале блок **SETTINGS**. Измени число в следующей строке:
- Для скриптов №1 и №2:
local region_len = 10.0 -- Замени 10.0 на 20.0 или 30.0
- Для скриптов №3 и №4 (значение по умолчанию в окне ввода):
local default_len = "10.0" -- Замени "10.0" на "20.0" или "30.0"
 

Вложения

Последнее редактирование:
  • Like
Реакции: Antonio и Kokarev Maxim
@Денис Фет, то, о чем я говорил - не зная ваших задач я делал как для себя, и скрипты из предыдущего поста имеют особенность - они раздвигают проект =) т.е. если вы поставите курсор между двумя существующими регионами - скрипт создаст между ними пустое пространство от курсора вправо =)
А если вам просто надо обозначить кусок проекта ничего никуда не двигая?
Так что вот все те же скрипты, что в посте выше, только с пометкой No Offset - то же самое по поводу длины, покраски и т.д., только они просто создают регион никак не затрагивая содержимое дорожек (айтемы и другие регионы остаются на своих местах)
 

Вложения

Последнее редактирование:
  • Like
Реакции: Antonio
привет коммунити. навайбкодил тут на выходных отображалку миди айтемов в виде гитарных табов. делал для себя, но вдруг кому понадобится. аналоги есть, но вроде как платные.

screenshot.png
 
  • Like
Реакции: Antonio и truemanofan
навайбкодил (Deepseek)
Код:
-- @description Set FX routing (per-pin control)
-- @version 7.2
-- @author Andernik
--
-- ============================================================================
-- ОПИСАНИЕ
-- ============================================================================
-- Скрипт позволяет гибко настраивать маршрутизацию пинов (pin mapping)
-- для плагинов на выбранных дорожках. Вы можете задать:
--   • какие эффекты обрабатывать (первый, последний или все);
--   • количество каналов плагина (VST3 bus size);
--   • количество каналов самой дорожки;
--   • для каждого пина – на какой канал трека он должен быть направлен
--     (можно указывать комбинации каналов через "+" или отключать пин через "-").
--   • Ограничение каналов до 64 (Так как REAPER API поддерживает только 64 канала для pin mapping.)

-- Скрипт удобно использовать, создавая несколько копий с разными настройками
-- и запуская их по необходимости.
--
-- ============================================================================
-- КАК ПОЛЬЗОВАТЬСЯ
-- ============================================================================
-- 1. Выделите одну или несколько дорожек в REAPER.
-- 2. Отредактируйте настройки в блоке ниже под нужный сценарий.
-- 3. Запустите скрипт.
--
-- ============================================================================
-- ПРИМЕРЫ НАСТРОЕК
-- ============================================================================
-- Пример 1. Моно из первого канала, стерео выход (классический mono-режим):
--   mode = 2
--   VST3_BUS_SIZE = 1
--   TRACK_CHANNELS = 0
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1, 2=2"
--
-- Пример 2. Левый канал на вход, выход дублируется на каналы 1 и 2:
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1+2"
--
-- Пример 3. Sidechain на каналах 3 и 4, основные входы не трогаем:
--   HARD_RESET_PINS = 0
--   SIDECHAIN_PINS = "2=3, 3=4"
--   OUTPUT_PINS = "1=1, 2=2"
--
-- Пример 4. 6-канальный плагин: входы 1-6, выходы 1-6 (жёсткий сброс):
--   HARD_RESET_PINS = 1
--   VST3_BUS_SIZE = 6
--   TRACK_CHANNELS = 6
--   INPUT_PINS = "1=1, 2=2, 3=3, 4=4, 5=5, 6=6"
--   OUTPUT_PINS = "1=1, 2=2, 3=3, 4=4, 5=5, 6=6"
--
-- Пример 5. Все эффекты, каждый принимает моно из первого канала,
--           и выводит на первый канал:
--   mode = 3
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1"
--
-- ============================================================================

-- ============================================================
-- НАСТРОЙКИ (изменяйте здесь под каждую копию скрипта)
-- ============================================================

-- Режим выбора эффектов:
-- 1 = только первый эффект на дорожке
-- 2 = только последний эффект на дорожке
-- 3 = все эффекты на дорожке
local mode = 2

-- VST3 bus size (количество каналов плагина):
-- 0 = не менять, 1 = моно, 2 = стерео, и т.д. до 128
local VST3_BUS_SIZE = 1

-- Количество каналов дорожки (0 = не менять)
local TRACK_CHANNELS = 2

-- Жёсткий сброс всех пинов перед применением:
-- 0 = не сбрасывать (будут изменены только явно указанные пины)
-- 1 (или любое ненулевое) = сбросить все входные и выходные пины в 0 перед настройкой
local HARD_RESET_PINS = 1

-- Основные входные пины: "пин=канал, пин=канал1+канал2, пин=-"
-- Примеры:
--   "1=1"                -- пин1 на канал1
--   "1 = 1+2, 2 = 1+2"   -- пин1 на сумму 1+2, пин2 на сумму 1+2 (пробелы допустимы)
--   "1=1, 2=-"           -- пин1 на канал1, пин2 отключён
-- Если строка пустая или "0", пины не трогаются.
local INPUT_PINS = "1=1"

-- Sidechain входные пины: абсолютные номера пинов (как в окне pin connector)
-- Формат такой же, как у INPUT_PINS. Пример: "3=3,4=4" ( "0" без Sidechain)
local SIDECHAIN_PINS = "0"

-- Выходные пины: абсолютные номера пинов (начиная с 1)
-- Примеры:
--   "1=1+2"              -- пин1 на каналы 1 и 2
--   "1=1, 2=2"           -- пин1 на канал1, пин2 на канал2
local OUTPUT_PINS = "1=1+2"

-- ============================================================
-- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ (не изменять)
-- ============================================================

local function trim(s)
    return s:match("^%s*(.-)%s*$")
end

local function parseChannelMask(str)
    local mask = 0
    for token in str:gmatch("[^+]+") do
        local ch = tonumber(trim(token))
        if ch and ch >= 1 and ch <= 64 then   -- REAPER поддерживает только каналы 1-64
            mask = mask | (1 << (ch - 1))
        end
    end
    return mask
end

local function parsePinMap(str)
    if str == nil or str == "" then return nil end
    local trimmed = trim(str)
    if trimmed == "0" then return nil end  -- явное "0" означает "не трогать"
    local map = {}
    for pair in trimmed:gmatch("[^,]+") do
        local pair_trimmed = trim(pair)
        if pair_trimmed == "" then goto continue end
        local pin_str, value_str = pair_trimmed:match("^(%d+)%s*=%s*(.+)$")
        if pin_str and value_str then
            local pin = tonumber(pin_str)
            if pin and pin >= 1 and pin <= 128 then
                local val = trim(value_str)
                if val == "-" then
                    map[pin] = 0
                else
                    local mask = parseChannelMask(val)
                    if mask ~= 0 then
                        map[pin] = mask
                    end
                end
            end
        end
        ::continue::
    end
    return next(map) and map or nil
end

local function resetAllPins(track, fxidx)
    for pin = 1, 128 do
        reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, 0, 0)
        reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, 0, 0)
    end
end

local function applyInputPins(track, fxidx, map)
    if not map then return end
    for pin, mask in pairs(map) do
        -- Сначала отключаем пин, потом, если маска не ноль, устанавливаем новое значение
        reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, 0, 0)
        if mask ~= 0 then
            reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, mask, 0)
        end
    end
end

local function applyOutputPins(track, fxidx, map)
    if not map then return end
    for pin, mask in pairs(map) do
        reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, 0, 0)
        if mask ~= 0 then
            reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, mask, 0)
        end
    end
end

-- ============================================================
-- ОСНОВНАЯ ФУНКЦИЯ (обёрнута в pcall для безопасности)
-- ============================================================
local function main()
    local inputMap = parsePinMap(INPUT_PINS)
    local sidechainMap = parsePinMap(SIDECHAIN_PINS)
    local outputMap = parsePinMap(OUTPUT_PINS)

    local sel_tracks = reaper.CountSelectedTracks(0)
    if sel_tracks == 0 then return end

    reaper.Undo_BeginBlock2(0)
    local changed = false

    for i = 0, sel_tracks - 1 do
        local track = reaper.GetSelectedTrack(0, i)

        if TRACK_CHANNELS > 0 then
            reaper.SetMediaTrackInfo_Value(track, "I_NCHAN", TRACK_CHANNELS)
            changed = true
        end

        local fx_cnt = reaper.TrackFX_GetCount(track)
        if fx_cnt == 0 then
            goto continue   -- нет эффектов на дорожке
        end

        local start_idx, end_idx, step
        if mode == 1 then
            start_idx, end_idx, step = 0, 0, 1
        elseif mode == 2 then
            start_idx, end_idx, step = fx_cnt - 1, fx_cnt - 1, 1
        elseif mode == 3 then
            start_idx, end_idx, step = 0, fx_cnt - 1, 1
        else
            reaper.ShowMessageBox("Ошибка: mode должен быть 1, 2 или 3.", "Set FX routing", 0)
            reaper.Undo_EndBlock2(0, "", -1)
            return
        end

        for fxidx = start_idx, end_idx, step do
            if HARD_RESET_PINS ~= 0 then
                resetAllPins(track, fxidx)
            end

            if VST3_BUS_SIZE > 0 then
                reaper.TrackFX_SetNamedConfigParm(track, fxidx, 'channel_config', tostring(VST3_BUS_SIZE))
            end

            applyInputPins(track, fxidx, inputMap)
            applyInputPins(track, fxidx, sidechainMap)
            applyOutputPins(track, fxidx, outputMap)

            changed = true
        end

        ::continue::
    end

    if changed then
        reaper.Undo_EndBlock2(0, "Set FX routing (per-pin)", -1)
    else
        reaper.Undo_EndBlock2(0, "", -1)
    end
end

-- Защищённый запуск с гарантированным закрытием Undo блока
local ok, err = pcall(main)
if not ok then
    reaper.Undo_EndBlock2(0, "", -1)   -- закрываем блок, если он был открыт
    reaper.ShowMessageBox("Ошибка выполнения: " .. tostring(err), "Set FX routing", 0)
end
 

Вложения

Последнее редактирование:
Исправленная версия.
Код:
-- @description Set FX routing (per-pin control)
-- @version 7.3
-- @author Andernik
--
-- ============================================================================
-- ОПИСАНИЕ
-- ============================================================================
-- Скрипт позволяет гибко настраивать маршрутизацию пинов (pin mapping)
-- для плагинов на выбранных дорожках. Вы можете задать:
--   • какие эффекты обрабатывать (первый, последний или все);
--   • количество каналов плагина (VST3 bus size);
--   • количество каналов самой дорожки;
--   • для каждого пина – на какой канал трека он должен быть направлен
--     (можно указывать комбинации каналов через "+" или отключать пин через "-").
--   • Ограничение каналов до 64 (Так как REAPER API поддерживает только 64 канала для pin mapping.)
--
-- Скрипт удобно использовать, создавая несколько копий с разными настройками
-- и запуская их по необходимости.
--
-- ============================================================================
-- КАК ПОЛЬЗОВАТЬСЯ
-- ============================================================================
-- 1. Выделите одну или несколько дорожек в REAPER.
-- 2. Отредактируйте настройки в блоке ниже под нужный сценарий.
-- 3. Запустите скрипт.
--
-- ============================================================================
-- ПРИМЕРЫ НАСТРОЕК
-- ============================================================================
-- Пример 1. Моно из первого канала, стерео выход (классический mono-режим):
--   mode = 2
--   VST3_BUS_SIZE = 1
--   TRACK_CHANNELS = 0
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1, 2=2"
--
-- Пример 2. Левый канал на вход, выход дублируется на каналы 1 и 2:
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1+2"
--
-- Пример 3. Sidechain на каналах 3 и 4, основные входы не трогаем:
--   HARD_RESET_PINS = 0
--   SIDECHAIN_PINS = "2=3, 3=4"
--   OUTPUT_PINS = "1=1, 2=2"
--
-- Пример 4. 6-канальный плагин: входы 1-6, выходы 1-6 (жёсткий сброс):
--   HARD_RESET_PINS = 1
--   VST3_BUS_SIZE = 6
--   TRACK_CHANNELS = 6
--   INPUT_PINS = "1=1, 2=2, 3=3, 4=4, 5=5, 6=6"
--   OUTPUT_PINS = "1=1, 2=2, 3=3, 4=4, 5=5, 6=6"
--
-- Пример 5. Все эффекты, каждый принимает моно из первого канала,
--           и выводит на первый канал:
--   mode = 3
--   INPUT_PINS = "1=1"
--   OUTPUT_PINS = "1=1"
--
-- ============================================================================

-- ============================================================
-- НАСТРОЙКИ (изменяйте здесь под каждую копию скрипта)
-- ============================================================

-- Режим выбора эффектов:
-- 1 = только первый эффект на дорожке
-- 2 = только последний эффект на дорожке
-- 3 = все эффекты на дорожке
local mode = 2

-- VST3 bus size (количество каналов плагина):
-- 0 = не менять, 1 = моно, 2 = стерео, и т.д. до 128
local VST3_BUS_SIZE = 1

-- Количество каналов дорожки (0 = не менять)
local TRACK_CHANNELS = 2

-- Жёсткий сброс всех пинов перед применением:
-- 0 = не сбрасывать (будут изменены только явно указанные пины)
-- 1 (или любое ненулевое) = сбросить все входные и выходные пины в 0 перед настройкой
local HARD_RESET_PINS = 1

-- Основные входные пины: "пин=канал, пин=канал1+канал2, пин=-"
-- Примеры:
--   "1=1"                -- пин1 на канал1
--   "1 = 1+2, 2 = 1+2"   -- пин1 на сумму 1+2, пин2 на сумму 1+2 (пробелы допустимы)
--   "1=1, 2=-"           -- пин1 на канал1, пин2 отключён
-- Если строка пустая или "0", пины не трогаются.
local INPUT_PINS = "1=1"

-- Sidechain входные пины: абсолютные номера пинов (как в окне pin connector)
-- Формат такой же, как у INPUT_PINS. Пример: "3=3,4=4" ( "0" без Sidechain)
-- ВНИМАНИЕ: если в SIDECHAIN_PINS указаны те же пины, что и в INPUT_PINS,
--           они будут применены после INPUT_PINS и перезапишут их.
local SIDECHAIN_PINS = "0"

-- Выходные пины: абсолютные номера пинов (начиная с 1)
-- Примеры:
--   "1=1+2"              -- пин1 на каналы 1 и 2
--   "1=1, 2=2"           -- пин1 на канал1, пин2 на канал2
local OUTPUT_PINS = "1=1+2"

-- ============================================================
-- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ (не изменять)
-- ============================================================

local function trim(s)
    return s:match("^%s*(.-)%s*$")
end

local function parseChannelMask(str)
    local mask = 0
    for token in str:gmatch("[^+]+") do
        local ch = tonumber(trim(token))
        if ch and ch >= 1 and ch <= 64 then   -- REAPER поддерживает только каналы 1-64
            mask = mask | (1 << (ch - 1))
        end
    end
    return mask
end

local function parsePinMap(str)
    if str == nil or str == "" then return nil end
    local trimmed = trim(str)
    if trimmed == "0" then return nil end  -- явное "0" означает "не трогать"
    local map = {}
    for pair in trimmed:gmatch("[^,]+") do
        local pair_trimmed = trim(pair)
        if pair_trimmed == "" then goto continue end
        local pin_str, value_str = pair_trimmed:match("^(%d+)%s*=%s*(.+)$")
        if pin_str and value_str then
            local pin = tonumber(pin_str)
            if pin and pin >= 1 and pin <= 128 then
                local val = trim(value_str)
                if val == "-" then
                    map[pin] = 0
                else
                    local mask = parseChannelMask(val)
                    if mask ~= 0 then
                        map[pin] = mask
                    end
                end
            end
        end
        ::continue::
    end
    return next(map) and map or nil
end

local function resetAllPins(track, fxidx)
    for pin = 1, 128 do
        reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, 0, 0)
        reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, 0, 0)
    end
end

local function applyInputPins(track, fxidx, map)
    if not map then return end
    for pin, mask in pairs(map) do
        -- Сначала отключаем пин, потом, если маска не ноль, устанавливаем новое значение
        reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, 0, 0)
        if mask ~= 0 then
            reaper.TrackFX_SetPinMappings(track, fxidx, 0, pin - 1, mask, 0)
        end
    end
end

local function applyOutputPins(track, fxidx, map)
    if not map then return end
    for pin, mask in pairs(map) do
        reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, 0, 0)
        if mask ~= 0 then
            reaper.TrackFX_SetPinMappings(track, fxidx, 1, pin - 1, mask, 0)
        end
    end
end

-- ============================================================
-- ОСНОВНАЯ ФУНКЦИЯ
-- ============================================================
local function main()
    local inputMap = parsePinMap(INPUT_PINS)
    local sidechainMap = parsePinMap(SIDECHAIN_PINS)
    local outputMap = parsePinMap(OUTPUT_PINS)

    local sel_tracks = reaper.CountSelectedTracks(0)
    if sel_tracks == 0 then return end

    -- Проверка корректности режима
    if mode ~= 1 and mode ~= 2 and mode ~= 3 then
        reaper.ShowMessageBox("Ошибка: mode должен быть 1, 2 или 3.", "Set FX routing", 0)
        return
    end

    -- Начинаем блок отмены только после всех проверок
    reaper.Undo_BeginBlock2(0)
    local changed = false

    for i = 0, sel_tracks - 1 do
        local track = reaper.GetSelectedTrack(0, i)

        if TRACK_CHANNELS > 0 then
            reaper.SetMediaTrackInfo_Value(track, "I_NCHAN", TRACK_CHANNELS)
            changed = true
        end

        local fx_cnt = reaper.TrackFX_GetCount(track)
        if fx_cnt == 0 then
            goto continue   -- нет эффектов на дорожке
        end

        local start_idx, end_idx, step
        if mode == 1 then
            start_idx, end_idx, step = 0, 0, 1
        elseif mode == 2 then
            start_idx, end_idx, step = fx_cnt - 1, fx_cnt - 1, 1
        else -- mode == 3
            start_idx, end_idx, step = 0, fx_cnt - 1, 1
        end

        for fxidx = start_idx, end_idx, step do
            if HARD_RESET_PINS ~= 0 then
                resetAllPins(track, fxidx)
            end

            if VST3_BUS_SIZE > 0 then
                reaper.TrackFX_SetNamedConfigParm(track, fxidx, 'channel_config', tostring(VST3_BUS_SIZE))
            end

            applyInputPins(track, fxidx, inputMap)
            applyInputPins(track, fxidx, sidechainMap)
            applyOutputPins(track, fxidx, outputMap)

            changed = true
        end

        ::continue::
    end

    if changed then
        reaper.Undo_EndBlock2(0, "Set FX routing (per-pin)", -1)
    else
        reaper.Undo_EndBlock2(0, "", -1)
    end
end

-- Защищённый запуск с гарантированным закрытием Undo блока
local ok, err = pcall(main)
if not ok then
    reaper.Undo_EndBlock2(0, "", -1)   -- закрываем блок, если он был открыт
    reaper.ShowMessageBox("Ошибка выполнения: " .. tostring(err), "Set FX routing", 0)
end
 

Вложения

  • Like
Реакции: Antonio и Nagor

Сейчас просматривают