1 /* 2 Cockos WDL License 3 4 Copyright (C) 2005 - 2015 Cockos Incorporated 5 Copyright (C) 2015 - 2017 Auburn Sounds 6 7 Portions copyright other contributors, see each source file for more information 8 9 This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. 10 11 Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 14 1. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 15 1. This notice may not be removed or altered from any source distribution. 16 */ 17 /** 18 DAW identification. 19 */ 20 module dplug.client.daw; 21 22 import core.stdc.string; 23 24 import std.string; 25 import std.conv; 26 import std.utf; 27 28 nothrow: 29 @nogc: 30 31 32 /// 33 /// Plug-in categories. 34 /// For each plug-in format, a format-specific category is obtained from this. 35 /// 36 /// Important: a `PluginCategory`doesn't affect I/O or MIDI, it's only a 37 /// hint for the goal of categorizing a plug-in in lists. 38 /// 39 /// You should use such a category enclosed with quotes in plugin.json, eg: 40 /// 41 /// Example: 42 /// 43 /// { 44 /// "category": "effectAnalysisAndMetering" 45 /// } 46 /// 47 enum PluginCategory 48 { 49 // ### Effects 50 51 /// FFT analyzers, phase display, waveform display, meters... 52 effectAnalysisAndMetering, 53 54 /// Any kind of delay, but not chorus/flanger types. 55 effectDelay, 56 57 /// Any kind of distortion: amp simulations, octavers, wave-shapers, 58 /// clippers, tape simulations... 59 effectDistortion, 60 61 /// Compressors, limiters, gates, transient designers... 62 effectDynamics, 63 64 /// Any kind of equalization. 65 effectEQ, 66 67 /// Stereoizers, panners, stereo manipulation, spatial modeling... 68 effectImaging, 69 70 /// Chorus, flanger, any kind of modulation effect... 71 effectModulation, 72 73 /// Any kind of pitch processing: shifters, pitch correction, 74 /// vocoder, formant shifting... 75 effectPitch, 76 77 /// Any kind of reverb: algorithmic, early reflections, convolution... 78 effectReverb, 79 80 /// Effects that don't fit in any other category. 81 /// eg: Dither, noise reduction... 82 effectOther, 83 84 85 // ### Instruments 86 87 /// Source that generates sound primarily from drum samples/drum synthesis. 88 instrumentDrums, 89 90 /// Source that generates sound primarily from samples, romplers... 91 instrumentSampler, 92 93 /// Source that generates sound primarily from synthesis. 94 instrumentSynthesizer, 95 96 /// Generates sound, but doesn't fit in any other category. 97 instrumentOther, 98 99 // Should never be used, except for parsing. 100 invalid = -1, 101 } 102 103 /// From a string, return the PluginCategory enumeration. 104 /// Should be reasonably fast since it will be called at compile-time. 105 /// Returns: `PluginCategory.invalid` if parsing failed. 106 PluginCategory parsePluginCategory(const(char)[] input) 107 { 108 if (input.length >= 6 && input[0..6] == "effect") 109 { 110 input = input[6..$]; 111 if (input == "AnalysisAndMetering") return PluginCategory.effectAnalysisAndMetering; 112 if (input == "Delay") return PluginCategory.effectDelay; 113 if (input == "Distortion") return PluginCategory.effectDistortion; 114 if (input == "Dynamics") return PluginCategory.effectDynamics; 115 if (input == "EQ") return PluginCategory.effectEQ; 116 if (input == "Imaging") return PluginCategory.effectImaging; 117 if (input == "Modulation") return PluginCategory.effectModulation; 118 if (input == "Pitch") return PluginCategory.effectPitch; 119 if (input == "Reverb") return PluginCategory.effectReverb; 120 if (input == "Other") return PluginCategory.effectOther; 121 } 122 else if (input.length >= 10 && input[0..10] == "instrument") 123 { 124 input = input[10..$]; 125 if (input == "Drums") return PluginCategory.instrumentDrums; 126 if (input == "Sampler") return PluginCategory.instrumentSampler; 127 if (input == "Synthesizer") return PluginCategory.instrumentSynthesizer; 128 if (input == "Other") return PluginCategory.instrumentOther; 129 } 130 return PluginCategory.invalid; 131 } 132 133 unittest 134 { 135 assert(parsePluginCategory("effectDelay") == PluginCategory.effectDelay); 136 assert(parsePluginCategory("instrumentSynthesizer") == PluginCategory.instrumentSynthesizer); 137 138 assert(parsePluginCategory("does-not-exist") == PluginCategory.invalid); 139 assert(parsePluginCategory("effect") == PluginCategory.invalid); 140 } 141 142 143 enum DAW 144 { 145 Unknown, 146 Reaper, 147 ProTools, 148 Cubase, 149 Nuendo, 150 Sonar, 151 Vegas, 152 FLStudio, 153 Samplitude, 154 AbletonLive, 155 Tracktion, 156 NTracks, 157 MelodyneStudio, 158 VSTScanner, 159 AULab, 160 Forte, 161 Chainer, 162 Audition, 163 Orion, 164 Bias, 165 SAWStudio, 166 Logic, 167 GarageBand, 168 DigitalPerformer, 169 Standalone, 170 AudioMulch, 171 StudioOne, 172 VSTHost, 173 VST3TestHost, 174 Ardour, 175 ClapValidator, 176 ClapInfo, 177 OBSStudio 178 // These hosts don't report the host name (maybe they use vendor string?) 179 // EnergyXT2 180 // MiniHost 181 } 182 183 private bool hasSubstring(const(char*) s, const(char*) sub) pure nothrow @nogc 184 { 185 return strstr(s, sub) != null; 186 } 187 188 DAW identifyDAW(const(char*) s) pure nothrow @nogc 189 { 190 // Warning: this relies on zero terminated string literals 191 if (hasSubstring(s, "reaper")) return DAW.Reaper; 192 if (hasSubstring(s, "cubase")) return DAW.Cubase; 193 if (hasSubstring(s, "reaper")) return DAW.Reaper; 194 if (hasSubstring(s, "nuendo")) return DAW.Nuendo; 195 if (hasSubstring(s, "cakewalk")) return DAW.Sonar; 196 if (hasSubstring(s, "samplitude")) return DAW.Samplitude; 197 if (hasSubstring(s, "fruity")) return DAW.FLStudio; 198 if (hasSubstring(s, "live")) return DAW.AbletonLive; 199 if (hasSubstring(s, "melodyne")) return DAW.MelodyneStudio; 200 if (hasSubstring(s, "vstmanlib")) return DAW.VSTScanner; 201 if (hasSubstring(s, "aulab")) return DAW.AULab; 202 if (hasSubstring(s, "garageband")) return DAW.GarageBand; 203 if (hasSubstring(s, "forte")) return DAW.Forte; 204 if (hasSubstring(s, "chainer")) return DAW.Chainer; 205 if (hasSubstring(s, "audition")) return DAW.Audition; 206 if (hasSubstring(s, "orion")) return DAW.Orion; 207 if (hasSubstring(s, "sawstudio")) return DAW.SAWStudio; 208 if (hasSubstring(s, "logic")) return DAW.Logic; 209 if (hasSubstring(s, "digital")) return DAW.DigitalPerformer; 210 if (hasSubstring(s, "audiomulch")) return DAW.AudioMulch; 211 if (hasSubstring(s, "presonus")) return DAW.StudioOne; 212 if (hasSubstring(s, "vst3plugintesthost")) return DAW.VST3TestHost; 213 if (hasSubstring(s, "vsthost")) return DAW.VSTHost; 214 if (hasSubstring(s, "protools")) return DAW.ProTools; 215 if (hasSubstring(s, "ardour")) return DAW.Ardour; 216 if (hasSubstring(s, "standalone")) return DAW.Standalone; 217 if (hasSubstring(s, "clap-validator")) return DAW.ClapValidator; 218 if (hasSubstring(s, "clap-info")) return DAW.ClapInfo; 219 return DAW.Unknown; 220 } 221 222 // For those DAW that uses the vendor string to put their name in 223 // Sometimes useful when identifyDAW fails and return DAW.Unknown 224 DAW identifyDAWWithVendorString(const(char*) s) pure nothrow @nogc 225 { 226 if (hasSubstring(s, "obs studio")) return DAW.OBSStudio; 227 return DAW.Unknown; 228 }