Skip to main content
Glama
test_bus_routing.py13.5 kB
"""Tests for bus routing and mixing workflow tools.""" import pytest from unittest.mock import patch, MagicMock class TestBusRouting: """Test bus routing and mixing functions.""" @pytest.mark.asyncio async def test_create_bus_track(self, reaper_mcp_client): """Test creating a bus track.""" result = await reaper_mcp_client.call_tool("create_bus_track", { "name": "Test Bus", "num_channels": 2, "color": 0xFF0000 # Red }) assert result assert result.get("success") is True assert result.get("name") == "Test Bus" assert result.get("num_channels") == 2 assert "track_index" in result @pytest.mark.asyncio async def test_route_tracks_to_bus(self, reaper_mcp_client): """Test routing multiple tracks to a bus.""" # Create source tracks source_indices = [] for i in range(3): track_result = await reaper_mcp_client.call_tool("insert_track", { "index": i, "name": f"Source {i+1}" }) source_indices.append(track_result.get("track_index")) # Create bus bus_result = await reaper_mcp_client.call_tool("create_bus_track", { "name": "Mix Bus" }) bus_index = bus_result.get("track_index") # Route tracks to bus result = await reaper_mcp_client.call_tool("route_tracks_to_bus", { "source_track_indices": source_indices, "bus_track_index": bus_index, "send_mode": "post-fader", "send_level_db": -6.0 }) assert result assert result.get("success") is True assert len(result.get("routed_tracks", [])) == 3 assert result.get("send_mode") == "post-fader" @pytest.mark.asyncio async def test_create_parallel_compression_bus(self, reaper_mcp_client): """Test creating parallel compression setup.""" # Create drum tracks drum_indices = [] for i, name in enumerate(["Kick", "Snare", "HiHat"]): track_result = await reaper_mcp_client.call_tool("insert_track", { "index": i, "name": name }) drum_indices.append(track_result.get("track_index")) # Create parallel compression result = await reaper_mcp_client.call_tool("create_parallel_compression_bus", { "source_track_indices": drum_indices, "bus_name": "Drum Crush", "blend_amount_db": -10.0 }) assert result assert result.get("success") is True assert result.get("bus_name") == "Drum Crush" assert result.get("source_tracks") == drum_indices assert "compressor_added" in result @pytest.mark.asyncio async def test_create_reverb_send_bus(self, reaper_mcp_client): """Test creating reverb send bus.""" result = await reaper_mcp_client.call_tool("create_reverb_send_bus", { "reverb_type": "hall", "return_level_db": -12.0 }) assert result assert result.get("success") is True assert result.get("reverb_type") == "hall" assert result.get("return_level_db") == -12.0 assert "reverb_added" in result @pytest.mark.asyncio async def test_create_stem_buses(self, reaper_mcp_client): """Test creating stem buses for track groups.""" # Create tracks for different instrument groups track_map = {} track_idx = 0 # Drums drum_indices = [] for drum in ["Kick", "Snare", "HiHat", "Toms"]: track_result = await reaper_mcp_client.call_tool("insert_track", { "index": track_idx, "name": drum }) drum_indices.append(track_result.get("track_index")) track_idx += 1 # Bass bass_result = await reaper_mcp_client.call_tool("insert_track", { "index": track_idx, "name": "Bass" }) bass_indices = [bass_result.get("track_index")] track_idx += 1 # Keys keys_indices = [] for key in ["Piano", "Synth"]: track_result = await reaper_mcp_client.call_tool("insert_track", { "index": track_idx, "name": key }) keys_indices.append(track_result.get("track_index")) track_idx += 1 # Create stem buses result = await reaper_mcp_client.call_tool("create_stem_buses", { "stem_groups": { "Drums": drum_indices, "Bass": bass_indices, "Keys": keys_indices } }) assert result assert result.get("success") is True assert len(result.get("stems_created", [])) == 3 # Verify stem names stem_names = [s["name"] for s in result.get("stems_created", [])] assert "Drums" in stem_names assert "Bass" in stem_names assert "Keys" in stem_names @pytest.mark.asyncio async def test_create_sidechain_routing(self, reaper_mcp_client): """Test creating sidechain routing.""" # Create source (kick) and destination (bass) tracks kick_result = await reaper_mcp_client.call_tool("insert_track", { "index": 0, "name": "Kick" }) kick_index = kick_result.get("track_index") bass_result = await reaper_mcp_client.call_tool("insert_track", { "index": 1, "name": "Bass" }) bass_index = bass_result.get("track_index") # Create sidechain routing result = await reaper_mcp_client.call_tool("create_sidechain_routing", { "source_track_index": kick_index, "destination_track_index": bass_index, "channel_offset": 2 # Channels 3/4 }) assert result assert result.get("success") is True assert result.get("source_track") == kick_index assert result.get("destination_track") == bass_index assert result.get("sidechain_channels") == "3/4" @pytest.mark.asyncio async def test_setup_monitor_mix(self, reaper_mcp_client): """Test setting up monitor mix.""" # Create performer tracks performer_indices = [] for i, name in enumerate(["Vocals", "Guitar", "Keys"]): track_result = await reaper_mcp_client.call_tool("insert_track", { "index": i, "name": name }) performer_indices.append(track_result.get("track_index")) # Create click track click_result = await reaper_mcp_client.call_tool("insert_track", { "index": 3, "name": "Click" }) click_index = click_result.get("track_index") # Setup monitor mix result = await reaper_mcp_client.call_tool("setup_monitor_mix", { "performer_tracks": performer_indices, "click_track_index": click_index, "output_channel": 2 # Hardware outputs 3/4 }) assert result assert result.get("success") is True assert result.get("performer_tracks") == performer_indices assert result.get("click_included") is True assert result.get("output_channel") == 3 # 1-based display @pytest.mark.asyncio async def test_create_headphone_cue_mixes(self, reaper_mcp_client): """Test creating multiple headphone cue mixes.""" result = await reaper_mcp_client.call_tool("create_headphone_cue_mixes", { "num_mixes": 4 }) assert result assert result.get("success") is True assert len(result.get("cue_mixes", [])) == 4 # Verify output assignments for i, cue in enumerate(result.get("cue_mixes", [])): assert cue["name"] == f"Cue Mix {i+1}" expected_outputs = f"{i*2+1}/{i*2+2}" assert cue["output_channels"] == expected_outputs @pytest.mark.asyncio async def test_analyze_routing_matrix(self, reaper_mcp_client): """Test analyzing routing matrix.""" # Create a simple routing setup track1_result = await reaper_mcp_client.call_tool("insert_track", { "index": 0, "name": "Source" }) track2_result = await reaper_mcp_client.call_tool("insert_track", { "index": 1, "name": "Bus" }) # Create send await reaper_mcp_client.call_tool("route_tracks_to_bus", { "source_track_indices": [track1_result.get("track_index")], "bus_track_index": track2_result.get("track_index") }) # Analyze routing result = await reaper_mcp_client.call_tool("analyze_routing_matrix", {}) assert result assert result.get("success") is True assert result.get("track_count") >= 2 routing = result.get("routing", []) assert len(routing) >= 2 # Verify source track has send source_info = next((t for t in routing if t["name"] == "Source"), None) assert source_info assert source_info["num_sends"] > 0 # Verify bus track has receive bus_info = next((t for t in routing if t["name"] == "Bus"), None) assert bus_info assert bus_info["num_receives"] > 0 class TestBusRoutingSync: """Synchronous tests for bus routing using mocked bridge.""" @patch('server.tools.bus_routing.ReaperBridge.send_request') def test_create_bus_track_sync(self, mock_send): """Test creating bus track with mock.""" from server.tools.bus_routing import create_bus_track # Mock responses mock_send.side_effect = [ {"result": True, "count": 5}, # CountTracks {"result": True}, # InsertTrackAtIndex {"result": True, "track": "bus_handle"}, # GetTrack {"result": True}, # GetSetMediaTrackInfo_String (name) {"result": True}, # SetMediaTrackInfo_Value (color) {"result": True}, # SetMediaTrackInfo_Value (folder) ] result = create_bus_track("Test Bus", color=0xFF0000) assert result["success"] is True assert result["track_index"] == 5 assert result["name"] == "Test Bus" @patch('server.tools.bus_routing.ReaperBridge.send_request') def test_route_tracks_to_bus_sync(self, mock_send): """Test routing tracks with mock.""" from server.tools.bus_routing import route_tracks_to_bus # Mock responses mock_send.side_effect = [ {"result": True, "track": "bus_handle"}, # GetTrack (bus) {"result": True, "track": "track1"}, # GetTrack (source 1) {"result": True, "send_index": 0}, # CreateTrackSend {"result": True}, # SetTrackSendInfo_Value (mode) {"result": True}, # SetTrackSendInfo_Value (level) {"result": True, "track": "track2"}, # GetTrack (source 2) {"result": True, "send_index": 0}, # CreateTrackSend {"result": True}, # SetTrackSendInfo_Value (mode) {"result": True}, # SetTrackSendInfo_Value (level) ] result = route_tracks_to_bus([0, 1], 2, "post-fader", -6.0) assert result["success"] is True assert len(result["routed_tracks"]) == 2 assert result["send_mode"] == "post-fader" @patch('server.tools.bus_routing.ReaperBridge.send_request') def test_create_stem_buses_sync(self, mock_send): """Test creating stem buses with mock.""" from server.tools.bus_routing import create_stem_buses # Mock for creating drum stem mock_send.side_effect = [ {"result": True, "count": 10}, # CountTracks {"result": True}, # InsertTrackAtIndex {"result": True, "track": "drum_bus"}, # GetTrack {"result": True}, # GetSetMediaTrackInfo_String (name) {"result": True}, # SetMediaTrackInfo_Value (color) {"result": True}, # SetMediaTrackInfo_Value (folder) {"result": True, "track": "drum_bus"}, # GetTrack (bus) {"result": True, "track": "kick"}, # GetTrack (source 1) {"result": True, "send_index": 0}, # CreateTrackSend {"result": True}, # SetTrackSendInfo_Value (mode) {"result": True, "track": "kick"}, # GetTrack (for master send) {"result": True}, # SetMediaTrackInfo_Value (remove master) {"result": True, "track": "snare"}, # GetTrack (source 2) {"result": True, "send_index": 0}, # CreateTrackSend {"result": True}, # SetTrackSendInfo_Value (mode) {"result": True, "track": "snare"}, # GetTrack (for master send) {"result": True}, # SetMediaTrackInfo_Value (remove master) ] result = create_stem_buses({"Drums": [0, 1]}) assert result["success"] is True assert len(result["stems_created"]) == 1 assert result["stems_created"][0]["name"] == "Drums"

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