1 /* -----------------------------------------------------------------------------
2 *
3 * Giada - Your Hardcore Loopmachine
4 *
5 * -----------------------------------------------------------------------------
6 *
7 * Copyright (C) 2010-2020 Giovanni A. Zuliani | Monocasual
8 *
9 * This file is part of Giada - Your Hardcore Loopmachine.
10 *
11 * Giada - Your Hardcore Loopmachine is free software: you can
12 * redistribute it and/or modify it under the terms of the GNU General
13 * Public License as published by the Free Software Foundation, either
14 * version 3 of the License, or (at your option) any later version.
15 *
16 * Giada - Your Hardcore Loopmachine is distributed in the hope that it
17 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Giada - Your Hardcore Loopmachine. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 * -------------------------------------------------------------------------- */
26
27
28 #include <FL/Fl.H>
29 #include "gui/dialogs/mainWindow.h"
30 #include "gui/dialogs/midiIO/midiInputBase.h"
31 #include "gui/dialogs/warnings.h"
32 #include "gui/elems/basics/button.h"
33 #include "gui/elems/mainWindow/mainTransport.h"
34 #include "gui/elems/mainWindow/mainTimer.h"
35 #include "gui/elems/mainWindow/keyboard/keyboard.h"
36 #include "gui/elems/mainWindow/keyboard/channel.h"
37 #include "gui/elems/mainWindow/keyboard/channelButton.h"
38 #include "gui/elems/mainWindow/keyboard/sampleChannel.h"
39 #include "utils/gui.h"
40 #include "utils/log.h"
41 #include "utils/math.h"
42 #include "core/model/model.h"
43 #include "core/recorder.h"
44 #include "core/conf.h"
45 #include "core/recManager.h"
46 #include "core/kernelAudio.h"
47 #include "core/mixer.h"
48 #include "core/mixerHandler.h"
49 #include "core/wave.h"
50 #include "core/midiDispatcher.h"
51 #include "core/clock.h"
52 #include "core/recorderHandler.h"
53 #include "main.h"
54 #include "channel.h"
55 #include "io.h"
56
57
58 extern giada::v::gdMainWindow* G_MainWin;
59
60
61 namespace giada {
62 namespace c {
63 namespace io
64 {
65 namespace
66 {
rebuildMidiWindows_()67 void rebuildMidiWindows_()
68 {
69 u::gui::rebuildSubWindow(WID_MIDI_INPUT);
70 u::gui::rebuildSubWindow(WID_MIDI_OUTPUT);
71 }
72 } // {anonymous}
73
74 /* -------------------------------------------------------------------------- */
75 /* -------------------------------------------------------------------------- */
76 /* -------------------------------------------------------------------------- */
77
78
Channel_InputData(const m::Channel & c)79 Channel_InputData::Channel_InputData(const m::Channel& c)
80 : channelId (c.id)
81 , channelType (c.getType())
82 , enabled (c.midiLearner.state->enabled.load())
83 , velocityAsVol(c.samplePlayer ? c.samplePlayer->state->velocityAsVol.load() : 0)
84 , filter (c.midiLearner.state->filter.load())
85 , keyPress (c.midiLearner.state->keyPress.getValue())
86 , keyRelease (c.midiLearner.state->keyRelease.getValue())
87 , kill (c.midiLearner.state->kill.getValue())
88 , arm (c.midiLearner.state->arm.getValue())
89 , volume (c.midiLearner.state->volume.getValue())
90 , mute (c.midiLearner.state->mute.getValue())
91 , solo (c.midiLearner.state->solo.getValue())
92 , pitch (c.midiLearner.state->pitch.getValue())
93 , readActions (c.midiLearner.state->readActions.getValue())
94 {
95 #ifdef WITH_VST
96 for (ID id : c.pluginIds) {
97 m::Plugin& p = m::model::get(m::model::plugins, id);
98
99 PluginData pd;
100 pd.id = p.id;
101 pd.name = p.getName();
102 for (int i = 0; i < p.getNumParameters(); i++)
103 pd.params.push_back({ i, p.getParameterName(i), p.midiInParams.at(i).getValue() });
104
105 plugins.push_back(pd);
106 }
107 #endif
108 }
109
110
111 /* -------------------------------------------------------------------------- */
112
113
MidiChannel_OutputData(const m::MidiSender & s)114 MidiChannel_OutputData::MidiChannel_OutputData(const m::MidiSender& s)
115 : enabled(s.state->enabled.load())
116 , filter (s.state->filter.load())
117 {
118 }
119
120
121 /* -------------------------------------------------------------------------- */
122
123
Channel_OutputData(const m::Channel & c)124 Channel_OutputData::Channel_OutputData(const m::Channel& c)
125 : channelId (c.id)
126 , lightningEnabled(c.midiLighter.state->enabled.load())
127 , lightningPlaying(c.midiLighter.state->playing.getValue())
128 , lightningMute (c.midiLighter.state->mute.getValue())
129 , lightningSolo (c.midiLighter.state->solo.getValue())
130 {
131 if (c.getType() == ChannelType::MIDI)
132 output = std::make_optional<MidiChannel_OutputData>(*c.midiSender);
133 }
134
135
136 /* -------------------------------------------------------------------------- */
137
138
Master_InputData(const m::model::MidiIn & midiIn)139 Master_InputData::Master_InputData(const m::model::MidiIn& midiIn)
140 : enabled (midiIn.enabled)
141 , filter (midiIn.filter)
142 , rewind (midiIn.rewind)
143 , startStop (midiIn.startStop)
144 , actionRec (midiIn.actionRec)
145 , inputRec (midiIn.inputRec)
146 , volumeIn (midiIn.volumeIn)
147 , volumeOut (midiIn.volumeOut)
148 , beatDouble(midiIn.beatDouble)
149 , beatHalf (midiIn.beatHalf)
150 , metronome (midiIn.metronome)
151 {
152 }
153
154
155 /* -------------------------------------------------------------------------- */
156 /* -------------------------------------------------------------------------- */
157 /* -------------------------------------------------------------------------- */
158
159
channel_getInputData(ID channelId)160 Channel_InputData channel_getInputData(ID channelId)
161 {
162 namespace mm = m::model;
163
164 mm::ChannelsLock cl(mm::channels);
165 #ifdef WITH_VST
166 mm::PluginsLock ml(mm::plugins);
167 #endif
168
169 return Channel_InputData(mm::get(mm::channels, channelId));
170 }
171
172
173 /* -------------------------------------------------------------------------- */
174
175
channel_getOutputData(ID channelId)176 Channel_OutputData channel_getOutputData(ID channelId)
177 {
178 namespace mm = m::model;
179
180 mm::ChannelsLock cl(mm::channels);
181 return Channel_OutputData(mm::get(mm::channels, channelId));
182 }
183
184
185 /* -------------------------------------------------------------------------- */
186
187
master_getInputData()188 Master_InputData master_getInputData()
189 {
190 namespace mm = m::model;
191
192 mm::MidiInLock l(mm::midiIn);
193 return Master_InputData(*mm::midiIn.get());
194 }
195
196
197 /* -------------------------------------------------------------------------- */
198
199
channel_enableMidiLearn(ID channelId,bool v)200 void channel_enableMidiLearn(ID channelId, bool v)
201 {
202 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
203 {
204 c.midiLearner.state->enabled.store(v);
205 });
206 rebuildMidiWindows_();
207 }
208
209
210 /* -------------------------------------------------------------------------- */
211
212
channel_enableMidiLightning(ID channelId,bool v)213 void channel_enableMidiLightning(ID channelId, bool v)
214 {
215 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
216 {
217 c.midiLighter.state->enabled.store(v);
218 });
219 rebuildMidiWindows_();
220 }
221
222
223 /* -------------------------------------------------------------------------- */
224
225
channel_enableMidiOutput(ID channelId,bool v)226 void channel_enableMidiOutput(ID channelId, bool v)
227 {
228 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
229 {
230 c.midiSender->state->enabled.store(v);
231 });
232 rebuildMidiWindows_();
233 }
234
235
236 /* -------------------------------------------------------------------------- */
237
238
channel_enableVelocityAsVol(ID channelId,bool v)239 void channel_enableVelocityAsVol(ID channelId, bool v)
240 {
241 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
242 {
243 c.samplePlayer->state->velocityAsVol.store(v);
244 });
245 }
246
247
248 /* -------------------------------------------------------------------------- */
249
250
channel_setMidiInputFilter(ID channelId,int ch)251 void channel_setMidiInputFilter(ID channelId, int ch)
252 {
253 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
254 {
255 c.midiLearner.state->filter.store(ch);
256 });
257 }
258
259
channel_setMidiOutputFilter(ID channelId,int ch)260 void channel_setMidiOutputFilter(ID channelId, int ch)
261 {
262 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
263 {
264 c.midiSender->state->filter.store(ch);
265 });
266 }
267
268
269 /* -------------------------------------------------------------------------- */
270
271
channel_setKey(ID channelId,int k)272 void channel_setKey(ID channelId, int k)
273 {
274 m::model::onGet(m::model::channels, channelId, [&](m::Channel& c)
275 {
276 c.state->key.store(k);
277 }, /*rebuild=*/true);
278 }
279
280
281 /* -------------------------------------------------------------------------- */
282
283
channel_startMidiLearn(int param,ID channelId)284 void channel_startMidiLearn(int param, ID channelId)
285 {
286 m::midiDispatcher::startChannelLearn(param, channelId, rebuildMidiWindows_);
287 }
288
289
master_startMidiLearn(int param)290 void master_startMidiLearn(int param)
291 {
292 m::midiDispatcher::startMasterLearn(param, rebuildMidiWindows_);
293 }
294
295
296 #ifdef WITH_VST
297
plugin_startMidiLearn(int paramIndex,ID pluginId)298 void plugin_startMidiLearn(int paramIndex, ID pluginId)
299 {
300 m::midiDispatcher::startPluginLearn(paramIndex, pluginId, rebuildMidiWindows_);
301 }
302
303 #endif
304
305
306 /* -------------------------------------------------------------------------- */
307
308
stopMidiLearn()309 void stopMidiLearn()
310 {
311 m::midiDispatcher::stopLearn();
312 rebuildMidiWindows_();
313 }
314
315
316 /* -------------------------------------------------------------------------- */
317
318
channel_clearMidiLearn(int param,ID channelId)319 void channel_clearMidiLearn(int param, ID channelId)
320 {
321 m::midiDispatcher::clearChannelLearn(param, channelId, rebuildMidiWindows_);
322 }
323
324
master_clearMidiLearn(int param)325 void master_clearMidiLearn (int param)
326 {
327 m::midiDispatcher::clearMasterLearn(param, rebuildMidiWindows_);
328 }
329
330
331 #ifdef WITH_VST
332
plugin_clearMidiLearn(int param,ID pluginId)333 void plugin_clearMidiLearn (int param, ID pluginId)
334 {
335 m::midiDispatcher::clearPluginLearn(param, pluginId, rebuildMidiWindows_);
336 }
337
338 #endif
339
340
341 /* -------------------------------------------------------------------------- */
342
343
master_enableMidiLearn(bool v)344 void master_enableMidiLearn(bool v)
345 {
346 m::model::onSwap(m::model::midiIn, [&](m::model::MidiIn& m)
347 {
348 m.enabled = v;
349 });
350 rebuildMidiWindows_();
351 }
352
353
354 /* -------------------------------------------------------------------------- */
355
356
master_setMidiFilter(int c)357 void master_setMidiFilter(int c)
358 {
359 m::model::onSwap(m::model::midiIn, [&](m::model::MidiIn& m)
360 {
361 m.filter = c;
362 });
363 }
364 }}} // giada::c::io::
365