Reaper 5 ReaScriptでいろいろ作ってみた

# はじめに

luaで書いていく、ReaScript 拡張アクション。

※ **ReaScript** に関する日本語ドキュメントが皆無なので Qiitaに投稿することにしました。
ここに書いてあるのは実用的なアクションではないですが、基本的な使い方を掴むには向いてると思います。

# 選択したトラック/メディアアイテムを取得する

**選択済みのトラックを取得する場合**

```lua
MediaTrack reaper.GetSelectedTrack   (ReaProject proj, integer seltrackidx)
integer    reaper.CountSelectedTracks(ReaProject proj)
```

**MediaTrack** クラスは Reaper 内で定義されており、スクリプトで取得できるのはポインタです。ReaScript API の関数でこのポインタを使用してトラックの情報に取得と更新をしていきます。

**選択済みのメディアアイテムを取得する場合**

```lua
integer   reaper.CountSelectedMediaItems(ReaProject proj)
MediaItem reaper.GetSelectedMediaItem   (ReaProject proj, integer selitem)
```
この**MediaItem**も同様にスクリプトで取得できるのはポインタです。こちらもReaScript API の関数でこのポインタを使用して**MediaItem**の情報の取得と更新をしていきます。




# 取得したトラックの設定を取得してみる。

![GettrackName.gif](https://qiita-image-store.s3.amazonaws.com/0/212250/38aa946c-49f2-f6b7-9355-40d15548f68a.gif)
画像 : 選択されてあるトラックの名前を取得する

```lua
--====================================================================
function DBG(str ) --デバッグ表示用関数
    reaper.ShowConsoleMsg(tostring(str.."\n"))
end
--====================================================================
local proj = 0;
local selectedTrackNum = reaper.CountSelectedTracks(proj) -- 選択されてある総トラック数を取得
--====================================================================
local count = 0;
while ( count < selectedTrackNum)
do
    local mediaTarck = reaper.GetSelectedTrack(proj, count)

    -- トラックの名前を取得する
    local check
        , trackName = reaper.GetSetMediaTrackInfo_String( mediaTarck
                                                   , "P_NAME" -- パラメータの名前（公式ドキュメント参照)
                                                   , ""       -- 値を取得する場合は未使用
                                                   , false )  -- 新しい値で更新するかどうか
    DBG( trackName) -- 確認用にコンソールに表示
    
    -- トラックのソロモードの設定を取得する
    local soloMode = reaper.GetMediaTrackInfo_Value( mediaTarck
                                                   , "I_SOLO " ) -- パラメータの名前（ドキュメント参照)
    -- トラックのボリュームの設定を取得する
    local volume   = reaper.GetMediaTrackInfo_Value( mediaTarck
                                                   , "D_VOL " )  -- パラメータの名前（ドキュメント参照)

    count = count + 1 -- increment
end
--====================================================================
```


# 選択したトラックの名前を変更してみる

![trackName.gif](https://qiita-image-store.s3.amazonaws.com/0/212250/2a26e29d-9e2d-3c60-a516-31c48365b724.gif)


```lua
--====================================================================
function DBG(str ) --デバッグ表示用関数
    reaper.ShowConsoleMsg(tostring(str.."\n"))
end
--====================================================================
local proj = 0;
local selectedTrackNum = reaper.CountSelectedTracks(proj)
--====================================================================
local count = 0;
while ( count < selectedTrackNum)
do
    local mediaTarck = reaper.GetSelectedTrack(proj, count)

    -- トラックの現在の名前を取得する
    local check
        , trackName = reaper.GetSetMediaTrackInfo_String( mediaTarck
                                                  , "P_NAME" -- パラメータの名前（公式ドキュメント参照)
                                                  , ""       -- 値を取得する場合は未使用
                                                  , false )  -- 新しい値で更新するかどうか
    ------- 
    local  newTrackName = "TEST NEW NAME" .. tostring(count)
    local  isSucceed = reaper.GetSetMediaTrackInfo_String( mediaTarck
                                                  , "P_NAME"       -- パラメータの名前
                                                  , newTrackName   -- 新しいトラックの名前
                                                  , true )         -- 新しい値で更新するかどうか
   
    count = count + 1 -- increment
end
--====================================================================
```

# 選択したトラックのカラーを変更してみる

![Random_TrackColor2.gif](https://qiita-image-store.s3.amazonaws.com/0/212250/9d80a10b-680e-c7d0-40cf-b231f02b0813.gif)

``` lua
--====================================================================
function DBG(str )
    reaper.ShowConsoleMsg(tostring(str ).."\n")
end
--====================================================================
math.randomseed = reaper.time_precise()/os.time() -- ランダムシードを更新
--====================================================================
local proj = 0;
local selectedTrackNum = reaper.CountSelectedTracks(proj)
--====================================================================
local count = 0;
while ( count < selectedTrackNum)
do
    local mediaTarck = reaper.GetSelectedTrack(proj, count)

    local randomColor = reaper.ColorToNative( math.floor( math.random()*255)
                                            , math.floor( math.random()*255)
                                            , math.floor( math.random()*255) )
    --================================================================
    --  カラー設定を更新。 |0x1000000 しているのは公式ドキュメントを参照。
    local isSucceed  = reaper.SetMediaTrackInfo_Value( mediaTarck
                                                     , "I_CUSTOMCOLOR" --パラメータの名前
                                                     , randomColor|0x1000000  )

    -- SetTrackColor関数を使う方法も。
    -- reaper.SetTrackColor(mediaTarck, randomColor )
    
    count = count + 1 -- increment
end
--====================================================================
```

# 選択したメディアアイテムのカラーを変更してみる

![Change COlor.gif](https://qiita-image-store.s3.amazonaws.com/0/212250/6b205b45-a30f-52d7-7b7c-3934e9a076d0.gif)

※ 選択したアイテムの色がわかりやすいようにテーマを変更しています。

```lua
--====================================================================
local proj = 0;
local selectedMediaItemNum = reaper.CountSelectedMediaItems(proj)
math.randomseed = reaper.time_precise()/os.time() -- ランダムシードを更新
--====================================================================
local count = 0;
while ( count < selectedMediaItemNum)
do
    local mediaItem = reaper.GetSelectedMediaItem(proj, count)

    local randomColor = reaper.ColorToNative( math.floor( math.random()*255)
                                            , math.floor( math.random()*255)
                                            , math.floor( math.random()*255) )
    --================================================================
    --  カラー設定を更新。 |0x1000000 しているのは公式ドキュメントを参照。
    local isSucceed = reaper.SetMediaItemInfo_Value( mediaTarck
                                                   , "I_CUSTOMCOLOR" --パラメータの名前
                                                   , randomColor|0x1000000  )
    
    count = count + 1 -- increment
end
--====================================================================
```

# 選択したメディアアイテムのテイクのネームを変更してみる
![TakeName2.gif](https://qiita-image-store.s3.amazonaws.com/0/212250/6e95b4e2-f5ae-3995-0fe5-013896dae435.gif)

```lua

--====================================================================
local proj = 0;
local selectedMediaItemNum = reaper.CountSelectedMediaItems(proj)

--====================================================================
local count = 0;
while ( count < selectedMediaItemNum)
do
    local mediaItem = reaper.GetSelectedMediaItem(proj, count)

    -- 現在 アクティブなテイク (Mediaitem_Take) を取得
    local currentTakeId =reaper.GetMediaItemInfo_Value(mediaItem, "I_CURTAKE ")
    local currentTake = reaper.GetMediaItemTake( mediaItem
                                               , currentTakeId)
    
    local newName = "New Take Name"
    -- アクティブテイクの名前を変更・更新
    local isSucceed  = reaper.GetSetMediaItemTakeInfo_String( MediaItem_Take tk
                                                , "P_NAME" -- パラメータの名前（公式ドキュメント参照)
                                                , newName  -- 新しいテイクの名前
                                                , true )
    
    count = count + 1 -- increment
end
--====================================================================
```


# スクリプトを使って Reaper標準のコマンドを呼び出してみる

* Reaperのアクションウィンドウから 実行したい コマンド IDを確認しておく。
* スクリプト内で ``Main_OnCommand `` または ``Main_OnCommandEx`` 関数を使用して実行する。

```lua
-- Transport: Play/stop 40044 
local ID_PLAY_STROP = 40044              -- 実行させたい Reaper 標準のアクションのID
reaper.Main_OnCommand( ID_PLAY_STOP ,-1) -- 現在編集中のプロジェクトに対して アクションを実行する
```

もしくは、対象のプロジェクトを指定する場合、

```lua
local proj = 0                                  -- 現在、編集中のプロジェクト
reaper.Main_OnCommandEx( ID_PLAY_STOP ,-1,proj) -- 対象のプロジェクトを指定して実行する
```

# UNDO ポイントを記録する

**Undo_BeginBlock2** と **Undo_EndBlock2** で囲む

```lua
local proj = 0 -- 現在編集中のプロジェクト
reaper.Undo_BeginBlock2(proj )
--====================================================================

--- 処理

--====================================================================
local undoStr ="undo description."
reaper.Undo_EndBlock2(proj,undoStr, -1);
```

# ---

駆け足でコードを書きました。 詳しい内容の説明を飛ばしてしまいましたが、柔軟に自分で好きなアクションを追加できるのはReaperの強みだと思います。時間の合間にグラフィックを扱う方法、MIDIノートを扱う方法を書いていけたらなと思います。

少しでも興味のある方のお役に立てればうれしいです。
ここに書いてある以外の関数リファレンスは こちら のページに。

* https://www.reaper.fm/sdk/reascript/reascript.php
* https://www.cockos.com/reaper/sdk/reascript/reascripthelp.html

※ Reaperはアップデート情報については公式のforumへ。 ごくまれにAPIの仕様が変わるようです。
※ 間違った内容はコメント欄にてご助言いただけると嬉しいです。

※ スクリプト管理ツールの **ReaPack** もすごく便利なのでこちらもぜひ
https://qiita.com/kawakawa_/items/550c1a06bbf1b72140bc

# その他・Reaper関連参考リンク

* **Reaper Official** : https://www.reaper.fm/
* **Reaper Official Forums** : https://forum.cockos.com/forumdisplay.php?f=20
* **Extream Raym** : [How to Learn ReaScript for REAPER](https://www.extremraym.com/en/learn-reascript-reaper/ )
* **Extream Raym** : [REASCRIPT API — DOCUMENTATION](https://www.extremraym.com/cloud/reascript-doc/)
* **ReaPack** [Package manager for REAPER]( http://reapack.com/ )
* **ReaPack** [Repository List](https://reapack.com/repos)
* **AdmiralBumbleBee.com** :[Reaper Script Showcase](http://www.admiralbumblebee.com/ReaperScripts.html)