fx_tools.py•9.08 kB
import os
from pathlib import Path
import reapy
from reapy import reascript_api as RPR
class FXTools:
    """Tools for managing VST instruments and effects in REAPER."""
    
    def __init__(self, config):
        """
        Initialize FXTools with configuration.
        
        Args:
            config (dict): Configuration dictionary
        """
        self.config = config
        self.vst_directories = config.get("vst_directories", [])
    
    def add_vst_instrument(self, track_id, vst_name):
        """
        Add a VST instrument to the specified track.
        
        Args:
            track_id (int): Track ID
            vst_name (str): VST instrument name
            
        Returns:
            dict: FX information
        """
        try:
            # Get track by ID
            track = reapy.Track.from_id(track_id)
            
            # Add VST instrument
            fx_index = track.add_fx(vst_name)
            
            if fx_index < 0:
                return {
                    "success": False,
                    "error": f"VST instrument not found: {vst_name}"
                }
            
            # Get the FX
            fx = track.fxs[fx_index]
            
            # Configure track for MIDI input
            track.input_mode = reapy.InputMode.ALL_MIDI
            
            return {
                "success": True,
                "fx_id": fx.id,
                "index": fx_index,
                "name": fx.name,
                "track_id": track_id,
                "preset": fx.preset_name
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }
    
    def add_vst_effect(self, track_id, vst_name):
        """
        Add a VST effect to the specified track.
        
        Args:
            track_id (int): Track ID
            vst_name (str): VST effect name
            
        Returns:
            dict: FX information
        """
        try:
            # Get track by ID
            track = reapy.Track.from_id(track_id)
            
            # Add VST effect
            fx_index = track.add_fx(vst_name)
            
            if fx_index < 0:
                return {
                    "success": False,
                    "error": f"VST effect not found: {vst_name}"
                }
            
            # Get the FX
            fx = track.fxs[fx_index]
            
            return {
                "success": True,
                "fx_id": fx.id,
                "index": fx_index,
                "name": fx.name,
                "track_id": track_id,
                "preset": fx.preset_name
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }
    
    def set_vst_parameter(self, track_id, fx_id, param_index, value):
        """
        Set a parameter value for the specified VST.
        
        Args:
            track_id (int): Track ID
            fx_id (int): FX ID
            param_index (int): Parameter index
            value (float): Parameter value (normalized 0.0-1.0)
            
        Returns:
            dict: Result of the operation
        """
        try:
            # Get track by ID
            track = reapy.Track.from_id(track_id)
            
            # Find FX by ID
            fx = None
            for i in range(track.n_fxs):
                current_fx = track.fxs[i]
                if current_fx.id == fx_id:
                    fx = current_fx
                    break
            
            if fx is None:
                return {
                    "success": False,
                    "error": f"FX with ID {fx_id} not found on track {track_id}"
                }
            
            # Set parameter value
            fx.params[param_index].normalized_value = value
            
            # Get parameter name
            param_name = fx.params[param_index].name
            
            return {
                "success": True,
                "fx_id": fx_id,
                "param_index": param_index,
                "param_name": param_name,
                "value": value,
                "track_id": track_id
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }
    
    def get_fx_parameters(self, track_id, fx_id):
        """
        Get all parameters for the specified FX.
        
        Args:
            track_id (int): Track ID
            fx_id (int): FX ID
            
        Returns:
            dict: FX parameters
        """
        try:
            # Get track by ID
            track = reapy.Track.from_id(track_id)
            
            # Find FX by ID
            fx = None
            for i in range(track.n_fxs):
                current_fx = track.fxs[i]
                if current_fx.id == fx_id:
                    fx = current_fx
                    break
            
            if fx is None:
                return {
                    "success": False,
                    "error": f"FX with ID {fx_id} not found on track {track_id}"
                }
            
            # Get parameters
            params = []
            for i in range(fx.n_params):
                param = fx.params[i]
                params.append({
                    "index": i,
                    "name": param.name,
                    "value": param.normalized_value,
                    "formatted_value": param.formatted_value
                })
            
            return {
                "success": True,
                "fx_id": fx_id,
                "name": fx.name,
                "track_id": track_id,
                "preset": fx.preset_name,
                "parameters": params
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }
    
    def load_fx_preset(self, track_id, fx_id, preset_name):
        """
        Load a preset for the specified FX.
        
        Args:
            track_id (int): Track ID
            fx_id (int): FX ID
            preset_name (str): Preset name
            
        Returns:
            dict: Result of the operation
        """
        try:
            # Get track by ID
            track = reapy.Track.from_id(track_id)
            
            # Find FX by ID
            fx = None
            for i in range(track.n_fxs):
                current_fx = track.fxs[i]
                if current_fx.id == fx_id:
                    fx = current_fx
                    break
            
            if fx is None:
                return {
                    "success": False,
                    "error": f"FX with ID {fx_id} not found on track {track_id}"
                }
            
            # Load preset
            fx.preset_name = preset_name
            
            return {
                "success": True,
                "fx_id": fx_id,
                "name": fx.name,
                "track_id": track_id,
                "preset": fx.preset_name
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }
    
    def list_available_vsts(self, vst_type="all"):
        """
        List all available VSTs of the specified type.
        
        Args:
            vst_type (str): VST type (all, instrument, effect)
            
        Returns:
            dict: List of available VSTs
        """
        try:
            # Use REAPER's built-in function to get VST list
            # This is a simplified implementation - in practice, you'd need to parse
            # REAPER's FX browser or use a more complex approach
            
            # For now, return some common VSTs as an example
            common_instruments = [
                "ReaSynth",
                "ReaSamplOmatic5000",
                "VSTi: Surge XT (Surge Synth Team)",
                "VSTi: Vital (Vital)",
                "VSTi: TAL-NoiseMaker (Togu Audio Line)"
            ]
            
            common_effects = [
                "ReaEQ",
                "ReaComp",
                "ReaDelay",
                "ReaVerb",
                "VST: FabFilter Pro-Q 3 (FabFilter)",
                "VST: Valhalla VintageVerb (Valhalla DSP)",
                "VST: Soundtoys EchoBoy (Soundtoys)"
            ]
            
            if vst_type.lower() == "instrument":
                vsts = common_instruments
            elif vst_type.lower() == "effect":
                vsts = common_effects
            else:
                vsts = common_instruments + common_effects
            
            return {
                "success": True,
                "vst_type": vst_type,
                "vsts": vsts
            }
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }