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 }