Помогите создать экшн / кастом экшн / скрипт (3 онлайн)

igor13r

New Member
8 Ноя 2013
22
1
3
saransk
@diggidon, качнул весь reapack me2beats и оттуда выбрал скрипт, всё получилось )
спасибо )..... а вот к примеру с айтемами такое можно сделать ? Айтемы тоже на разных треках
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.063
113
62
Киев
@CerberPic, так если кто-то не прислушивается к базовым советам и использует кирилицу - флаг ему в руки, у него не только со скриптами проблемы будут.
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.063
113
62
Киев
Поскольку TrackFX_GetInstrument() возвращает индекс первого инструмента, а инструментов может быть несколько, то можно использовать что-то в духе
PHP:
  function IsInstrument(track, fx) return ({reaper.TrackFX_GetFXName( track, fx, '' )})[2]:match('[%u]+i%:')~= nil end

  tr = reaper.GetSelectedTrack(0,0)
  is_FX_instrument = IsInstrument(tr,0)
Михаил, не обычный синтаксис.
Вот это вот выражение -
PHP:
({reaper.TrackFX_GetFXName( track, fx, '' )})[2]
это получение значения второй переменной в таблице значений функции reaper.TrackFX_GetFXName?
Не встречал раньше. Интересно.
 

CerberPic

Member
17 Фев 2017
70
22
8
35
Потестите что получилось. Скрипт Smart freeze/unfreeze track with deleting source files. Работает пока только с одним выделенным треком и некириллическими путями. С кириллическими тоже в целом работает, но не выполняет главную функцию - удаление фризов с диска.
При заморозке скрипт попросит ввести желаемое кол-во каналов (1 - моно, 2 - стерео, 3 - многоканальный)
При запуске для зафриженного трека спросит, разморозить ли его. При выборе "Нет" будет произведена повторная заморозка.
Возможны баги. Замечания по синтаксису тоже приветствуются.
PHP:
local types = {"WAVE", "MIDI", "MP3", "FLAC", "VIDEO", "VORBIS", "WMA", "OPUS", "APE", "CLICK", "REX", "RPP"}
local track = reaper.GetSelectedTrack(0, 0)
local track_chunk, source, wave
local exist = {}
local input_msg = 'Specify the number of channels:'
local err_msg = 'Something went wrong'
local nf_msg = 'One or more source file(s) was not found. Do you want unfreeze the track anyway?'
local unfrz_msg = [[
Unfreeze track and delete freezed files from disc?
(Press "No" if you want to freeze track once more)
]]

    ---------------------------------------------------
function eugen27771_GetTrackStateChunk(track)
    local fast_str = reaper.SNM_CreateFastString("")
    if reaper.SNM_GetSetObjectState(track, fast_str, false, false) then
        track_chunk = reaper.SNM_GetFastString(fast_str)
    end
    reaper.SNM_DeleteFastString(fast_str)
    return track_chunk
end
    ---------------------------------------------------
function get_sources()
    local t = {}
    track_chunk = eugen27771_GetTrackStateChunk(track)
    local ch_open, ch_cnt, it_id = false, 0, 0
    for line in track_chunk:gmatch('[^\n\r]+') do
        if line:match('<FREEZE') then ch_open = true end
        if ch_open and line:match('<ITEM') then it_id = it_id + 1 end
        if ch_cnt > 0 then
            if not t[it_id] then t[it_id] = {} end
            t[it_id][#t[it_id]+1] = line
        end
        if ch_open and line:match('<') then ch_cnt = ch_cnt + 1 end
        if ch_open and line:match('>') then ch_cnt = ch_cnt - 1 end
        if ch_open and ch_cnt < 1 then break end
    end
    local sources = t
    for key in pairs(sources) do
        local ch = table.concat(sources[key], '\n')
        source = tostring(ch:match('<SOURCE %w+')):sub(9)
        if source == "" then source = "EMPTY" end
        if source ~= "MIDI" and source ~= "LTC" and source ~= "EMPTY" then
            local filename = tostring(ch:match('FILE %C+')):sub(7)
            filename = filename:gsub('"%s*%d*', "")
            local file_exists = reaper.file_exists(filename)
            if source == "CLICK" then file_exists = true end
            table.insert(exist, tostring(file_exists))
            wave = 1
        end
        if source == "MIDI" then wave = 1 end
    end
end
    ---------------------------------------------------
function frz()
    local t = {}
    for i = 0, reaper.CountTrackMediaItems(track) - 1 do
        local item = reaper.GetTrackMediaItem(track, i)
        local take = reaper.GetActiveTake(item)
        if take then
            local src = reaper.GetMediaItemTake_Source(take)
            source = reaper.GetMediaSourceType(src, "")
            if source == "RPP_PROJECT" then source = "RPP" end
        else
            source = "EMPTY"
        end
        table.insert(t, source)
    end
    local c = table.concat(types)
    for key, val in pairs(t) do
        local finds = c:find(val)
        if finds then wave = 1 break end
    end
    if not wave then return end
    local retval, chan = reaper.GetUserInputs("Channels", 1, input_msg, '')
    chan = tonumber(chan)
    if chan == 1 then
        reaper.Main_OnCommand(40901, 0) -- freeze to mono
    elseif chan == 2 then
        reaper.Main_OnCommand(41223, 0) -- freeze to stereo
    elseif chan == 3 then
        reaper.Main_OnCommand(40877, 0) -- freeze to multichannel
    else
        return
    end
end
    ---------------------------------------------------
function Ident(bool)
    local t = {}
    local ident
    for line in track_chunk:gmatch('[^\n\r]+') do
        fr = line:match('FREEZE %d.+')
        if fr then table.insert(t, fr) end
    end
    local item_count = reaper.CountTrackMediaItems(track)
    for k = #t - item_count, #t - 1 do
        local pos_len = t[k+1]:match('%d.+%s'):gsub(" ", "$")
        pos_len = pos_len:sub(1, #pos_len - 1)
        local pos = pos_len:match('(.*($))')
        pos = ('%.4f'):format(pos:sub(1, #pos - 1))
        local len = pos_len:match('(($).*)')
        len = ('%.4f'):format(len:sub(2))
        local item = reaper.GetTrackMediaItem(track, k - #t + item_count)
        local it_pos = ('%.4f'):format(reaper.GetMediaItemInfo_Value(item, "D_POSITION"))
        local it_len = ('%.4f'):format(reaper.GetMediaItemInfo_Value(item, "D_LENGTH"))
        if tonumber(pos) == tonumber(it_pos) and tonumber(len) == tonumber(it_len) then
            ident = true
        else
            ident = false
            reaper.MB(err_msg, "Error", 0)
            return
        end
    end
    return ident
end

function unfrz()
    reaper.PreventUIRefresh(-1)
    reaper.SelectAllMediaItems(0, 0)
    for i = 0, reaper.CountTrackMediaItems(track) - 1 do
        local item = reaper.GetTrackMediaItem(track, i)
        reaper.SetMediaItemSelected(item, 1)
        reaper.Main_OnCommand(40440, 0) -- set offline
    end
    local con = table.concat(exist)
    local not_found = tostring(con):find("false")
    if not_found and source ~= "RPP" then
        local dialog = reaper.MB(nf_msg, "Warning", 4)
        if dialog == 6 then
            reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_DELTAKEANDFILE2"), 0)
            reaper.Main_OnCommand(41644, 0) -- unfreeze
        else
            reaper.SelectAllMediaItems(0, 0)
        end
    else
        reaper.Main_OnCommand(reaper.NamedCommandLookup("_S&M_DELTAKEANDFILE2"), 0)
        reaper.Main_OnCommand(41644, 0) -- unfreeze
    end
    reaper.PreventUIRefresh(1)
end
    ---------------------------------------------------
function Main()
    local sel_track = reaper.CountSelectedTracks(0)
    if sel_track ~= 1 then return end
    local freeze = reaper.BR_GetMediaTrackFreezeCount(track)
    if freeze ~= 0 then
        get_sources()
        if wave == 1 then
            local dialog = reaper.MB(unfrz_msg, "Unfreeze", 3)
            if dialog == 6 then
                Ident(bool)
                unfrz()
            elseif dialog == 7 then
                frz()
            end
        else
            reaper.Main_OnCommand(41644, 0) -- unfreeze
        end
    else
        frz()
    end
end

Main()
Выражаю благодарность @@Michael за помощь и подсказки.
 
Последнее редактирование:
  • Like
Реакции: Buyan и Maestro Sound

Maestro Sound

Active Member
1 Ноя 2007
721
86
28
@CerberPic, ЗДОРОВО. Мое видение, лучше убрать все всплывающие запросы сделать три варианта моно/стерео/multi (редко фризиться в моно, в основном Vsti в стерео). На выход из фриза убрать запрос на повторный фриз он незачем. (Проще нажал скрипт, если трек не зафризен - то зафризеть его, а если зафризен разфризеть) Операции с зафризеным треком, лучше не производить кроме как добавления в FX нового плагина и то в исключительных мерах).При разморозке копировать добавленные Fxсы, и добавлять их в цепочку размороженного. Работа с несколькими выделенными тоже желательна но там Александр Олейник говорил есть заминка (типа что не успевает разморозка за скоростью роботы скрипта ---не помню точно)
 
Последнее редактирование:

CerberPic

Member
17 Фев 2017
70
22
8
35
Мое видение, лучше убрать все всплывающие запросы сделать три варианта моно/стерео/multi (редко фризиться в моно, в основном Vsti в стерео).
Сделаю отдельную версию. Лично я частенько фрижу в моно определённые треки.
На выход из фриза убрать запрос на повторный фриз он незачем. (Проще нажал скрипт, если трек не зафризен - то зафризеть его, а если зафризен разфризеть)
Это, конечно, многое упрощает. Но многократная заморозка - это одна из главных фишек риперовского фриза и может быть очень полезной на слабых машинах. Поэтому я предусмотрел и такой вариант. В принципе, чем он мешает? Захотели расфризить - жмите "да", если передумали - "отмена". Конечно, кнопка "нет" может ввести в заблуждение, особенно если работать в спешке и не читать сообщение в диалоге.
Операции с зафризеным треком, лучше не производить кроме как добавления в FX нового плагина и то в исключительных мерах).При разморозке копировать добавленные Fxсы, и добавлять их в цепочку размороженного.
Они при разморозке же вроде бы и так никуда не деваются.

По поводу работы с несколькими треками - я пока не знаю, как это реализовать. Если и возможно, то только последовательно, поскольку проверка исходников и сама разморозка происходит в цикле на один трек.
 
Последнее редактирование:
  • Like
Реакции: Maestro Sound

Maestro Sound

Active Member
1 Ноя 2007
721
86
28
Они при разморозке же вроде бы и так никуда не деваются.
Да протупил

Но многократная заморозка - это одна из главных фишек риперовского фриза и может быть очень полезной на слабых машинах
Да протестил и действительно прикольно. Но все же ходелось бы резные варианты МultiFreeze (с запросами) и SingleFreez (робота в два клика) А так Браво!!!!!!!!!!
 

Maestro Sound

Active Member
1 Ноя 2007
721
86
28
@CerberPic, Спасибо Замечательно. Я сделал себе 4 варианта
Вот еще бы к Вашей коллекции smart freez-unfreez Vsti Instrument (only)...........
 
Последнее редактирование:

Death Buster

Member
28 Сен 2012
70
6
8
35
Санкт-Петербург
vk.com
Ищу скрипт, который поместит Edit cursor в конец Time Selection или в конец лупа.

Так же быть может кто то встречал экшн, который притянет Edit Cursor к ближайшей Grid Line, если курсор стоит не на ней. Но если курсор стоит четко на Grid Line, то экшн его не двигает.
 

belovw

Well-Known Member
22 Апр 2009
9.201
8.384
113
50
RK Almaty
Ищу скрипт, который поместит Edit cursor в конец Time Selection или в конец лупа.
action: Go to end of time selection
action: Go to end of loop
_____________________

экшн, который притянет Edit Cursor к ближайшей Grid Line
script by me2beats: Move cursor to nearest grid division
_____________________

Поиском бьётся за 10 минут. С вас Коньяк. ))
 

Death Buster

Member
28 Сен 2012
70
6
8
35
Санкт-Петербург
vk.com
action: Go to end of time selection
action: Go to end of loop
Экшены типа "Go to" перебрасывают play cursor и при использовании кастом экшна, в котором присутствует такое действие проигрывание трека скачет туда-сюда, что вовсе не желательно в моем случае(

Есть Script: me2beats_Move cursor to start of loop.lua
он работает как нужно, но нет такого же, чтобы перемещал в конец!(

Может кто подскажет, как можно скорректировать существующий вышеупомянутый скрипт?
 

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
@CerberPic, Я вот тоже озадачился проблемой фризинга, интересная тема.

Опишите детально пожалуйста, что делает ваш скрипт, в чем его особенность?

В общем неплохо было-бы собрать и систематизировать все желаемые задачи, которые ожидаются от фризинга пользователями, потом поэтапно попробовать реализовать какое-то универсальное решение.

работает, но не выполняет главную функцию - удаление фризов с диска.
Я скрипты в рипер изучаю недавно, мало понимаю, но предыдущий опыт подсказывает, что должно быть какое-то простое и оригинальное решение. Например, в lua вроде есть возможность выполнять внешние приложения, точно не знаю работает-ли это в окружении рипера. Если да, т с файлами можно делать все что угодно посредством командной строки. Но важно понимать на каком этапе возникают проблемы с кириллицей. Если есть возможность запустить например внешний батник, то ему можно передать имена в бинарном виде, а там преобразовать их и произвести необходимые операции. Ну в общем ход мыслей ясен...
 
Последнее редактирование:

Слава

Member
22 Ноя 2006
98
23
8
Так, пресеты-таки. По крайней мере для обучения - вещь невероятная.
Сами настройки очень близки к ReaComp, поэтому я прикинул, что их можно на ReaComp и выставить спец. кнопочкой.
Мне нравится.
Посмотреть вложение 139744
А мне они (пресеты) и не только для обучения пригодятся. Да и не только мне, полагаю :)
 

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
Вопрос знающим людям. Использую данные экшены:
SWS/BR: Move closest grid line to mouse cursor (perform until shortcut released)
SWS/BR: Move closest measure grid line to mouse cursor (perform until shortcut released)
SWS/BR: Move closest tempo marker to mouse cursor (perform until shortcut released)

Но они некорректно работают если маркеры имеют свойство Gradually transition tempo to next marker.
Возможно-ли с помощью скриптов воссоздать аналогичные этим экшенам действия?
Если да, то подскажите пожалуйста в какую сторону копать. Я пока не нашел API для позиций темпо-маркеров.
 

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
@Aleksandr Oleynik, Спасибо! А я искал по запросу TempoMarker и ничего.
Правда алгоритм вырисовывается не для начального уровня, с позицией мыши работать придется. Боюсь, что так сходу может оказаться и не по зубам мне такая задача. Хотя с другой стороны вопрос наболевший, да и начинать как-то нужно, с чего-то интересного, учится решать наболевшие проблемы)
 

CerberPic

Member
17 Фев 2017
70
22
8
35
С Folder треками не работает
Да, фолдеры-то я не учёл. Теперь всё должно работать (обе версии во вложении).

Опишите детально пожалуйста, что делает ваш скрипт, в чем его особенность?
Ну, значит, первая, оригинальная версия делает следующее:
  • При запуске скрипта проверяет, зафрижен трек или нет. Если нет, то выдаёт запрос на желаемое количество каналов. Для моно фриза нужно ввести 1, для стерео - 2 и для многоканального - 3.
  • При запуске для зафриженного трека спрашивает, хотите ли вы разморозить его. Если не хотите размораживать, а хотите заморозить повторно, нужно нажать "Нет". Если передумали вообще что-либо делать, жмите "Отмена". При разморозке файлы фриза с диска удаляются в корзину.
  • Если исходник был удалён или переименован, рипер оповестит об этом при загрузке проекта. Но если один из исходников каким-то образом потерялся во время работы (до закрытия проекта), скрипт при запуске сообщит об этом. (Этот момент не очень корректно отрабатывается при многократном фризе - скрипт ссылается только на первоначальный исходник).
Вторая версия (та, что no dialog, stereo only) сделана по просьбе @Maestro Sound и работает попеременно - фриз/анфриз. Повторная заморозка не происходит, фризятся треки в стерео. Никаких запросов не выдаётся, это более быстрый вариант.
Я скрипты в рипер изучаю недавно, мало понимаю, но предыдущий опыт подсказывает, что должно быть какое-то простое и оригинальное решение. Например, в lua вроде есть возможность выполнять внешние приложения, точно не знаю работает-ли это в окружении рипера. Если да, т с файлами можно делать все что угодно посредством командной строки.
Я говорил на эту тему с Михаилом. Он сказал, что удалять при помощи экшна от SWS предпочтительнее, чем командной строкой. Хотя бы потому что там учтены все варианты - вывод в оффлайн, удаление в корзину... Я пробовал оба метода, проблемы с кириллицей возникают в обоих случаях, SWS при этом ещё выдаёт уведомление о том, что файл не был удалён. Вообще работа с консолью посредством lua в рипере организована как-то кривовато, как мне показалось.
Если есть возможность запустить например внешний батник, то ему можно передать имена в бинарном виде, а там преобразовать их и произвести необходимые операции
Внешний батник - отдельный исполняемый процесс, отдельный файл, который нужно будет скачивать пользователю для того, чтобы опробовать скрипт, класть в определённую директорию... И неизвестно, к каким дополнительным траблам может привести такой метод. Вопрос: зачем всё это, если можно просто избегать кириллицы в путях?
 

Вложения

Последнее редактирование:
  • Like
Реакции: Maestro Sound

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
@CerberPic, Спасибо за описание. Интересно.

Внешний батник - отдельный исполняемый процесс, отдельный файл, который нужно будет скачивать пользователю для того, чтобы опробовать скрипт, класть в определенную директорию...
В разумных пределах все может вмещаться в одну командную строку. При необходимости все дополнительные файлы генерируются скриптом и им-же удаляются.

И неизвестно, к каким дополнительным траблам может привести такой метод.
Как минимум работать будет только на Windows, а это уже немаленькое ограничение.

Вопрос: зачем всё это, если можно просто избегать кириллицы в путях?
Еще со времен MS-DOS привык избегать пробелов и кириллицы)
 
  • Like
Реакции: CerberPic

Maestro Sound

Active Member
1 Ноя 2007
721
86
28
Подскажите пожалуйста API для перемещения выделенного трека на последний по списку
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.063
113
62
Киев
Нет такого.
На перемещение треков, FX-ов нет ни API ни Экшинов ни стандартных команд.
 

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
Начинайте, помогу.
Спасибо! Уже начал осваивать потихоньку. Закончил эксперименты с курсором, перехожу к маркерам.
К стати вопрос мучающий меня с самого начала - Скрипт должен работать циклически пока нажата клавиша. Имеется-ли такая возможность, опрашивать состояние какой-либо клавиши? Хотя нет, неудобно... Как принято реализовывать подобного рода вещи?
Сейчас я по удержанию назначенной клавиши получаю позицию мыши, просто посредством многократного запуска скрипта. Чего в принципе может оказаться и достаточно для данного рода задачи.

Ух... страшно. Все те административные скрипты, которые я когда-либо писал, детский сад по сравнению с этим. Никогда не доводилось работать с мышкой, позициями, интерфейсами и прочем. Но при этом до ужаса интересно.
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.063
113
62
Киев
@Buyan, опишите подробнее что должен скрипт делать.
В общих чертах есть два типпа скриптов - разово срабатывающих и с дефером.
Те, что разово срабатывают, они просто что-то делают в зависимости от конкретной ситуации при их срабатывании - т.е. - опрасили Рипер по нужным параметрам и в зависимости от их состояния что-то сделали.
С дефером - работает либо пока его не остановит пользователь, либо пока не наступит какое то событие.
Ну вот собственно работающий скрипт и ждет всяких событий и на них реагирует.
[DOUBLEPOST=1513152770][/DOUBLEPOST]
Приехали!!!....... а говорили что скриптом все можно:)
Можно. Вы же не об этом спросили, а об API.
API такого нет, но это не значит что само действие нельзя сделать.
 

Buyan

Member
19 Апр 2016
137
24
18
40
Белая Церковь
опишите подробнее что должен скрипт делать.
Я выше приводил пример какие экшены мне нужно заменить скриптом. Подробно, сам пока не понимаю до конца алгоритма. прежде чем составлять алгоритм, нужно знать возможности среды в которой предполагается реализация. В моем случае изучение данной среды происходит параллельно с разработкой алгоритма. Учусь на предмете, так-сказать.
Но если кратко, то скрипт должен менять позицию ближайшей к курсору линии сетки, создавать там темпо-маркер, перемещать его в зависимости от позиции курсора, не изменяя при этом позиции соседних маркеров. Пока я предполагаю, что требуемую операцию вполне возможно решить за один проход(один запуск скрипта), а требуемую процедуру (последовательность операций), можно осуществить многократным запуском скрипта при удержании клавиши.
В общих чертах есть два типпа скриптов - разово срабатывающих и с дефером.
Про дефер интересно.
С дефером - работает либо пока его не остановит пользователь
Как происходит механизм остановки скрипта пользователем? Как это событие определяется в скрипте? Скрипт-же не принимает параметры, что-бы создавать разные кнопки с командами запуска-остановки например. Предполагаю, что останавливать можно по событию повторного запуска. Или есть механизм принудительной остановки скрипта из вне в рипере?
[DOUBLEPOST=1513154310][/DOUBLEPOST]@Aleksandr Oleynik, Спасибо!
 

Maestro Sound

Active Member
1 Ноя 2007
721
86
28
@Aleksandr Oleynik, По Вашему скрипту Bypass Fx (Vsti)

в строке reaper.TrackFX_SetEnabled(track, i-1, 1 ) -- Unbypass FX
reaper.TrackFX_SetEnabled(track, i-1, 0 ) -- Bypass FX
мне нужно поменять что бы удалял Vsti какой сюда Api вставить?
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.063
113
62
Киев
Как происходит механизм остановки скрипта пользователем?
Очень просто - ещё раз "запускаете" скрипт или нажимаете его кнопку на тулбаре.
Один раз клацнули по скрипту - он работает, второй - он перестал работать. Для визуального подтверждения того, что скрипт работает - сделали "светящуюся" во время работы кнопку (програмно сделали).
[DOUBLEPOST=1513158308][/DOUBLEPOST]
в строке
reaper.TrackFX_SetEnabled(track, i-1, 1 ) -- Unbypass FX
reaper.TrackFX_SetEnabled(track, i-1, 0 ) -- Bypass FX
мне нужно поменять что бы удалял Vsti какой сюда Api вставить?
Так это не работает - нужно менять условия - т.е. синтаксис.

И, кстати, ни разу не искал удаление - похоже и нет, нужно подумать
Через чанк нужно удалять
 
Последнее редактирование:
  • Like
Реакции: Buyan

Сейчас онлайн (Пользователей: 0, Гостей: 3)