Skip to main content
Glama
mixer.py8.77 kB
"""Mixer control tools for FL Studio.""" from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from fastmcp import FastMCP def register_mixer_tools(mcp: FastMCP) -> None: """Register mixer control tools with the MCP server.""" from fl_studio_mcp.utils.connection import get_connection @mcp.tool() def fl_get_mixer_track_count() -> int: """Get the total number of mixer tracks available. FL Studio typically has 125 mixer tracks (0-124), where track 0 is the Master. """ conn = get_connection() result = conn.send_command("mixer.getTrackCount") if not result.get("success", False) and "error" in result: return -1 # Return -1 to indicate error return result.get("count", 0) @mcp.tool() def fl_get_mixer_track_info(track: int) -> dict: """Get detailed information about a specific mixer track. Args: track: Mixer track index (0 = Master, 1-124 = insert tracks) """ conn = get_connection() result = conn.send_command("mixer.getTrackInfo", {"track": track}) if not result.get("success", False) and "error" in result: return {"error": result["error"]} return { "index": result.get("index", track), "name": result.get("name", ""), "volume": result.get("volume", 0), "volume_db": result.get("volume_db", 0), "pan": result.get("pan", 0), "stereo_separation": result.get("stereo_separation", 0), "is_muted": result.get("is_muted", False), "is_solo": result.get("is_solo", False), "is_armed": result.get("is_armed", False), "color": result.get("color", "0x0"), } @mcp.tool() def fl_get_all_mixer_tracks(include_empty: bool = False) -> list[dict]: """Get information about all mixer tracks. Args: include_empty: If False, only returns tracks with non-default names. If True, returns all 125 tracks. """ conn = get_connection() result = conn.send_command("mixer.getAllTracks", {"include_empty": include_empty}) if not result.get("success", False) and "error" in result: return [{"error": result["error"]}] return result.get("tracks", []) @mcp.tool() def fl_set_track_volume(track: int, volume: float) -> str: """Set the volume of a mixer track. Args: track: Mixer track index (0 = Master) volume: Volume level from 0.0 (silence) to 1.0 (0dB). Default FL Studio volume is 0.8 (~-5.2dB). Values above 1.0 may cause clipping. """ if not 0.0 <= volume <= 1.25: return "Error: Volume should be between 0.0 and 1.25" conn = get_connection() result = conn.send_command("mixer.setTrackVolume", { "track": track, "volume": volume, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" new_vol = result.get("volume", 0) new_vol_db = result.get("volume_db", 0) return f"Track {track} volume set to {new_vol:.3f} ({new_vol_db:.1f} dB)" @mcp.tool() def fl_set_track_pan(track: int, pan: float) -> str: """Set the pan position of a mixer track. Args: track: Mixer track index (0 = Master) pan: Pan position from -1.0 (full left) to 1.0 (full right). 0.0 is center. """ if not -1.0 <= pan <= 1.0: return "Error: Pan must be between -1.0 (left) and 1.0 (right)" conn = get_connection() result = conn.send_command("mixer.setTrackPan", { "track": track, "pan": pan, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" new_pan = result.get("pan", 0) if new_pan < -0.01: direction = f"{abs(new_pan) * 100:.0f}% left" elif new_pan > 0.01: direction = f"{new_pan * 100:.0f}% right" else: direction = "center" return f"Track {track} pan set to {direction}" @mcp.tool() def fl_mute_track(track: int, muted: bool | None = None) -> str: """Mute or unmute a mixer track. Args: track: Mixer track index muted: True to mute, False to unmute, None to toggle """ conn = get_connection() result = conn.send_command("mixer.muteTrack", { "track": track, "muted": muted, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" is_muted = result.get("is_muted", False) track_name = result.get("track_name", f"Track {track}") return f"{track_name} {'muted' if is_muted else 'unmuted'}" @mcp.tool() def fl_solo_track(track: int, solo: bool | None = None, mode: int = 3) -> str: """Solo or unsolo a mixer track. Args: track: Mixer track index solo: True to solo, False to unsolo, None to toggle mode: Solo mode: 1 = Solo with source tracks 2 = Solo with send tracks 3 = Solo with both source and send tracks (default) 4 = Solo track only """ conn = get_connection() result = conn.send_command("mixer.soloTrack", { "track": track, "solo": solo, "mode": mode, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" is_solo = result.get("is_solo", False) track_name = result.get("track_name", f"Track {track}") return f"{track_name} {'soloed' if is_solo else 'unsoloed'}" @mcp.tool() def fl_arm_track(track: int) -> str: """Toggle the recording arm state of a mixer track. Armed tracks will record audio when recording is enabled. Args: track: Mixer track index """ conn = get_connection() result = conn.send_command("mixer.armTrack", {"track": track}) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" is_armed = result.get("is_armed", False) track_name = result.get("track_name", f"Track {track}") return f"{track_name} recording {'armed' if is_armed else 'disarmed'}" @mcp.tool() def fl_set_track_name(track: int, name: str) -> str: """Set the name of a mixer track. Args: track: Mixer track index name: New name for the track. Empty string resets to default. """ conn = get_connection() result = conn.send_command("mixer.setTrackName", { "track": track, "name": name, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" return f"Track {track} renamed to '{name}'" @mcp.tool() def fl_set_track_color(track: int, red: int, green: int, blue: int) -> str: """Set the color of a mixer track. Args: track: Mixer track index red: Red component (0-255) green: Green component (0-255) blue: Blue component (0-255) """ conn = get_connection() result = conn.send_command("mixer.setTrackColor", { "track": track, "r": red, "g": green, "b": blue, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" return f"Track {track} color set to RGB({red}, {green}, {blue})" @mcp.tool() def fl_set_stereo_separation(track: int, separation: float) -> str: """Set the stereo separation of a mixer track. Args: track: Mixer track index separation: Stereo separation from -1.0 (merged/mono) to 1.0 (full separation). 0.0 is default. """ if not -1.0 <= separation <= 1.0: return "Error: Separation must be between -1.0 and 1.0" conn = get_connection() result = conn.send_command("mixer.setStereoSep", { "track": track, "separation": separation, }) if not result.get("success", False) and "error" in result: return f"Error: {result['error']}" return f"Track {track} stereo separation set to {separation}"

Latest Blog Posts

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/karl-andres/fl-studio-mcp'

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