Skip to main content
Glama
mcp_bridge_dsl_functions.lua15.6 kB
-- DSL Bridge Functions for REAPER MCP -- These functions support the high-level DSL/Macro layer -- Add these functions to the main bridge by including this file -- DSL Helper Functions -- Get detailed track information including MIDI/audio content and FX local function GetTrackInfo(track_index) local track = nil if track_index == -1 then track = reaper.GetMasterTrack(0) else track = reaper.GetTrack(0, track_index) end if not track then return {ok = false, error = "Track not found"} end -- Get track info local retval, name = reaper.GetTrackName(track) local retval, guid = reaper.GetSetMediaTrackInfo_String(track, "GUID", "", false) -- Check for MIDI and audio items local has_midi = false local has_audio = false local item_count = reaper.CountTrackMediaItems(track) for i = 0, item_count - 1 do local item = reaper.GetTrackMediaItem(track, i) if item then local take = reaper.GetActiveTake(item) if take then if reaper.TakeIsMIDI(take) then has_midi = true else has_audio = true end end end end -- Get FX names local fx_names = {} local fx_count = reaper.TrackFX_GetCount(track) for i = 0, fx_count - 1 do local retval, fx_name = reaper.TrackFX_GetFXName(track, i, "") if retval then table.insert(fx_names, fx_name) end end -- Check for role in track notes local retval, notes = reaper.GetSetMediaTrackInfo_String(track, "P_EXT:role", "", false) local role = nil if notes and notes ~= "" then role = notes end return { ok = true, info = { guid = guid, name = name, has_midi = has_midi, has_audio = has_audio, fx_names = fx_names, role = role, muted = reaper.GetMediaTrackInfo_Value(track, "B_MUTE") == 1, soloed = reaper.GetMediaTrackInfo_Value(track, "I_SOLO") > 0 } } end -- Get all tracks with detailed info local function GetAllTracksInfo() local tracks = {} local count = reaper.CountTracks(0) for i = 0, count - 1 do local result = GetTrackInfo(i) if result.ok then local info = result.info info.index = i table.insert(tracks, info) end end return {ok = true, tracks = tracks} end -- Get/Set track notes (used for storing role) local function SetTrackNotes(track_index, notes) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end -- Store in extended state reaper.GetSetMediaTrackInfo_String(track, "P_EXT:role", notes, true) return {ok = true} end -- Get current cursor position local function GetCursorPosition() local pos = reaper.GetCursorPosition() return {ok = true, ret = pos} end -- Get time selection local function GetTimeSelection() local start_time, end_time = reaper.GetSet_LoopTimeRange(false, false, 0, 0, false) return {ok = true, start = start_time, ["end"] = end_time} end -- Set time selection local function SetTimeSelection(start_time, end_time) reaper.GetSet_LoopTimeRange(true, false, start_time, end_time, false) return {ok = true} end -- Get loop time range local function GetLoopTimeRange() local start_time, end_time = reaper.GetSet_LoopTimeRange(false, true, 0, 0, false) return {ok = true, start = start_time, ["end"] = end_time} end -- Convert bars to time duration local function BarsToTime(bars, start_pos) -- Get tempo at position local tempo = reaper.Master_GetTempo() local retval, num, denom = reaper.TimeMap_GetTimeSigAtTime(0, start_pos or 0) -- Calculate duration local beats_per_bar = num local total_beats = bars * beats_per_bar local duration = (total_beats / tempo) * 60 return {ok = true, ret = duration} end -- Find region by name local function FindRegion(name) local retval, num_markers, num_regions = reaper.CountProjectMarkers(0) for i = 0, num_markers + num_regions - 1 do local retval, isrgn, pos, rgnend, rgn_name, markrgnindexnumber = reaper.EnumProjectMarkers(i) if isrgn and rgn_name == name then return {ok = true, found = true, start = pos, ["end"] = rgnend} end end return {ok = true, found = false} end -- Find marker by name local function FindMarker(name) local retval, num_markers, num_regions = reaper.CountProjectMarkers(0) for i = 0, num_markers + num_regions - 1 do local retval, isrgn, pos, rgnend, marker_name, markrgnindexnumber = reaper.EnumProjectMarkers(i) if not isrgn and marker_name == name then return {ok = true, found = true, position = pos} end end return {ok = true, found = false} end -- Get selected items local function GetSelectedItems() local items = {} local count = reaper.CountSelectedMediaItems(0) for i = 0, count - 1 do local item = reaper.GetSelectedMediaItem(0, i) if item then local track = reaper.GetMediaItem_Track(item) local track_index = -1 -- Find track index for j = 0, reaper.CountTracks(0) - 1 do if reaper.GetTrack(0, j) == track then track_index = j break end end local take = reaper.GetActiveTake(item) local is_midi = take and reaper.TakeIsMIDI(take) local retval, name = reaper.GetTakeName(take or item) table.insert(items, { index = i, track_index = track_index, position = reaper.GetMediaItemInfo_Value(item, "D_POSITION"), length = reaper.GetMediaItemInfo_Value(item, "D_LENGTH"), name = name, is_midi = is_midi }) end end return {ok = true, items = items} end -- Get all items local function GetAllItems() local items = {} local track_count = reaper.CountTracks(0) for t = 0, track_count - 1 do local track = reaper.GetTrack(0, t) local item_count = reaper.CountTrackMediaItems(track) for i = 0, item_count - 1 do local item = reaper.GetTrackMediaItem(track, i) if item then local take = reaper.GetActiveTake(item) local is_midi = take and reaper.TakeIsMIDI(take) local retval, name = reaper.GetTakeName(take or item) table.insert(items, { index = i, track_index = t, position = reaper.GetMediaItemInfo_Value(item, "D_POSITION"), length = reaper.GetMediaItemInfo_Value(item, "D_LENGTH"), name = name, is_midi = is_midi }) end end end return {ok = true, items = items} end -- Get items on specific track local function GetTrackItems(track_index) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local items = {} local item_count = reaper.CountTrackMediaItems(track) for i = 0, item_count - 1 do local item = reaper.GetTrackMediaItem(track, i) if item then local take = reaper.GetActiveTake(item) local is_midi = take and reaper.TakeIsMIDI(take) local retval, name = reaper.GetTakeName(take or item) table.insert(items, { index = i, track_index = track_index, position = reaper.GetMediaItemInfo_Value(item, "D_POSITION"), length = reaper.GetMediaItemInfo_Value(item, "D_LENGTH"), name = name, is_midi = is_midi }) end end return {ok = true, items = items} end -- Create MIDI item local function CreateMIDIItem(track_index, start_pos, end_pos) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local item = reaper.CreateNewMIDIItemInProj(track, start_pos, end_pos, false) if not item then return {ok = false, error = "Failed to create MIDI item"} end -- Find item index on track local item_index = -1 for i = 0, reaper.CountTrackMediaItems(track) - 1 do if reaper.GetTrackMediaItem(track, i) == item then item_index = i break end end return {ok = true, item_index = item_index} end -- Create audio item (empty) local function CreateAudioItem(track_index, start_pos, end_pos) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end -- Create empty item local item = reaper.AddMediaItemToTrack(track) if not item then return {ok = false, error = "Failed to create audio item"} end -- Set position and length reaper.SetMediaItemInfo_Value(item, "D_POSITION", start_pos) reaper.SetMediaItemInfo_Value(item, "D_LENGTH", end_pos - start_pos) -- Find item index on track local item_index = -1 for i = 0, reaper.CountTrackMediaItems(track) - 1 do if reaper.GetTrackMediaItem(track, i) == item then item_index = i break end end return {ok = true, item_index = item_index} end -- Set item loop source local function SetItemLoopSource(track_index, item_index, loop_source) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local item = reaper.GetTrackMediaItem(track, item_index) if not item then return {ok = false, error = "Item not found"} end reaper.SetMediaItemInfo_Value(item, "B_LOOPSRC", loop_source and 1 or 0) return {ok = true} end -- Insert MIDI note local function InsertMIDINote(track_index, item_index, pitch, start_ppq, length_ppq, velocity, channel) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local item = reaper.GetTrackMediaItem(track, item_index) if not item then return {ok = false, error = "Item not found"} end local take = reaper.GetActiveTake(item) if not take or not reaper.TakeIsMIDI(take) then return {ok = false, error = "Not a MIDI take"} end -- Convert time to PPQ local item_pos = reaper.GetMediaItemInfo_Value(item, "D_POSITION") local ppq_start = reaper.MIDI_GetPPQPosFromProjTime(take, item_pos + start_ppq) local ppq_end = reaper.MIDI_GetPPQPosFromProjTime(take, item_pos + start_ppq + length_ppq) reaper.MIDI_InsertNote(take, false, false, ppq_start, ppq_end, channel or 0, pitch, velocity or 100, false) reaper.MIDI_Sort(take) return {ok = true} end -- Quantize item local function QuantizeItem(track_index, item_index, strength, grid) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local item = reaper.GetTrackMediaItem(track, item_index) if not item then return {ok = false, error = "Item not found"} end local take = reaper.GetActiveTake(item) if not take or not reaper.TakeIsMIDI(take) then return {ok = false, error = "Not a MIDI take"} end -- Note: This is a simplified quantization -- In practice, you'd use MIDI editor actions or more complex logic -- For now, just return success return {ok = true} end -- Track operations local function GetTrackVolume(track_index) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local vol = reaper.GetMediaTrackInfo_Value(track, "D_VOL") return {ok = true, ret = vol} end local function SetTrackVolume(track_index, volume) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end reaper.SetMediaTrackInfo_Value(track, "D_VOL", volume) return {ok = true} end local function GetTrackPan(track_index) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end local pan = reaper.GetMediaTrackInfo_Value(track, "D_PAN") return {ok = true, ret = pan} end local function SetTrackPan(track_index, pan) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end reaper.SetMediaTrackInfo_Value(track, "D_PAN", pan) return {ok = true} end local function SetTrackMute(track_index, mute) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end reaper.SetMediaTrackInfo_Value(track, "B_MUTE", mute and 1 or 0) return {ok = true} end local function SetTrackSolo(track_index, solo) local track = reaper.GetTrack(0, track_index) if not track then return {ok = false, error = "Track not found"} end reaper.SetMediaTrackInfo_Value(track, "I_SOLO", solo and 1 or 0) return {ok = true} end -- Transport operations local function Play() reaper.Main_OnCommand(1007, 0) -- Transport: Play return {ok = true} end local function Stop() reaper.Main_OnCommand(1016, 0) -- Transport: Stop return {ok = true} end local function GetTempo() local tempo = reaper.Master_GetTempo() return {ok = true, ret = tempo} end local function SetTempo(bpm) reaper.SetTempoTimeSigMarker(0, -1, -1, -1, -1, bpm, 0, 0, false) return {ok = true} end local function GetTimeSignature() local retval, num, denom = reaper.TimeMap_GetTimeSigAtTime(0, reaper.GetCursorPosition()) return {ok = true, numerator = num, denominator = denom} end -- Export function table for DSL DSL_FUNCTIONS = { -- Track info GetTrackInfo = GetTrackInfo, GetAllTracksInfo = GetAllTracksInfo, SetTrackNotes = SetTrackNotes, -- Time operations GetCursorPosition = GetCursorPosition, GetTimeSelection = GetTimeSelection, SetTimeSelection = SetTimeSelection, GetLoopTimeRange = GetLoopTimeRange, BarsToTime = BarsToTime, FindRegion = FindRegion, FindMarker = FindMarker, -- Item operations GetSelectedItems = GetSelectedItems, GetAllItems = GetAllItems, GetTrackItems = GetTrackItems, CreateMIDIItem = CreateMIDIItem, CreateAudioItem = CreateAudioItem, SetItemLoopSource = SetItemLoopSource, InsertMIDINote = InsertMIDINote, QuantizeItem = QuantizeItem, -- Track operations GetTrackVolume = GetTrackVolume, SetTrackVolume = SetTrackVolume, GetTrackPan = GetTrackPan, SetTrackPan = SetTrackPan, SetTrackMute = SetTrackMute, SetTrackSolo = SetTrackSolo, -- Transport Play = Play, Stop = Stop, GetTempo = GetTempo, SetTempo = SetTempo, GetTimeSignature = GetTimeSignature }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shiehn/total-reaper-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server