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