ReaScripts (скрипты для Reaper) - обсуждение (3 онлайн)

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Я вообще ни разу не программист, и полгода назад любой скрипт представлял собой набор бессмысленных символов.
Значит у тебя просто мозги более заточены под все эти коды :)
Я могу большую часть всего этого понять и освоить (не всё, увы), но только на работающих примерах...... :(

Насколько мне известно, только перебор + GetSetMediaTrackInfo_String.
Я не очень представляю логику действия программы при исполнении "прямого обращения". Вот с id понятно, есть набор индексов, к ним можно обращаться быстро. А к каждому индексу привязана куча всего. Если ещё и для каждого параметра внутри индекса держать отдельную ячейку памяти для "быстрого обращения", рипер явно не был бы столь шустрым.
Могу ошибаться, но выход вижу Очень простой (как компромис) - через ini файлы, которые и так очень много чего в Рипере задают при его старте.
При сохранении проекта и при его старте - писать таблицу соответствия id и имён и считывать её.
Но сейчас этого нет, а в SWS ReaConsole функция - s "имя трека" прекрасно и очень быстро работает. Больше того, работает и "*имя трека *" - выделяя все треки в которых есть часть между **.
Я сделал одинаковый функционал с участием Имени Трека в EEL и церез Cycle Action с использованием в нём команд Console - EEL при своём срабатывании вызывает треск в Аудио канале, Cycle Action работает молниеносно и без малейших артефактов.
С TrackFX и TrackEnvelope сделано исключительно для удобства, мне кажется (ну и вряд ли найдутся два параметра или огибающих с одинаковыми именами для одного трека),
Очень даже возможно, по скольку у одних и тех-же типов плагов имена параметров бывают одни и те-же.
хотя где-то глубоко в коде рипера они так и работают перебором+сравнением, полагаю.
Возможно, но возможно он в будущем сможет делать как я выше написал - при сохранении проекта создавать таблицу соответствия id и имён и при его последующем открытии обращаться прямо к ней.
Кстати, а как работает Snapshots SWS-ный? Думаю, что где-то так-же, по скольку куда бы я не переместил трек, как бы я его не переименовывал - а Snapshots его моментально находит и возвращает ему запомненные параметры, а это значит он к нему обращается не по номеру трека!
[DOUBLEPOST=1434104839,1434094305][/DOUBLEPOST]PS: Кстати, про Snapshots SWS-ный - он явно использует в качестве индификатора не номер трека и не его имя, а что-то третье!
Значит можно?

И после сохранения проекта и закрытия-открытия Рипера и проекта - ни чего не теряется!
 
Последнее редактирование:

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
GUID - {32-значный уникальный номер в таких скобочках}.
Сейчас как раз пишу скрипт для Коли Ефремова, где в качестве вспомогательной операции нужен экшн, запоминающий/восстанавливающий выбранные итемы/треки. Там всё через guid итемов и треков (в SWS есть только Save/Restore Selected track(s) selected item(s) - запоминает/восстанавливает выборку итемов только на выбранных треках).
 
Последнее редактирование:

EUGEN27771

Well-Known Member
23 Апр 2010
2.293
1.995
113
@@Michael, а чем GUID от ID отличается?Сохраняется вместе с проектом?
Я похожее на то,что и Вы сейчас через ID.Сохранял все ID начальных айтемов в массив и потом когда убирал с них выделение.
PHP:
//==Store All starting Track items to Array "All_Track_Items[]" for Strict-Selection==//
Starting_Items_Amount = CountTrackMediaItems(Track_ID);n = 0; //Count Starting Items
loop(Starting_Items_Amount,All_Track_Items[n] = GetTrackMediaItem(Track_ID, n);n += 1;);//Get n-items IDs to Array


А потом,когда нужно
//==Strict-Sel After "Copy-Paste Item" applying==//
Main_OnCommand(40421, 0); n = 0;  //Select All item on Sel Track//Loop = Strict Un-Select All Starting Items by IDs
loop(Starting_Items_Amount, SetMediaItemSelected(All_Track_Items[n],0);n += 1;);//Strict Un-sel Start-Items by IDs
И маленькую ремарку по массиву в EEL оставлю,может кому-то время сэкономит.
В EEL массив может быть только один,но со смещением.То есть,первая переменная задает смещение,например:
4[0]=4-й элемент массива,20[4]=24-й элемент,в справке они называют это слотами.

Если нужно сохранить разные типы данных в как бы "разные" массивы,нужно задавать смещение,и оно может быть переменной
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
GUID - {шестнадцатизначный уникальный номер в таких скобочках}.
Сейчас как раз пишу скрипт для Коли Ефремова, где в качестве вспомогательной операции нужен экшн, запоминающий/восстанавливающий выбранные итемы/треки. Там всё через guid итемов и треков
Ну так я о таком где-то и писал - скрипт, который при сохранении проекта делает эту таблицусоответствия, к которой можно было-бы обращаться другим скриптам.
Но как это сделать практически - я понятия не имею.
[DOUBLEPOST=1434109774,1434109621][/DOUBLEPOST]@EUGEN27771, loop - похоже по любому, при том, что треков под сотню (включая вспомогательно-служебные) СИЛЬНО грузит Рипер.
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
чем GUID от ID отличается?Сохраняется вместе с проектом?
Сохраняется, посмотри файл проекта любого.
Айдишки присваиваются автоматом, после каждой манипуляции удаления, клонирования (сохраняется порядок 1,2,3,4...).
Уникальные имена присваиваются один раз и больше не меняются.
Поправлюсь - GUID не 16-значный, а 32-значный.

Примерно так guid я сохраняю в таблицу:
PHP:
...
-- step1 -- save selected items
function step1() local selitemcount, i, item, item_guid, bool_isselected, tempstr
  selitemcount = reaper.CountSelectedMediaItems(0)
  if selitemcount > 0 then
   for i = 1, selitemcount do
     item = reaper.GetSelectedMediaItem(0, i-1)
     item_guid = reaper.BR_GetMediaItemGUID(item, "")
     if item ~= nil then
       tempstr = string.format("%s%s", "1", item_guid)
       table.insert(selected_item_guid_t, i, tempstr)
     end  -- item not nil
   end -- loop
   condition1 = 1
  else
   condition1 = 0
  end -- itemcount > 0
end -- func step1
...

и так обратно вызываю конкретный айтем:
PHP:
...
for i = 1, #selected_item_guid_t do
      selected_item_guid = selected_item_guid_t[i]
      item_old = reaper.BR_GetMediaItemByGUID(0, selected_item_guid)
      if item_old ~= nil then
        reaper.SetMediaItemSelected(item_old, true)
...
ну и дальше делаем с айтемом что хотели
(можно было конечно запоминать таблицу с помощью return, но мне это не подходит, так как вызов функции сломает структуру всего скрипта)
 
Последнее редактирование:

EUGEN27771

Well-Known Member
23 Апр 2010
2.293
1.995
113
@@Michael, ID присваивается при создании объекта,тоже остается уникальным и постоянным и не меняется,но не сохраняется с проектом.
(сохраняется порядок 1,2,3,4...).
Это индекс,а не ID,(в мануале индекс- это idx- от того и путаница),то есть просто порядковый номер.
ID-восьмизначная комбинация.
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
EUGEN27771, да, понял, о чём ты, просто привык к скриптовым id с порядковых
Код:
track_ID = GetTrack(0, index)
или с выделенных
Код:
track_ID = GetSelectedTrack(0, index)
треков.

Id мы получаем из GetTrack, GetSelectedTrack, GetTrackbyName, из айтемов, инсертслотов и т.д. но когда все эти вещи перемещаются, переименовываются, перевыбираются и скачут из одной версии проекта в другую, проще юзать GUID.
 
Последнее редактирование:

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
А теперь парни расскажите как это использовать?
Как просто запомнить ID трека с конкретным именем и потом его использовать, обратившись к нему не через этот механизм перебора?

Кстати, Snapshot следит постоянно за изменениями в номере трека и его имени -
Т.е. как только изменил порядковый номер трека, который участвует в Snapshot и/или его имя - в информации Snapshot это отображается.....
 
Последнее редактирование:

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
Запомнить:
PHP:
GetUserInputs("trackname", 1, "", #user_def);
trackcount = CountTracks(0);
i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0);
  match(#trackname,#user_def) ? (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
  );
  i += 1;
);

Найти:
PHP:
track = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
 
  • Like
Реакции: EUGEN27771

EUGEN27771

Well-Known Member
23 Апр 2010
2.293
1.995
113
Опять через перебор,но я других вариантов и не вижу.Даже программа,вероятно,внутри ищет так,просто механизм работает несравненно быстрее.
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Женя, если этот Перебор можно сделать один раз при старте Проекта, а потом в исполняющих во время Лайва скриптах уже обращаться к GUID - меня это более чем устраивает.
Но я что-то пока не соображу как это сделать :(
 
Последнее редактирование:

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
И это может быть два разных скрипта?
Если два разных, то запомнить:
PHP:
GetUserInputs("trackname", 1, "", #user_def);
trackcount = CountTracks(0);
i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0); 
  match(#trackname,#user_def) ? (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
  );
  i += 1;
);
SetExtState("TrackGUID", "TrackGUID1", #trackguid, 1);

найти:
PHP:
GetExtState(#trackguid, "TrackGUID", "TrackGUID1");
track = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);

#trackguid в этом случае сохраняется в файл проекта.
То есть всё, что нужно, можно забить дома, а вызывать потом хоть где и хоть на чём.
 
  • Like
Реакции: Aleksandr Oleynik

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
То есть всё, что нужно, можно забить дома, а вызывать потом хоть где и хоть на чём.
Так собственно этого и добиваюсь!
Михаил, да! это работает!
Результат нужный мне уже близок - ну в том плане, что я начинаю понимать механизм работы скрипта, а значит могу его использовать...
Но вопросы всё-же есть, но чуть позже..

PS: Собственно вопрос - а нельзя таким образом сохранить не соответствие Имени Трека его GUID номеру, а Просто ИМЯ трека?
И потом прямо к нему и обращаться.
PSS: Всё, Въехал!
Михаил - огромное спасибо!
Всё пашет как мне нужно.
Теперь бы только как-то оптимизировать скрипт сохранения, я пока его так написал, но что-то мне подсказывает, что можно не повторять секцию столько раз, сколько Имён мне нужно сохранить. --


PHP:
trackcount = CountTracks(0);
i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0);
  match(#trackname, "K001") ? (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
  );
  i += 1;
);
SetExtState("TrackGUID", "K001", #trackguid, 1);

i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0);
  match(#trackname, "K002") ? (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
  );
  i += 1;
);
SetExtState("TrackGUID", "K002", #trackguid, 1);
PSSS: Вроди оптимизировал, или ещё можно?

PHP:
trackcount = CountTracks(0);
i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0);
 
  match(#trackname, "G001") ?
    (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
    SetExtState("TrackGUID", "G001", #trackguid, 1);
     );

  match(#trackname, "G002") ?
    (
    extension_api("BR_GetMediaTrackGUID", track, #trackguid);
    SetExtState("TrackGUID", "G002", #trackguid, 1);
     );
 
  i += 1;
);
[DOUBLEPOST=1434137130,1434135372][/DOUBLEPOST]Собственно почти то, что я и хотел - в Project sturtup грузим этот Экшин, который запоминает имена и всё - все исполняющие скрипты работают без всякого перебора моментально.

Почему собственно "почти" - а потому как чувствую, что должен быть какой-то механизм, который позволяет стартовый скрипт не писать с перечислением ВСЕХ имён Треков, которые в процессе работы мне нужны, а дать команду запомнить ВСЕ Имена Треков в проекте как их GUID - вот это был бы реально Элегантнейший скрипт.
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
PHP:
trackcount = CountTracks(0);
i = 0;
loop(trackcount,
  track = GetTrack(0, i);
  GetSetMediaTrackInfo_String(track, "P_NAME", #trackname, 0);
  extension_api("BR_GetMediaTrackGUID", track, #trackguid);
  SetExtState("TrackGUID", #trackname, #trackguid, 1);
  i += 1;
);
 
  • Like
Реакции: Aleksandr Oleynik

EUGEN27771

Well-Known Member
23 Апр 2010
2.293
1.995
113
@Aleksandr Oleynik, @@Michael, все равно это перебор,а по другому и нельзя,с точки зрения математики.Даже если в Рипере на уровне его API это быстрее делается,то это тоже перебор
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
EUGEN27771, если из API напрямую, то постим дружно реквест на API: GetTrackByName (что если два трека с одинаковыми именами?).
Способ выше по сути позволяет скрипту (второму) считывать напрямую без перебора нужный трек из определённой ячейки памяти, заполняемой при старте проекта. Что и требовалось Александру, не так ли?
 
Последнее редактирование:

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Что и требовалось Александру, не так ли?
Именно так!
[DOUBLEPOST=1434145599,1434145427][/DOUBLEPOST]
(что если два трека с одинаковыми именами?)
Реагировать только на первый по порядку - да и всё.
В любом случае - это ведь один из способов, кому нужен именно он - за уникальностью имён будет следить.
PS: На мой взгляд идентификация трека по его номеру на много более опсная и не предсказуемая вещь - добавляешь трек в начало проекта и трындец ВСЕМ скриптам - вахканалия начинается сразу.
[DOUBLEPOST=1434225614][/DOUBLEPOST]
Способ выше по сути позволяет скрипту (второму) считывать напрямую без перебора нужный трек из определённой ячейки памяти, заполняемой при старте проекта.
Сделал проект используя ЭТОТ способ - Скрипты переключают эффекты как нужно и ни каких артефактов и повышения нагрузки на комп НЕТ!

Михаил, а на сколько имеет смысл писать в память не все имена треков в проекте, а только те, которые нужны в процессе управления другими скриптами?
 

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Какой из кодов является более верным -

PHP:
       GetExtState(#trackguid1, "TrackGUID", "KEY01_P1");
       GetExtState(#trackguid2, "TrackGUID", "KEY01_P4");
       KEY01_P1 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid1);
       KEY01_P4 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid2);
       TrackFX_SetPreset(KEY01_P1, 1, "P004");
       TrackFX_SetPreset(KEY01_P4, 1, "ORGAN1");
Или -

PHP:
           GetExtState(#trackguid, "TrackGUID", "KEY01_P1");
           KEY01_P1 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
           TrackFX_SetPreset(KEY01_P1, 1, "P004");

           GetExtState(#trackguid, "TrackGUID", "KEY01_P4");   
           KEY01_P4 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);   
           TrackFX_SetPreset(KEY01_P4, 1, "ORGAN1");
Мне таким образом нужно поменять параметры FX-ов на куче треков, может есть более оптимальный способ записи?
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
PHP:
#tempstr = "KEY01_P1, P004"; // trackname, presetname
match("%s,%s", #tempstr, #trackname, #preset);
GetExtState(#trackguid, "TrackGUID", #trackname);
track = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
TrackFX_SetPreset(track, 1, #preset);
Это вы меняете параметры на втором эффекте каждого трека. Поэтому вам нужно вместе с guid трека также запоминать guid эффекта в рэке.
Например так:

PHP:
TrackFX_GetFXGUID(#retguid, track, fx);
SetExtState("FXGUID", #fxname, #retguid, 1);
 
Последнее редактирование:

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Михаил, не...., это я просто для примера так написал, что на каждом втором. В реальном проекте это совсем не так, в реальном проекте, на каком-то треке активным будет второй FX и в нём пресет должен быть сменён, на каком-то первый и второй, на каком-то третий. В общем системы в ЭТОМ нет. Где-то и не пресет нужно менять, а величину конкретного параметра.
Это всё решается при "программировании" звучания конкретной Композиции - а для втрой, третей, 30-ой всё задаётся иначе.

Просто я так понимаю, что в первом варианте я могу всем нужным мне трекам по их имени присвоить - #trackguidN и потом уже использовать индификатор трека в выражениях для FX-ов,
Но мне казалось, что есть какой-то функционал, который бы позволил не перечислять все нужные мне дальше имена GUID, а написать вместо вот этого -
PHP:
       GetExtState(#trackguid1, "TrackGUID", "KEY01_P1");
       GetExtState(#trackguid2, "TrackGUID", "KEY01_P4");
       KEY01_P1 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid1);
       KEY01_P4 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid2);
какое-то выражение, говорящее, что будем в качестве переменной track брать имя GUID запомненное, ну и писать дальше спокойно -
PHP:
TrackFX_SetPreset(KEY01_P1, 1, "P004");
TrackFX_SetPreset(KEY01_P2, 1, "P003");
TrackFX_SetPreset(ПЕК01_P1, 1, "Т001");
И т.д.


А во втором варианте записи я последовательно вычисляю #trackguid по имени GUID и делаю на ЭТОМ конкретном треке все изменения и приступаю к следующему.

Т.е. в общем-то по факту оба варианта работают как мне нужно, но я просто не уверен какой из них может сбойнуть.

В JSFX-е мой второй вариант просто не возможен, там ведь сначала задаются переменные, а потом они используются, а вот в EEL-е оказалось, что возможен?
 
Последнее редактирование:

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
там ведь сначала задаются переменные, а потом они используются
Также и в EEL

Код:
GetExtState(#trackguid, "TrackGUID", "KEY01_P1")
- достали переменную
Просто в данном случае запись другая, вам ближе была бы запись в духе
Код:
#trackguid = GetExtState("TrackGUID", "KEY01_P1")
, но она так не работает.

Код:
KEY01_P1 = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
- взяли трек

Код:
TrackFX_SetPreset(KEY01_P1, 1, "P004");
- применили пресет
 
  • Like
Реакции: Aleksandr Oleynik

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Понял. Другой синтаксис, но принцип тот-же.
Получается, что оба варианта рабочих, только в первом варианте я каждому значению GUID присваиваю свою переменную - #trackguid1, #trackguid2, #trackguid3 и т.д.
а потом их использую.
А во втором варианте я после получения и использования #trackguid её по новой перезаписываю и уже использую с новым значением.
Я правильно понимаю?

PS: По моему разумению второй вариант лучше, так как использует только одну ячейку памяти, а в первом - запоминаем кучу переменных.
Но вы опять скажете - что тут всё равно - 1 или 100. Да?
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
Обе ваши версии запоминают одинаковое количество переменных. После проведения каждого TrackFX_SetPreset, переменные никуда не исчезают (в EEL по крайней мере). В данном случае вы просто меняете очерёдность операторов.

Я же написал краткую версию:
PHP:
#tempstr = "KEY01_P1, P004"; // trackname, presetname
match("%s,%s", #tempstr, #trackname, #preset);
GetExtState(#trackguid, "TrackGUID", #trackname);
track = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
TrackFX_SetPreset(track, 1, #preset);
В данном случае от вас требуется только написать в первой строке имя трека и имя пресета.
 
  • Like
Реакции: Aleksandr Oleynik

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
В данном случае от вас требуется только написать в первой строке имя трека и имя пресета.
Она в общем по кол-ву строк на две длиннее чем моя -
PHP:
           GetExtState(#trackguid, "TrackGUID", "KEY01_P1");
           tr = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
           TrackFX_SetPreset(tr, 1, "P004");
Или я во что-то не врубаюсь.
Мне ведь всё равно в вашем варианте для каждого нового трека и/или порядкового номера FX нужно опять весь этот код писать?
 
Последнее редактирование:

Aleksandr Oleynik

Well-Known Member
16 Янв 2007
26.360
20.064
113
62
Киев
Понял! СПАСИБО!
Но тогда бы ещё в переменную ввести и порядковый номер FX-а - тогда да, логика была-бы полной ---- написал, через запятую три новых значения и всё.
А можно?
 

@Michael

Well-Known Member
14 Дек 2010
969
1.461
93
Орёл / Москва
Можно один раз забить функцию и потом её вызывать.

PHP:
function setpreset()
(
match("%s, %d, %s", #tempstr, #trackname, effect_id, #preset);
GetExtState(#trackguid, "TrackGUID", #trackname);
track = extension_api("BR_GetMediaTrackByGUID", 0, #trackguid);
i = effect_id - 1;
TrackFX_SetPreset(track, i, #preset);
);

#tempstr = "KEY01_P1, 1, P004"; // trackname, порядковый номер эффекта, presetname
setpreset();

#tempstr = "KEY05_P46, 5, P008"; // trackname, порядковый номер эффекта, presetname
setpreset();
 
Последнее редактирование:

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