/*
 * Copyright (C) 2026 Linux Studio Plugins Project <https://lsp-plug.in/>
 *           (C) 2026 Vladimir Sadovnikov <sadko4u@gmail.com>
 *
 * This file is part of lsp-plugins-art-delay
 * Created on: 3 авг. 2021 г.
 *
 * lsp-plugins-art-delay is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * lsp-plugins-art-delay is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with lsp-plugins-art-delay. If not, see <https://www.gnu.org/licenses/>.
 */

#include <lsp-plug.in/plug-fw/meta/ports.h>
#include <lsp-plug.in/plug-fw/meta/registry.h>
#include <lsp-plug.in/shared/meta/developers.h>
#include <private/meta/art_delay.h>

#define LSP_PLUGINS_ART_DELAY_VERSION_MAJOR       1
#define LSP_PLUGINS_ART_DELAY_VERSION_MINOR       0
#define LSP_PLUGINS_ART_DELAY_VERSION_MICRO       34

#define LSP_PLUGINS_ART_DELAY_VERSION  \
    LSP_MODULE_VERSION( \
        LSP_PLUGINS_ART_DELAY_VERSION_MAJOR, \
        LSP_PLUGINS_ART_DELAY_VERSION_MINOR, \
        LSP_PLUGINS_ART_DELAY_VERSION_MICRO  \
    )

namespace lsp
{
    namespace meta
    {
        static const port_item_t art_delay_lines[] =
        {
            { "1",            "art_delay.line_1"   },
            { "2",            "art_delay.line_2"   },
            { "3",            "art_delay.line_3"   },
            { "4",            "art_delay.line_4"   },
            { "5",            "art_delay.line_5"   },
            { "6",            "art_delay.line_6"   },
            { "7",            "art_delay.line_7"   },
            { "8",            "art_delay.line_8"   },
            { "9",            "art_delay.line_9"   },
            { "10",           "art_delay.line_10"  },
            { "11",           "art_delay.line_11"  },
            { "12",           "art_delay.line_12"  },
            { "13",           "art_delay.line_13"  },
            { "14",           "art_delay.line_14"  },
            { "15",           "art_delay.line_15"  },
            { "16",           "art_delay.line_16"  },
            { NULL, NULL }
        };

        static port_item_t art_delay_maxlen[] =
        {
            { "1",              NULL    },
            { "2",              NULL    },
            { "4",              NULL    },
            { "8",              NULL    },
            { "16",             NULL    },
            { "24",             NULL    },
            { "32",             NULL    },
            { "40",             NULL    },
            { "48",             NULL    },
            { "56",             NULL    },
            { "64",             NULL    },
            { "96",             NULL    },
            { "128",            NULL    },
            { "160",            NULL    },
            { "192",            NULL    },
            { "224",            NULL    },
            { "256",            NULL    },

            { NULL, NULL }
        };

        static port_item_t art_delay_references[] =
        {
            { "None",           "art_delay.none"    },

            { "1",              "art_delay.line_1"  },
            { "2",              "art_delay.line_2"  },
            { "3",              "art_delay.line_3"  },
            { "4",              "art_delay.line_4"  },
            { "5",              "art_delay.line_5"  },
            { "6",              "art_delay.line_6"  },
            { "7",              "art_delay.line_7"  },
            { "8",              "art_delay.line_8"  },
            { "9",              "art_delay.line_9"  },
            { "10",             "art_delay.line_10" },
            { "11",             "art_delay.line_11" },
            { "12",             "art_delay.line_12" },
            { "13",             "art_delay.line_13" },
            { "14",             "art_delay.line_14" },
            { "15",             "art_delay.line_15" },
            { "16",             "art_delay.line_16" },

            { NULL, NULL }
        };

        static port_item_t art_delay_tempo[] =
        {
            { "None",           "art_delay.none"    },

            { "1",              "art_delay.tempo_1" },
            { "2",              "art_delay.tempo_2" },
            { "3",              "art_delay.tempo_3" },
            { "4",              "art_delay.tempo_4" },
            { "5",              "art_delay.tempo_5" },
            { "6",              "art_delay.tempo_6" },
            { "7",              "art_delay.tempo_7" },
            { "8",              "art_delay.tempo_8" },

            { NULL, NULL }
        };

        static port_item_t art_delay_tempo_ratio[] =
        {
            { "1:1",            NULL    },
            { "1:2",            NULL    },
            { "1:3",            NULL    },
            { "2:1",            NULL    },
            { "2:3",            NULL    },
            { "3:1",            NULL    },
            { "3:2",            NULL    },

            { NULL, NULL }
        };

        #define ART_PAN_MONO(id, label, alias) \
            PAN_CTL("p" id, label " panorama", "Pan" alias, 0.0f)

        #define ART_PAN_STEREO(id, label, alias) \
            PAN_CTL("pl" id, label " left channel panorama", "Pan L" alias, -100.0f), \
            PAN_CTL("pr" id, label " right channel panorama", "Pan R" alias, 100.0f)

        #define ART_DELAY_COMMON(pan)  \
            BYPASS, \
            COMBO("lsel", "Delay line selector", "Delay selector", 0, art_delay_lines), \
            COMBO("dmax", "Maximum possible delay selector", "Max selector", 3, art_delay_maxlen), \
            pan("_in", "Input", " In"), \
            DRY_GAIN(GAIN_AMP_0_DB), \
            WET_GAIN(GAIN_AMP_0_DB), \
            DRYWET(100.0f), \
            SWITCH("dry_on", "Dry enable", "Dry on", 1.0f), \
            SWITCH("wet_on", "Wet enable", "Wet on", 1.0f), \
            SWITCH("mono", "Mono output", "Mono", 0.0f), \
            SWITCH("fb", "Feedback", "Feedback", 1.0f), \
            AMP_GAIN1("fbg", "Feedback gain", "Feed", GAIN_AMP_0_DB), \
            OUT_GAIN, \
            METER("dmaxv", "Actual delay maximum value", U_SEC, art_delay_metadata::DSEL), \
            METER("memuse", "Overall memory usage", U_BYTES, art_delay_metadata::MEMORY)

        #define ART_DELAY_TEMPO(id, sid) \
            CONTROL("tempo" #id, "Tempo " #sid, "Tempo " #sid, U_BPM, art_delay_metadata::TEMPO), \
            COMBO("ratio" #id, "Tempo " #sid " ratio", "Ratio " #sid, 0, art_delay_tempo_ratio), \
            SWITCH("sync" #id, "Tempo " #sid " sync", "Sync " #sid, 0.0f), \
            METER("atempo" #id, "Delay " #sid " actual tempo", U_BPM, art_delay_metadata::ATEMPO)

        #define ART_DELAY_PROCESSOR(id, sid, pan) \
            SWITCH("on" #id, "Delay " #sid " on", "Delay on " #sid, 0.0f), \
            SWITCH("s" #id, "Delay " #sid " solo", "Solo " #sid, 0.0f), \
            SWITCH("m" #id, "Delay " #sid " mute", "Mute " #sid, 0.0f), \
            COMBO("dref" #id, "Delay " #sid " reference", "Reference " #sid, 0, art_delay_references), \
            CONTROL("drefm" #id, "Delay " #sid " reference multiplier", "Ref mul " #sid, U_NONE, art_delay_metadata::DELAY_MULT), \
            COMBO("tref" #id, "Delay " #sid " tempo reference", "Tempo ref " #sid, 0, art_delay_tempo), \
            CONTROL("treff" #id, "Delay " #sid " bar fraction", "Bar frac " #sid, U_BAR, art_delay_metadata::DFRACTION), \
            INT_CONTROL("trefd" #id, "Delay " #sid " bar denominator", "Bar denom " #sid, U_BEAT, art_delay_metadata::DENOMINATOR), \
            CONTROL("trefm" #id, "Delay " #sid " bar multiplier", "Bar mul " #sid, U_NONE, art_delay_metadata::BAR_MULT), \
            CONTROL("frac" #id, "Delay " #sid " fraction", "Frac " #sid, U_BAR, art_delay_metadata::FRACTION), \
            INT_CONTROL("den" #id, "Delay " #sid " denominator", "Denom " #sid, U_BEAT, art_delay_metadata::DENOMINATOR), \
            CONTROL("dadd" #id, "Delay " #sid " time addition", "Add " #sid, U_SEC, art_delay_metadata::TIME), \
            SWITCH("eq" #id, "Equalizer " #sid " on", "Eqon " #sid, 0.0f), \
            SWITCH("lc" #id, "Delay " #sid " low-cut filter", "LCF on " #sid, 0.0f), \
            LOG_CONTROL("flc" #id, "Delay " #sid " low-cut frequency", "LCF freq " #sid, U_HZ, art_delay_metadata::LOW_CUT), \
            SWITCH("hc" #id, "Delay " #sid " high-cut filter", "HCF on " #sid, 0.0f), \
            LOG_CONTROL("fhc" #id, "Delay " #sid " high-cut frequency", "HCF freq " #sid, U_HZ, art_delay_metadata::HIGH_CUT), \
            LOG_CONTROL("fbs" #id, "Delay " #sid " sub-bass", "Sub lvl " #sid, U_GAIN_AMP, art_delay_metadata::BAND_GAIN), \
            LOG_CONTROL("fbb" #id, "Delay " #sid " bass", "Bass lvl " #sid, U_GAIN_AMP, art_delay_metadata::BAND_GAIN), \
            LOG_CONTROL("fbm" #id, "Delay " #sid " middle", "Mid lvl " #sid, U_GAIN_AMP, art_delay_metadata::BAND_GAIN), \
            LOG_CONTROL("fbp" #id, "Delay " #sid " presence", "Presence lvl " #sid, U_GAIN_AMP, art_delay_metadata::BAND_GAIN), \
            LOG_CONTROL("fbt" #id, "Delay " #sid " treble", "Treble lvl " #sid, U_GAIN_AMP, art_delay_metadata::BAND_GAIN), \
            pan(#id, "Delay " #sid, " " #sid), \
            AMP_GAIN10("dg" #id, "Delay " #sid " gain", "Gain " #sid, GAIN_AMP_0_DB), \
            HUE_CTL("hue" #id, "Delay " #sid " hue", float(id) / art_delay_metadata::MAX_PROCESSORS ), \
            SWITCH("fbe" #id, "Delay " #sid " feedback enable", "Feed on " #sid, 0.0f), \
            AMP_GAIN1("fbg" #id, "Delay " #sid " feedback gain", "Feed " #sid, GAIN_AMP_M_INF_DB), \
            COMBO("fbtr" #id, "Delay " #sid " feedback tempo reference", "Feed ref " #sid, 0, art_delay_tempo), \
            CONTROL("fbbf" #id, "Delay " #sid " feedback bar fraction", "Feed bar frac" #sid, U_BAR, art_delay_metadata::DFRACTION), \
            INT_CONTROL("fbbd" #id, "Delay " #sid " feedback bar denominator", "Feed bar den " #sid, U_BEAT, art_delay_metadata::DENOMINATOR), \
            CONTROL("fbbm" #id, "Delay " #sid " feedback bar multiplier", "Feed bar mul " #sid, U_NONE, art_delay_metadata::BAR_MULT), \
            CONTROL("fbf" #id, "Delay " #sid " feedback fraction", "Feed frac " #sid, U_BAR, art_delay_metadata::FRACTION), \
            INT_CONTROL("fbd" #id, "Delay " #sid " feedback denominator", "Feed denom " #sid, U_BEAT, art_delay_metadata::DENOMINATOR), \
            CONTROL("fbadd" #id, "Delay " #sid " feedback time addition", "Feed add " #sid, U_SEC, art_delay_metadata::TIME), \
            METER("adt" #id, "Delay " #sid " actual time", U_SEC, art_delay_metadata::DSEL), \
            METER("afbt" #id, "Delay " #sid " actual feedback time", U_SEC, art_delay_metadata::DSEL), \
            BLINK("door" #id, "Delay " #sid " out of range"), \
            BLINK("fbor" #id, "Delay " #sid " feedback out of range"), \
            BLINK("loop" #id, "Delay " #sid " dependency loop"), \
            METER("tval" #id, "Delay " #sid " selected tempo", U_BPM, art_delay_metadata::ATEMPO), \
            METER("fbtv" #id, "Delay " #sid " selected feedback tempo", U_BPM, art_delay_metadata::ATEMPO), \
            METER("dval" #id, "Delay " #sid " reference selected delay", U_SEC, art_delay_metadata::DSEL)

        #define ART_DELAY_TEMPOS \
            ART_DELAY_TEMPO(0, 1), \
            ART_DELAY_TEMPO(1, 2), \
            ART_DELAY_TEMPO(2, 3), \
            ART_DELAY_TEMPO(3, 4), \
            ART_DELAY_TEMPO(4, 5), \
            ART_DELAY_TEMPO(5, 6), \
            ART_DELAY_TEMPO(6, 7), \
            ART_DELAY_TEMPO(7, 8)

        #define ART_DELAY_PROCESSORS(pan) \
            ART_DELAY_PROCESSOR( 0,  1, pan), \
            ART_DELAY_PROCESSOR( 1,  2, pan), \
            ART_DELAY_PROCESSOR( 2,  3, pan), \
            ART_DELAY_PROCESSOR( 3,  4, pan), \
            ART_DELAY_PROCESSOR( 4,  5, pan), \
            ART_DELAY_PROCESSOR( 5,  6, pan), \
            ART_DELAY_PROCESSOR( 6,  7, pan), \
            ART_DELAY_PROCESSOR( 7,  8, pan), \
            ART_DELAY_PROCESSOR( 8,  9, pan), \
            ART_DELAY_PROCESSOR( 9, 10, pan), \
            ART_DELAY_PROCESSOR(10, 11, pan), \
            ART_DELAY_PROCESSOR(11, 12, pan), \
            ART_DELAY_PROCESSOR(12, 13, pan), \
            ART_DELAY_PROCESSOR(13, 14, pan), \
            ART_DELAY_PROCESSOR(14, 15, pan), \
            ART_DELAY_PROCESSOR(15, 16, pan)

        static const port_t art_delay_mono_ports[] =
        {
            // Input audio ports
            AUDIO_INPUT_MONO,
            AUDIO_OUTPUT_LEFT,
            AUDIO_OUTPUT_RIGHT,
            ART_DELAY_COMMON(ART_PAN_MONO),
            ART_DELAY_TEMPOS,
            ART_DELAY_PROCESSORS(ART_PAN_MONO),

            PORTS_END
        };

        static const port_t art_delay_stereo_ports[] =
        {
            // Input audio ports
            PORTS_STEREO_PLUGIN,
            ART_DELAY_COMMON(ART_PAN_STEREO),
            ART_DELAY_TEMPOS,
            ART_DELAY_PROCESSORS(ART_PAN_STEREO),

            PORTS_END
        };

        static const int plugin_classes[]       = { C_DELAY, -1 };
        static const int clap_features_mono[]   = { CF_AUDIO_EFFECT, CF_DELAY, CF_MONO, -1 };
        static const int clap_features_stereo[] = { CF_AUDIO_EFFECT, CF_DELAY, CF_STEREO, -1 };

        const meta::bundle_t art_delay_bundle =
        {
            "art_delay",
            "Artistic Delay",
            B_DELAYS,
            "mEP1WyLFruY",
            "This plugin allows one to construct almost any desired delay using up to 16 delay lines and 8 tempo settings. Almost all parameters can be smootly automated."
        };

        const meta::plugin_t  art_delay_mono =
        {
            "Künstlerische Verzögerung",
            "Artistic Delay Mono",
            "Artistic Delay Mono",
            "KV16M",
            &developers::v_sadovnikov,
            "art_delay_mono",
            {
                LSP_LV2_URI("art_delay_mono"),
                LSP_LV2UI_URI("art_delay_mono"),
                "vxll",
                LSP_VST3_UID("kv16m   vxll"),
                LSP_VST3UI_UID("kv16m   vxll"),
                LSP_LADSPA_ART_DELAY_BASE + 0,
                LSP_LADSPA_URI("art_delay_mono"),
                LSP_CLAP_URI("art_delay_mono"),
                LSP_GST_UID("art_delay_mono"),
            },
            LSP_PLUGINS_ART_DELAY_VERSION,
            plugin_classes,
            clap_features_mono,
            E_DUMP_STATE,
            art_delay_mono_ports,
            "plugins/delay/art_delay/mono.xml",
            NULL,
            mono_to_stereo_plugin_port_groups,
            &art_delay_bundle
        };
        LSP_REGISTER_METADATA(art_delay_mono);

        const meta::plugin_t  art_delay_stereo =
        {
            "Künstlerische Verzögerung",
            "Artistic Delay Stereo",
            "Artistic Delay Stereo",
            "KV16S",
            &developers::v_sadovnikov,
            "art_delay_stereo",
            {
                LSP_LV2_URI("art_delay_stereo"),
                LSP_LV2UI_URI("art_delay_stereo"),
                "kbbr",
                LSP_VST3_UID("kv16s   kbbr"),
                LSP_VST3UI_UID("kv16s   kbbr"),
                LSP_LADSPA_ART_DELAY_BASE + 1,
                LSP_LADSPA_URI("art_delay_stereo"),
                LSP_CLAP_URI("art_delay_stereo"),
                LSP_GST_UID("art_delay_stereo"),
            },
            LSP_PLUGINS_ART_DELAY_VERSION,
            plugin_classes,
            clap_features_stereo,
            E_DUMP_STATE,
            art_delay_stereo_ports,
            "plugins/delay/art_delay/stereo.xml",
            NULL,
            stereo_plugin_port_groups,
            &art_delay_bundle
        };
        LSP_REGISTER_METADATA(art_delay_stereo);

    } /* namespace meta */
} /* namespace lsp */
