Skip to main content
Glama
media_items.py25.9 kB
""" Media Items & Takes Tools for REAPER MCP This module contains tools for managing media items and takes. """ from typing import Optional from ..bridge import bridge # ============================================================================ # Media Item Management (10 tools) # ============================================================================ async def add_media_item_to_track(track_index: int) -> str: """Add a new media item to a track""" # Pass track index directly - the bridge will handle getting the track result = await bridge.call_lua("AddMediaItemToTrack", [track_index]) if result.get("ok"): item = result.get("ret") return f"Added media item to track {track_index}: {item}" else: raise Exception(f"Failed to add media item: {result.get('error', 'Unknown error')}") async def count_media_items(project_index: int = 0) -> str: """Count the number of media items in the project""" result = await bridge.call_lua("CountMediaItems", [project_index]) if result.get("ok"): count = result.get("ret", 0) return f"Project has {count} media items" else: raise Exception(f"Failed to count media items: {result.get('error', 'Unknown error')}") async def get_media_item(item_index: int, project_index: int = 0) -> str: """Get a media item by index""" result = await bridge.call_lua("GetMediaItem", [project_index, item_index]) if result.get("ok"): item = result.get("ret") if item: return f"Media item at index {item_index}: {item}" else: return f"No media item found at index {item_index}" else: raise Exception(f"Failed to get media item: {result.get('error', 'Unknown error')}") async def delete_track_media_item(track_index: int, item_index: int) -> str: """Delete a media item from a track""" # Pass indices directly - the bridge will handle getting the track and item result = await bridge.call_lua("DeleteTrackMediaItem", [track_index, item_index]) if result.get("ok"): return f"Deleted media item {item_index} from track {track_index}" else: raise Exception(f"Failed to delete media item: {result.get('error', 'Unknown error')}") async def get_media_item_length(item_index: int) -> str: """Get the length of a media item in seconds""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") result = await bridge.call_lua("GetMediaItemInfo_Value", [item_index, "D_LENGTH"]) if result.get("ok"): length = result.get("ret", 0.0) return f"Media item {item_index} length: {length:.3f} seconds" else: raise Exception(f"Failed to get media item length: {result.get('error', 'Unknown error')}") async def set_media_item_length(item_index: int, length: float) -> str: """Set the length of a media item in seconds""" # Use the index-based bridge function result = await bridge.call_lua("SetMediaItemLength", [item_index, length, True]) if result.get("ok"): return f"Set media item {item_index} length to {length:.3f} seconds" else: raise Exception(f"Failed to set media item length: {result.get('error', 'Unknown error')}") async def get_media_item_position(item_index: int) -> str: """Get the position of a media item in seconds""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") result = await bridge.call_lua("GetMediaItemInfo_Value", [item_index, "D_POSITION"]) if result.get("ok"): position = result.get("ret", 0.0) return f"Media item {item_index} position: {position:.3f} seconds" else: raise Exception(f"Failed to get media item position: {result.get('error', 'Unknown error')}") async def set_media_item_position(item_index: int, position: float) -> str: """Set the position of a media item in seconds""" # Use the index-based bridge function result = await bridge.call_lua("SetMediaItemPosition", [item_index, position, True]) if result.get("ok"): return f"Set media item {item_index} position to {position:.3f} seconds" else: raise Exception(f"Failed to set media item position: {result.get('error', 'Unknown error')}") async def set_media_item_selected(item_index: int, selected: bool) -> str: """Set the selection state of a media item""" # Pass item index directly - the bridge will handle getting the item result = await bridge.call_lua("SetMediaItemSelected", [item_index, selected]) if result.get("ok"): state = "selected" if selected else "unselected" return f"Media item {item_index} is now {state}" else: raise Exception(f"Failed to set media item selection: {result.get('error', 'Unknown error')}") async def count_selected_media_items(project_index: int = 0) -> str: """Count the number of selected media items""" result = await bridge.call_lua("CountSelectedMediaItems", [project_index]) if result.get("ok"): count = result.get("ret", 0) return f"Project has {count} selected media items" else: raise Exception(f"Failed to count selected items: {result.get('error', 'Unknown error')}") async def get_selected_media_item(index: int, project_index: int = 0) -> str: """Get a selected media item by index""" result = await bridge.call_lua("GetSelectedMediaItem", [project_index, index]) if result.get("ok"): item = result.get("ret") if item: return f"Selected media item at index {index}: {item}" else: return f"No selected media item at index {index}" else: raise Exception(f"Failed to get selected item: {result.get('error', 'Unknown error')}") # ============================================================================ # Media Item Operations (7 tools) # ============================================================================ async def split_media_item(item_index: int, split_position: float) -> str: """Split a media item at the specified position""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") result = await bridge.call_lua("SplitMediaItem", [item_index, split_position]) if result.get("ok"): return f"Split media item {item_index} at position {split_position:.3f}" else: raise Exception(f"Failed to split media item: {result.get('error', 'Unknown error')}") async def glue_media_items(item_indices: list[int], project_index: int = 0) -> str: """Glue multiple media items together""" # Implementation would need to select items first then call glue action # This is a simplified version result = await bridge.call_lua("Main_OnCommand", [40362, 0]) # Glue items if result.get("ok"): return f"Glued {len(item_indices)} media items" else: raise Exception(f"Failed to glue items: {result.get('error', 'Unknown error')}") async def duplicate_media_item(item_index: int) -> str: """Duplicate a media item""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Select the item await bridge.call_lua("SetMediaItemSelected", [item_index, True]) # Duplicate selected items result = await bridge.call_lua("Main_OnCommand", [41295, 0]) # Duplicate items if result.get("ok"): return f"Duplicated media item {item_index}" else: raise Exception(f"Failed to duplicate item: {result.get('error', 'Unknown error')}") async def set_media_item_color(item_index: int, color: int) -> str: """Set the color of a media item""" # Use the index-based bridge function result = await bridge.call_lua("SetMediaItemInfoValueByIndex", [item_index, "I_CUSTOMCOLOR", color | 0x01000000]) if result.get("ok"): return f"Set media item {item_index} color to {color:#08x}" else: raise Exception(f"Failed to set item color: {result.get('error', 'Unknown error')}") async def get_media_item_color(item_index: int) -> str: """Get the color of a media item""" # Use the index-based bridge function result = await bridge.call_lua("GetMediaItemInfoValueByIndex", [item_index, "I_CUSTOMCOLOR"]) if result.get("ok"): color = int(result.get("ret", 0)) if color & 0x01000000: color = color & 0xFFFFFF return f"Media item {item_index} color: {color:#08x}" else: return f"Media item {item_index} has no custom color" else: raise Exception(f"Failed to get item color: {result.get('error', 'Unknown error')}") async def get_media_item_peak(item_index: int) -> str: """Get the peak value of a media item""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get active take take_result = await bridge.call_lua("GetActiveTake", [item_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception("No active take in media item") # Get peak result = await bridge.call_lua("NF_GetMediaItemMaxPeak", [item_index]) if result.get("ok"): peak = result.get("ret", 0.0) return f"Media item {item_index} peak: {peak:.3f}" else: raise Exception(f"Failed to get item peak: {result.get('error', 'Unknown error')}") async def get_media_item_take_track(item_index: int, take_index: int) -> str: """Get the track that contains a media item""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") result = await bridge.call_lua("GetMediaItem_Track", [item_index]) if result.get("ok"): track = result.get("ret") return f"Media item {item_index} is on track: {track}" else: raise Exception(f"Failed to get item track: {result.get('error', 'Unknown error')}") # ============================================================================ # Take Management (11 tools) # ============================================================================ async def add_take_to_item(item_index: int) -> str: """Add a new take to a media item""" # Add take using item index directly result = await bridge.call_lua("AddTakeToMediaItem", [item_index]) if result.get("ok"): take_handle = result.get("ret") if take_handle: # Get take count for info count_result = await bridge.call_lua("CountTakes", [item_index]) take_count = count_result.get("ret", 0) if count_result.get("ok") else 0 return f"Added take to media item {item_index}. Item now has {take_count} takes" else: return f"Failed to add take to media item {item_index}" else: raise Exception(f"Failed to add take: {result.get('error', 'Unknown error')}") async def count_takes(item_index: int) -> str: """Count the number of takes in a media item""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") result = await bridge.call_lua("CountTakes", [item_index]) if result.get("ok"): count = result.get("ret", 0) return f"Media item {item_index} has {count} takes" else: raise Exception(f"Failed to count takes: {result.get('error', 'Unknown error')}") async def get_active_take(item_index: int) -> str: """Get the active take of a media item""" # Get active take using item index directly result = await bridge.call_lua("GetActiveTake", [item_index]) if result.get("ok"): take = result.get("ret") if take: # Get take name name_result = await bridge.call_lua("GetTakeName", [take]) take_name = name_result.get("ret", "Unnamed") if name_result.get("ok") else "Unknown" return f"Active take: {take_name}" else: return "No active take in media item" else: raise Exception(f"Failed to get active take: {result.get('error', 'Unknown error')}") async def set_active_take(item_index: int, take_index: int) -> str: """Set the active take of a media item""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") # Set as active result = await bridge.call_lua("SetActiveTake", [take_result.get("ret")]) if result.get("ok"): return f"Set take {take_index} as active in media item {item_index}" else: raise Exception(f"Failed to set active take: {result.get('error', 'Unknown error')}") async def get_take_name(item_index: int, take_index: int) -> str: """Get the name of a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") result = await bridge.call_lua("GetTakeName", [take_result.get("ret")]) if result.get("ok"): name = result.get("ret", "") return f"Take {take_index} name: {name}" else: raise Exception(f"Failed to get take name: {result.get('error', 'Unknown error')}") async def set_take_name(item_index: int, take_index: int, name: str) -> str: """Set the name of a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") result = await bridge.call_lua("GetSetMediaItemTakeInfo_String", [take_result.get("ret"), "P_NAME", name, True]) if result.get("ok"): return f"Set take {take_index} name to: {name}" else: raise Exception(f"Failed to set take name: {result.get('error', 'Unknown error')}") async def get_media_item_take_source(item_index: int, take_index: int) -> str: """Get the source file of a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") # Get source source_result = await bridge.call_lua("GetMediaItemTake_Source", [take_result.get("ret")]) if not source_result.get("ok") or not source_result.get("ret"): raise Exception("Failed to get take source") # Get filename result = await bridge.call_lua("GetMediaSourceFileName", [source_result.get("ret"), "", 4096]) if result.get("ok"): filename = result.get("ret", "") return f"Take {take_index} source: {filename}" else: raise Exception(f"Failed to get source filename: {result.get('error', 'Unknown error')}") async def set_media_item_take_source(item_index: int, take_index: int, source_file: str) -> str: """Set the source file of a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") # Create PCM source source_result = await bridge.call_lua("PCM_Source_CreateFromFile", [source_file]) if not source_result.get("ok") or not source_result.get("ret"): raise Exception(f"Failed to create source from file: {source_file}") # Set the source result = await bridge.call_lua("SetMediaItemTake_Source", [take_result.get("ret"), source_result.get("ret")]) if result.get("ok"): return f"Set take {take_index} source to: {source_file}" else: raise Exception(f"Failed to set take source: {result.get('error', 'Unknown error')}") async def get_media_item_take_peaks(item_index: int, take_index: int, channel: int, start_time: float, num_samples: int, num_channels: int, sample_rate: int) -> str: """Get peak samples from a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") result = await bridge.call_lua("GetMediaItemTake_Peaks", [take_result.get("ret"), sample_rate, start_time, num_channels, num_samples, channel, []]) if result.get("ok"): return f"Retrieved {num_samples} peak samples from take {take_index}" else: raise Exception(f"Failed to get take peaks: {result.get('error', 'Unknown error')}") async def get_media_item_take_info_value(item_index: int, take_index: int, param_name: str) -> str: """Get a parameter value from a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") result = await bridge.call_lua("GetMediaItemTakeInfo_Value", [take_result.get("ret"), param_name]) if result.get("ok"): value = result.get("ret", 0) return f"Take {take_index} {param_name}: {value}" else: raise Exception(f"Failed to get take info: {result.get('error', 'Unknown error')}") async def set_media_item_take_info_value(item_index: int, take_index: int, param_name: str, value: float) -> str: """Set a parameter value for a take""" # Get item first item_result = await bridge.call_lua("GetMediaItem", [0, item_index]) if not item_result.get("ok") or not item_result.get("ret"): raise Exception(f"Failed to find media item at index {item_index}") # Get the specific take take_result = await bridge.call_lua("GetMediaItemTake", [item_index, take_index]) if not take_result.get("ok") or not take_result.get("ret"): raise Exception(f"Failed to find take {take_index} in media item") result = await bridge.call_lua("SetMediaItemTakeInfo_Value", [take_result.get("ret"), param_name, value]) if result.get("ok"): return f"Set take {take_index} {param_name} to {value}" else: raise Exception(f"Failed to set take info: {result.get('error', 'Unknown error')}") async def create_midi_item(track_index: int, position: float, length: float, quantize: Optional[bool] = False) -> str: """Create a new MIDI item on a track""" # First deselect all tracks deselect_result = await bridge.call_lua("Main_OnCommand", [40297, 0]) # Track: Unselect all tracks if not deselect_result.get("ok"): raise Exception("Failed to deselect all tracks") # Then select only the target track select_result = await bridge.call_lua("SetTrackSelected", [track_index, True]) if not select_result.get("ok"): raise Exception(f"Failed to select track {track_index}") # Count items before creating count_before = await bridge.call_lua("CountMediaItems", [0]) if not count_before.get("ok"): raise Exception("Failed to count media items") # Use Main_OnCommand to insert empty MIDI item - this creates a proper MIDI take result = await bridge.call_lua("Main_OnCommand", [40214, 0]) # Insert empty MIDI item if not result.get("ok"): raise Exception("Failed to create MIDI item") # Get the last created item index count_after = await bridge.call_lua("CountMediaItems", [0]) if not count_after.get("ok"): raise Exception("Failed to count media items after creation") # The new item should be the last one item_index = count_after.get("ret", 1) - 1 # Verify we actually created a new item if count_after.get("ret", 0) <= count_before.get("ret", 0): raise Exception("Failed to create new media item") # Set position and length - pass item index directly await bridge.call_lua("SetMediaItemPosition", [item_index, position, True]) await bridge.call_lua("SetMediaItemLength", [item_index, length, True]) return f"Created MIDI item (index {item_index}) on track {track_index} at position {position:.3f} with length {length:.3f}" # ============================================================================ # Registration Function # ============================================================================ def register_media_items_tools(mcp) -> int: """Register all media items and takes tools with the MCP instance""" tools = [ # Media Item Management (add_media_item_to_track, "Add a new media item to a track"), (count_media_items, "Count the number of media items in the project"), (get_media_item, "Get a media item by index"), (delete_track_media_item, "Delete a media item from a track"), (get_media_item_length, "Get the length of a media item in seconds"), (set_media_item_length, "Set the length of a media item in seconds"), (get_media_item_position, "Get the position of a media item in seconds"), (set_media_item_position, "Set the position of a media item in seconds"), (set_media_item_selected, "Set the selection state of a media item"), (count_selected_media_items, "Count the number of selected media items"), (get_selected_media_item, "Get a selected media item by index"), # Media Item Operations (split_media_item, "Split a media item at the specified position"), (glue_media_items, "Glue multiple media items together"), (duplicate_media_item, "Duplicate a media item"), (set_media_item_color, "Set the color of a media item"), (get_media_item_color, "Get the color of a media item"), (get_media_item_peak, "Get the peak value of a media item"), (get_media_item_take_track, "Get the track that contains a media item"), # Take Management (add_take_to_item, "Add a new take to a media item"), (count_takes, "Count the number of takes in a media item"), (get_active_take, "Get the active take of a media item"), (set_active_take, "Set the active take of a media item"), (get_take_name, "Get the name of a take"), (set_take_name, "Set the name of a take"), (get_media_item_take_source, "Get the source file of a take"), (set_media_item_take_source, "Set the source file of a take"), (get_media_item_take_peaks, "Get peak samples from a take"), (get_media_item_take_info_value, "Get a parameter value from a take"), (set_media_item_take_info_value, "Set a parameter value for a take"), (create_midi_item, "Create a new MIDI item on a track"), ] # Register each tool for func, desc in tools: decorated = mcp.tool()(func) return len(tools)

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