<UVI4>
    <Program Name="Program" Bypass="0" Gain="1" Pan="0" DisplayName="FX Controls" TransposeOctaves="0" TransposeSemiTones="0" OutputName="" Polyphony="16" NotePolyphony="0" ProgramPath="./FXControls.M5p" LoopProgram="0" Streaming="1" BypassInsertFX="0">
        <ControlSignalSources/>
        <EventProcessors>
            <ScriptProcessor Name="EventProcessor0" Bypass="0" API_version="13">
                <Properties ScriptPath="./FXControls.lua"/>
                <script><![CDATA[--------------------------------------------------------------------------------
--! @title FX Controls
--! @brief Bind a Program insert effect to the script UI
--! @category UIHelpers
--!
--! Builds a small control panel for the first insert effect on the Program, here
--! a "Drive". The Param* widgets bind straight to the effect's parameters: each
--! control inherits its range, default and unit from the parameter and stays in
--! sync with host automation, modulation and preset changes - no changed callback
--! is needed to drive the effect. ParameterValue adds a non-visual binding, used
--! here to read a parameter's live value from script.
--!
--! The parameter names ("Bypass", "DriveAmount", "Mode") are the internal names of
--! the Drive effect; point Program.inserts[1] at that effect, or swap the names
--! for those of your own FX.
--------------------------------------------------------------------------------

-- the effect we want to control: first insert on the Program
local fx = Program.inserts[1]

setBackgroundColour("1a1a1a")

local panel = Panel{"drive"}
panel.bounds = {20, 20, 420, 150}
panel.backgroundColour = "2a2a2a"

-- No ranges are given: they are inherited from the bound parameter.
-- Bounds are relative to the panel.
local bypass = panel:ParamOnOffButton(fx, "Bypass")       -- boolean parameter
bypass.bounds = {25, 58, 110, 36}

local amount = panel:ParamKnob(fx, "DriveAmount")         -- 0..1, shown as %
amount.bounds = {180, 25, 100, 100}

local mode = panel:ParamMenu(fx, "Mode")                  -- enumerated parameter (entries from the param)
mode.bounds = {290, 54, 110, 44}

--------------------------------------------------------------------------------
-- Non-visual (logical) binding: read the live drive amount from script without
-- placing a control for it. ParameterValue draws nothing; it just exposes the
-- parameter through its .value.
--------------------------------------------------------------------------------
local driveValue = ParameterValue(fx, "DriveAmount")

bypass.changed = function(self)
    local state = self.value and "bypassed" or "active"
    print(string.format("Drive %s (amount = %d%%)", state, math.floor(driveValue.value * 100 + 0.5)))
end

setSize(460, 190)
makePerformanceView()
]]></script>
            </ScriptProcessor>
        </EventProcessors>
        <Inserts>
            <Drive Name="Drive" Bypass="0" DriveAmount="0.5" Mode="0" Oversampling="0"/>
        </Inserts>
        <Layers>
            <Layer Name="Layer 0" Bypass="0" Gain="1" Pan="0" Mute="0" MidiMute="0" Solo="0" DisplayName="Layer 1" OutputName="" LowKey="0" HighKey="127" CustomPolyphony="0" PlayMode="0" PortamentoTime="0.029999999" PortamentoMode="0" NumVoicesPerNote="1" VelocityCurve="0" BypassInsertFX="0">
                <Properties Color="ffff0000"/>
                <ControlSignalSources/>
                <BusRouters/>
                <Keygroups>
                    <Keygroup Name="Keygroup 0" Bypass="0" Gain="1" Pan="0" DisplayName="Keygroup 1" OutputName="" ExclusiveGroup="0" LowKey="0" HighKey="127" LowVelocity="1" HighVelocity="127" LowKeyFade="0" HighKeyFade="0" LowVelocityFade="0" HighVelocityFade="0" TriggerMode="0" TriggerSync="0" TriggerRule="0" LatchTrigger="0" FXPostGain="1" BypassInsertFX="0">
                        <Connections>
                            <SignalConnection Name="AmpEnvMod" Ratio="1" Source="Amp. Env" Destination="Gain" Mapper="" ConnectionMode="0" Bypass="0" Inverted="0"/>
                        </Connections>
                        <ControlSignalSources>
                            <DAHDSR Name="Amp. Env" Bypass="0" DelayTime="0" AttackTime="0.0089999996" AttackCurve="0.5" HoldTime="0" DecayTime="0.17399999" DecayCurve="-0.97000003" SustainLevel="1" ReleaseTime="0.050000001" ReleaseCurve="-0.97000003" DisplayName="Amp. Env" VelocityAmount="0.82999998" VelocitySens="0.75" Retrigger="1" NoteOffRetrigger="0"/>
                        </ControlSignalSources>
                        <Inserts/>
                        <BusRouters/>
                        <Oscillators>
                            <MinBlepGenerator Name="Oscillator" Bypass="0" Waveform="1" Pwm="0.5" StartPhase="0" Polarity="0" HardSync="0" HardSyncShift="0" NumOscillators="1" MultiOscSpread="0.1" Stereo="0" PhaseSpread="0" DetuneMode="0" StereoSpread="0.1" StereoSpreadMode="0" CoarseTune="0" FineTune="0" Gain="1" Pitch="0" NoteTracking="1" BaseNote="60" DisplayName="Oscillator 1"/>
                        </Oscillators>
                    </Keygroup>
                </Keygroups>
            </Layer>
        </Layers>
    </Program>
</UVI4>
