hydrogen 1.2.6
MidiAction.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2025 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22#include <QObject>
23
26#include <core/EventQueue.h>
28#include <core/Hydrogen.h>
29
34#include <core/Basics/Pattern.h>
36#include <core/Basics/Song.h>
38
40#include <core/MidiAction.h>
41
42#include <core/Basics/Drumkit.h>
43
44// #include <QFileInfo>
45
46#include <sstream>
47
48using namespace H2Core;
49
71
72Action::Action( QString sType ) {
73 m_sType = sType;
74 m_sParameter1 = "0";
75 m_sParameter2 = "0";
76 m_sParameter3 = "0";
77 m_sValue = "0";
78}
79
80Action::Action( std::shared_ptr<Action> pOther ) {
81 m_sType = pOther->m_sType;
82 m_sParameter1 = pOther->m_sParameter1;
83 m_sParameter2 = pOther->m_sParameter2;
84 m_sParameter3 = pOther->m_sParameter3;
85 m_sValue = pOther->m_sValue;
86}
87
88bool Action::isNull() const {
90}
91
92bool Action::isEquivalentTo( std::shared_ptr<Action> pOther ) {
93 if ( pOther == nullptr ) {
94 return false;
95 }
96
97 return ( m_sType == pOther->m_sType &&
98 m_sParameter1 == pOther->m_sParameter1 &&
99 m_sParameter2 == pOther->m_sParameter2 &&
100 m_sParameter3 == pOther->m_sParameter3 );
101}
102
103QString Action::toQString( const QString& sPrefix, bool bShort ) const {
104 QString s = Base::sPrintIndention;
105 QString sOutput;
106 if ( ! bShort ) {
107 sOutput = QString( "%1[Action]\n" ).arg( sPrefix )
108 .append( QString( "%1%2m_sType: %3\n" ).arg( sPrefix ).arg( s ).arg( m_sType ) )
109 .append( QString( "%1%2m_sValue: %3\n" ).arg( sPrefix ).arg( s ).arg( m_sValue ) )
110 .append( QString( "%1%2m_sParameter1: %3\n" ).arg( sPrefix ).arg( s ).arg( m_sParameter1 ) )
111 .append( QString( "%1%2m_sParameter2: %3\n" ).arg( sPrefix ).arg( s ).arg( m_sParameter2 ) )
112 .append( QString( "%1%2m_sParameter3: %3\n" ).arg( sPrefix ).arg( s ).arg( m_sParameter3 ) );
113 } else {
114 sOutput = QString( "[Action]" )
115 .append( QString( " m_sType: %1" ).arg( m_sType ) )
116 .append( QString( ", m_sValue: %1" ).arg( m_sValue ) )
117 .append( QString( ", m_sParameter1: %1" ).arg( m_sParameter1 ) )
118 .append( QString( ", m_sParameter2: %1" ).arg( m_sParameter2 ) )
119 .append( QString( ", m_sParameter3: %1" ).arg( m_sParameter3 ) );
120 }
121
122 return sOutput;
123}
124
139
141 __instance = this;
142
144 /*
145 the m_actionMap holds all Action identifiers which hydrogen is able to interpret.
146 it holds pointer to member function
147 */
148 m_actionMap.insert(std::make_pair("PLAY", std::make_pair( &MidiActionManager::play, 0 ) ));
149 m_actionMap.insert(std::make_pair("PLAY/STOP_TOGGLE", std::make_pair( &MidiActionManager::play_stop_pause_toggle, 0 ) ));
150 m_actionMap.insert(std::make_pair("PLAY/PAUSE_TOGGLE", std::make_pair( &MidiActionManager::play_stop_pause_toggle, 0 ) ));
151 m_actionMap.insert(std::make_pair("STOP", std::make_pair( &MidiActionManager::stop, 0 ) ));
152 m_actionMap.insert(std::make_pair("PAUSE", std::make_pair( &MidiActionManager::pause, 0 ) ));
153 m_actionMap.insert(std::make_pair("RECORD_READY", std::make_pair( &MidiActionManager::record_ready, 0 ) ));
154 m_actionMap.insert(std::make_pair("RECORD/STROBE_TOGGLE", std::make_pair( &MidiActionManager::record_strobe_toggle, 0 ) ));
155 m_actionMap.insert(std::make_pair("RECORD_STROBE", std::make_pair( &MidiActionManager::record_strobe, 0 ) ));
156 m_actionMap.insert(std::make_pair("RECORD_EXIT", std::make_pair( &MidiActionManager::record_exit, 0 ) ));
157 m_actionMap.insert(std::make_pair("MUTE", std::make_pair( &MidiActionManager::mute, 0 ) ));
158 m_actionMap.insert(std::make_pair("UNMUTE", std::make_pair( &MidiActionManager::unmute, 0 ) ));
159 m_actionMap.insert(std::make_pair("MUTE_TOGGLE", std::make_pair( &MidiActionManager::mute_toggle, 0 ) ));
160 m_actionMap.insert(std::make_pair("STRIP_MUTE_TOGGLE", std::make_pair( &MidiActionManager::strip_mute_toggle, 1 ) ));
161 m_actionMap.insert(std::make_pair("STRIP_SOLO_TOGGLE", std::make_pair( &MidiActionManager::strip_solo_toggle, 1 ) ));
162 m_actionMap.insert(std::make_pair(">>_NEXT_BAR", std::make_pair( &MidiActionManager::next_bar, 0 ) ));
163 m_actionMap.insert(std::make_pair("<<_PREVIOUS_BAR", std::make_pair( &MidiActionManager::previous_bar, 0 ) ));
164 m_actionMap.insert(std::make_pair("BPM_INCR", std::make_pair( &MidiActionManager::bpm_increase, 1 ) ));
165 m_actionMap.insert(std::make_pair("BPM_DECR", std::make_pair( &MidiActionManager::bpm_decrease, 1 ) ));
166 m_actionMap.insert(std::make_pair("BPM_CC_RELATIVE", std::make_pair( &MidiActionManager::bpm_cc_relative, 1 ) ));
167 m_actionMap.insert(std::make_pair("BPM_FINE_CC_RELATIVE", std::make_pair( &MidiActionManager::bpm_fine_cc_relative, 1 ) ));
168 m_actionMap.insert(std::make_pair("MASTER_VOLUME_RELATIVE", std::make_pair( &MidiActionManager::master_volume_relative, 0 ) ));
169 m_actionMap.insert(std::make_pair("MASTER_VOLUME_ABSOLUTE", std::make_pair( &MidiActionManager::master_volume_absolute, 0 ) ));
170 m_actionMap.insert(std::make_pair("STRIP_VOLUME_RELATIVE", std::make_pair( &MidiActionManager::strip_volume_relative, 1 ) ));
171 m_actionMap.insert(std::make_pair("STRIP_VOLUME_ABSOLUTE", std::make_pair( &MidiActionManager::strip_volume_absolute, 1 ) ));
172 m_actionMap.insert(std::make_pair("EFFECT_LEVEL_ABSOLUTE", std::make_pair( &MidiActionManager::effect_level_absolute, 2 ) ));
173 m_actionMap.insert(std::make_pair("EFFECT_LEVEL_RELATIVE", std::make_pair( &MidiActionManager::effect_level_relative, 2 ) ));
174 m_actionMap.insert(std::make_pair("GAIN_LEVEL_ABSOLUTE", std::make_pair( &MidiActionManager::gain_level_absolute, 3 ) ));
175 m_actionMap.insert(std::make_pair("PITCH_LEVEL_ABSOLUTE", std::make_pair( &MidiActionManager::pitch_level_absolute, 3 ) ));
176 m_actionMap.insert(std::make_pair("SELECT_NEXT_PATTERN", std::make_pair( &MidiActionManager::select_next_pattern, 1 ) ));
177 m_actionMap.insert(std::make_pair("SELECT_ONLY_NEXT_PATTERN", std::make_pair( &MidiActionManager::select_only_next_pattern, 1 ) ));
178 m_actionMap.insert(std::make_pair("SELECT_NEXT_PATTERN_CC_ABSOLUTE", std::make_pair( &MidiActionManager::select_next_pattern_cc_absolute, 0 ) ));
179 m_actionMap.insert(std::make_pair("SELECT_ONLY_NEXT_PATTERN_CC_ABSOLUTE", std::make_pair( &MidiActionManager::select_only_next_pattern_cc_absolute, 0 ) ));
180 m_actionMap.insert(std::make_pair("SELECT_NEXT_PATTERN_RELATIVE", std::make_pair( &MidiActionManager::select_next_pattern_relative, 1 ) ));
181 m_actionMap.insert(std::make_pair("SELECT_AND_PLAY_PATTERN", std::make_pair( &MidiActionManager::select_and_play_pattern, 1 ) ));
182 m_actionMap.insert(std::make_pair("PAN_RELATIVE", std::make_pair( &MidiActionManager::pan_relative, 1 ) ));
183 m_actionMap.insert(std::make_pair("PAN_ABSOLUTE", std::make_pair( &MidiActionManager::pan_absolute, 1 ) ));
184 m_actionMap.insert(std::make_pair("PAN_ABSOLUTE_SYM", std::make_pair( &MidiActionManager::pan_absolute_sym, 1 ) ));
185 m_actionMap.insert(std::make_pair("INSTRUMENT_PITCH",
186 std::make_pair( &MidiActionManager::instrument_pitch, 1 ) ));
187 m_actionMap.insert(std::make_pair("FILTER_CUTOFF_LEVEL_ABSOLUTE", std::make_pair( &MidiActionManager::filter_cutoff_level_absolute, 1 ) ));
188 m_actionMap.insert(std::make_pair("BEATCOUNTER", std::make_pair( &MidiActionManager::beatcounter, 0 ) ));
189 m_actionMap.insert(std::make_pair("TAP_TEMPO", std::make_pair( &MidiActionManager::tap_tempo, 0 ) ));
190 m_actionMap.insert(std::make_pair("PLAYLIST_SONG", std::make_pair( &MidiActionManager::playlist_song, 1 ) ));
191 m_actionMap.insert(std::make_pair("PLAYLIST_NEXT_SONG", std::make_pair( &MidiActionManager::playlist_next_song, 0 ) ));
192 m_actionMap.insert(std::make_pair("PLAYLIST_PREV_SONG", std::make_pair( &MidiActionManager::playlist_previous_song, 0 ) ));
193 m_actionMap.insert(std::make_pair("TOGGLE_METRONOME", std::make_pair( &MidiActionManager::toggle_metronome, 0 ) ));
194 m_actionMap.insert(std::make_pair("SELECT_INSTRUMENT", std::make_pair( &MidiActionManager::select_instrument, 0 ) ));
195 m_actionMap.insert(std::make_pair("UNDO_ACTION", std::make_pair( &MidiActionManager::undo_action, 0 ) ));
196 m_actionMap.insert(std::make_pair("REDO_ACTION", std::make_pair( &MidiActionManager::redo_action, 0 ) ));
197 m_actionMap.insert(std::make_pair("CLEAR_SELECTED_INSTRUMENT", std::make_pair(
199 m_actionMap.insert(std::make_pair("CLEAR_PATTERN", std::make_pair(
201 /*
202 the m_actionList holds all Action identifiers which hydrogen is able to interpret.
203 */
204 m_actionList <<"";
205 for ( const auto& ppAction : m_actionMap ) {
206 m_actionList << ppAction.first;
207 }
208}
209
210
212 //INFOLOG( "ActionManager delete" );
213 __instance = nullptr;
214}
215
217 if ( __instance == nullptr ) {
219 }
220}
221
222bool MidiActionManager::play( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
223 // Preventive measure to avoid bad things.
224 if ( pHydrogen->getSong() == nullptr ) {
225 ERRORLOG( "No song set yet" );
226 return false;
227 }
228
229 if ( pHydrogen->getAudioEngine()->getState() == AudioEngine::State::Ready ) {
230 pHydrogen->sequencer_play();
231 }
232 return true;
233}
234
235bool MidiActionManager::pause( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
236 // Preventive measure to avoid bad things.
237 if ( pHydrogen->getSong() == nullptr ) {
238 ERRORLOG( "No song set yet" );
239 return false;
240 }
241
242 pHydrogen->sequencer_stop();
243 return true;
244}
245
246bool MidiActionManager::stop( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
247 // Preventive measure to avoid bad things.
248 if ( pHydrogen->getSong() == nullptr ) {
249 ERRORLOG( "No song set yet" );
250 return false;
251 }
252
253 pHydrogen->sequencer_stop();
254 return pHydrogen->getCoreActionController()->locateToColumn( 0 );
255}
256
257bool MidiActionManager::play_stop_pause_toggle( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
258 // Preventive measure to avoid bad things.
259 if ( pHydrogen->getSong() == nullptr ) {
260 ERRORLOG( "No song set yet" );
261 return false;
262 }
263
264 QString sActionString = pAction->getType();
265 switch ( pHydrogen->getAudioEngine()->getState() )
266 {
268 pHydrogen->sequencer_play();
269 break;
270
272 if( sActionString == "PLAY/STOP_TOGGLE" ) {
273 pHydrogen->getCoreActionController()->locateToColumn( 0 );
274 }
275 pHydrogen->sequencer_stop();
276 break;
277
278 default:
279 ERRORLOG( "[Hydrogen::ActionManager(PLAY): Unhandled case" );
280 break;
281 }
282
283 return true;
284}
285
286//mutes the master, not a single strip
287bool MidiActionManager::mute( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
288 // Preventive measure to avoid bad things.
289 if ( pHydrogen->getSong() == nullptr ) {
290 ERRORLOG( "No song set yet" );
291 return false;
292 }
293
294 return pHydrogen->getCoreActionController()->setMasterIsMuted( true );
295}
296
297bool MidiActionManager::unmute( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
298 // Preventive measure to avoid bad things.
299 if ( pHydrogen->getSong() == nullptr ) {
300 ERRORLOG( "No song set yet" );
301 return false;
302 }
303
304 return pHydrogen->getCoreActionController()->setMasterIsMuted( false );
305}
306
307bool MidiActionManager::mute_toggle( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
308 // Preventive measure to avoid bad things.
309 if ( pHydrogen->getSong() == nullptr ) {
310 ERRORLOG( "No song set yet" );
311 return false;
312 }
313
314 return pHydrogen->getCoreActionController()->setMasterIsMuted( !pHydrogen->getSong()->getIsMuted() );
315}
316
317bool MidiActionManager::strip_mute_toggle( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
318 auto pSong = pHydrogen->getSong();
319
320 // Preventive measure to avoid bad things.
321 if ( pSong == nullptr ) {
322 ERRORLOG( "No song set yet" );
323 return false;
324 }
325
326 bool ok;
327 int nLine = pAction->getParameter1().toInt(&ok,10);
328
329 auto pInstrList = pSong->getInstrumentList();
330
331 auto pInstr = pInstrList->get( nLine );
332 if ( pInstr == nullptr ) {
333 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
334 return false;
335 }
336
337 return pHydrogen->getCoreActionController()->setStripIsMuted( nLine, !pInstr->is_muted() );
338}
339
340bool MidiActionManager::strip_solo_toggle( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
341 auto pSong = pHydrogen->getSong();
342
343 // Preventive measure to avoid bad things.
344 if ( pSong == nullptr ) {
345 ERRORLOG( "No song set yet" );
346 return false;
347 }
348
349 bool ok;
350 int nLine = pAction->getParameter1().toInt(&ok,10);
351
352 auto pInstrList = pSong->getInstrumentList();
353
354 auto pInstr = pInstrList->get( nLine );
355 if ( pInstr == nullptr ) {
356 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
357 return false;
358 }
359
360 return pHydrogen->getCoreActionController()->setStripIsSoloed( nLine, !pInstr->is_soloed() );
361}
362
363bool MidiActionManager::beatcounter( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
364 // Preventive measure to avoid bad things.
365 if ( pHydrogen->getSong() == nullptr ) {
366 ERRORLOG( "No song set yet" );
367 return false;
368 }
369
370 return pHydrogen->handleBeatCounter();
371}
372
373bool MidiActionManager::tap_tempo( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
374 // Preventive measure to avoid bad things.
375 if ( pHydrogen->getSong() == nullptr ) {
376 ERRORLOG( "No song set yet" );
377 return false;
378 }
379
380 pHydrogen->onTapTempoAccelEvent();
381 return true;
382}
383
384bool MidiActionManager::select_next_pattern( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
385 bool ok;
386 return nextPatternSelection( pAction->getParameter1().toInt(&ok,10) );
387}
388
389
390bool MidiActionManager::select_next_pattern_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
391 bool ok;
393 pAction->getParameter1().toInt(&ok,10) );
394}
395
396bool MidiActionManager::select_next_pattern_cc_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
397 bool ok;
398 return nextPatternSelection( pAction->getValue().toInt(&ok,10) );
399}
400
401bool MidiActionManager::nextPatternSelection( int nPatternNumber ) {
402 auto pHydrogen = Hydrogen::get_instance();
403 auto pSong = pHydrogen->getSong();
404
405 // Preventive measure to avoid bad things.
406 if ( pSong == nullptr ) {
407 ERRORLOG( "No song set yet" );
408 return false;
409 }
410
411 if ( nPatternNumber > pSong->getPatternList()->size() - 1 ||
412 nPatternNumber < 0 ) {
413 ERRORLOG( QString( "Provided value [%1] out of bound [0,%2]" ).arg( nPatternNumber )
414 .arg( pSong->getPatternList()->size() - 1 ) );
415 return false;
416 }
417
418 if ( pHydrogen->getPatternMode() == Song::PatternMode::Selected ) {
419 pHydrogen->setSelectedPatternNumber( nPatternNumber );
420 }
421 else if ( pHydrogen->getPatternMode() == Song::PatternMode::Stacked ) {
422 pHydrogen->toggleNextPattern( nPatternNumber );
423 }
424
425 return true;
426}
427
428bool MidiActionManager::select_only_next_pattern( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
429 bool ok;
430 return onlyNextPatternSelection( pAction->getParameter1().toInt(&ok,10) );
431}
432
433bool MidiActionManager::select_only_next_pattern_cc_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
434 bool ok;
435 return onlyNextPatternSelection( pAction->getValue().toInt(&ok,10) );
436}
437
439 auto pHydrogen = Hydrogen::get_instance();
440 auto pSong = pHydrogen->getSong();
441
442 // Preventive measure to avoid bad things.
443 if ( pSong == nullptr ) {
444 ERRORLOG( "No song set yet" );
445 return false;
446 }
447
448 if ( nPatternNumber > pSong->getPatternList()->size() -1 ||
449 nPatternNumber < 0 ) {
450 if ( pHydrogen->getPatternMode() == Song::PatternMode::Selected ) {
451 ERRORLOG( QString( "Provided pattern number [%1] out of bound [0,%2]." )
452 .arg( nPatternNumber )
453 .arg( pSong->getPatternList()->size() - 1 ) );
454 return false;
455 }
456 else {
457 INFOLOG( QString( "Provided pattern number [%1] out of bound [0,%2]. All patterns will be deselected." )
458 .arg( nPatternNumber )
459 .arg( pSong->getPatternList()->size() - 1 ) );
460 }
461 }
462
463 if ( pHydrogen->getPatternMode() == Song::PatternMode::Selected ) {
464 return nextPatternSelection( nPatternNumber );
465 }
466
467 return pHydrogen->flushAndAddNextPattern( nPatternNumber );
468}
469
470bool MidiActionManager::select_and_play_pattern( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
471 // Preventive measure to avoid bad things.
472 if ( pHydrogen->getSong() == nullptr ) {
473 ERRORLOG( "No song set yet" );
474 return false;
475 }
476
477 if ( ! select_next_pattern( pAction, pHydrogen ) ) {
478 return false;
479 }
480
481 if ( pHydrogen->getAudioEngine()->getState() == AudioEngine::State::Ready ) {
482 pHydrogen->sequencer_play();
483 }
484
485 return true;
486}
487
488bool MidiActionManager::select_instrument( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
489 auto pSong = pHydrogen->getSong();
490
491 // Preventive measure to avoid bad things.
492 if ( pSong == nullptr ) {
493 ERRORLOG( "No song set yet" );
494 return false;
495 }
496
497 bool ok;
498 int nInstrumentNumber = pAction->getValue().toInt(&ok,10) ;
499
500 if ( pSong->getInstrumentList()->size() < nInstrumentNumber ) {
501 nInstrumentNumber = pSong->getInstrumentList()->size() -1;
502 } else if ( nInstrumentNumber < 0 ) {
503 nInstrumentNumber = 0;
504 }
505
506 pHydrogen->setSelectedInstrumentNumber( nInstrumentNumber );
507 return true;
508}
509
510bool MidiActionManager::effect_level_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen) {
511 auto pSong = pHydrogen->getSong();
512
513 // Preventive measure to avoid bad things.
514 if ( pSong == nullptr ) {
515 ERRORLOG( "No song set yet" );
516 return false;
517 }
518
519 bool ok;
520 int nLine = pAction->getParameter1().toInt(&ok,10);
521 int fx_param = pAction->getValue().toInt(&ok,10);
522 int fx_id = pAction->getParameter2().toInt(&ok,10);
523
524 auto pInstrList = pSong->getInstrumentList();
525
526 auto pInstr = pInstrList->get( nLine );
527 if ( pInstr == nullptr) {
528 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
529 return false;
530 }
531
532 if( fx_param != 0 ) {
533 pInstr->set_fx_level( (float) (fx_param / 127.0 ), fx_id );
534 } else {
535 pInstr->set_fx_level( 0 , fx_id );
536 }
537
538 pHydrogen->setSelectedInstrumentNumber( nLine );
539
541
542 return true;
543}
544
545bool MidiActionManager::effect_level_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
546 auto pSong = pHydrogen->getSong();
547
548 // Preventive measure to avoid bad things.
549 if ( pSong == nullptr ) {
550 ERRORLOG( "No song set yet" );
551 return false;
552 }
553
554 bool ok;
555 int nLine = pAction->getParameter1().toInt(&ok,10);
556 int fx_param = pAction->getValue().toInt(&ok,10);
557 int fx_id = pAction->getParameter2().toInt(&ok,10);
558
559 auto pInstrList = pSong->getInstrumentList();
560
561 auto pInstr = pInstrList->get( nLine );
562 if ( pInstr == nullptr) {
563 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
564 return false;
565 }
566 if ( fx_param != 0 ) {
567 if ( fx_param == 1 && pInstr->get_fx_level( fx_id ) <= 0.95 ) {
568 pInstr->set_fx_level( pInstr->get_fx_level( fx_id ) + 0.05, fx_id );
569 }
570 else if ( pInstr->get_fx_level( fx_id ) >= 0.05 ) {
571 pInstr->set_fx_level( pInstr->get_fx_level( fx_id ) - 0.05, fx_id );
572 }
573 }
574
575 pHydrogen->setSelectedInstrumentNumber( nLine );
576
578
579 return true;
580}
581
582//sets the volume of a master output to a given level (percentage)
583bool MidiActionManager::master_volume_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
584 auto pSong = pHydrogen->getSong();
585
586 // Preventive measure to avoid bad things.
587 if ( pSong == nullptr ) {
588 ERRORLOG( "No song set yet" );
589 return false;
590 }
591
592 bool ok;
593 int nVolume = pAction->getValue().toInt(&ok,10);
594
595 if ( nVolume != 0 ) {
596 pSong->setVolume( 1.5* ( (float) (nVolume / 127.0 ) ));
597 } else {
598 pSong->setVolume( 0 );
599 }
600
601 return true;
602}
603
604//increments/decrements the volume of the whole song
605bool MidiActionManager::master_volume_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
606 auto pSong = pHydrogen->getSong();
607
608 // Preventive measure to avoid bad things.
609 if ( pSong == nullptr ) {
610 ERRORLOG( "No song set yet" );
611 return false;
612 }
613
614 bool ok;
615 int nVolume = pAction->getValue().toInt(&ok,10);
616
617 if ( nVolume != 0 ) {
618 if ( nVolume == 1 && pSong->getVolume() < 1.5 ) {
619 pSong->setVolume( pSong->getVolume() + 0.05 );
620 } else if ( pSong->getVolume() >= 0.0 ) {
621 pSong->setVolume( pSong->getVolume() - 0.05 );
622 }
623 } else {
624 pSong->setVolume( 0 );
625 }
626
627 return true;
628}
629
630//sets the volume of a mixer strip to a given level (percentage)
631bool MidiActionManager::strip_volume_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
632 auto pSong = pHydrogen->getSong();
633
634 // Preventive measure to avoid bad things.
635 if ( pSong == nullptr ) {
636 ERRORLOG( "No song set yet" );
637 return false;
638 }
639
640 bool ok;
641 int nLine = pAction->getParameter1().toInt(&ok,10);
642 int nVolume = pAction->getValue().toInt(&ok,10);
643
644 auto pInstrList = pSong->getInstrumentList();
645
646 auto pInstr = pInstrList->get( nLine );
647 if ( pInstr == nullptr ) {
648 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
649 return false;
650 }
651
652 if ( nVolume != 0 ) {
653 pInstr->set_volume( 1.5* ( (float) (nVolume / 127.0 ) ));
654 } else {
655 pInstr->set_volume( 0 );
656 }
657
658 pHydrogen->setSelectedInstrumentNumber(nLine);
660
661 return true;
662}
663
664//increments/decrements the volume of one mixer strip
665bool MidiActionManager::strip_volume_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
666 auto pSong = pHydrogen->getSong();
667
668 // Preventive measure to avoid bad things.
669 if ( pSong == nullptr ) {
670 ERRORLOG( "No song set yet" );
671 return false;
672 }
673
674 bool ok;
675 int nLine = pAction->getParameter1().toInt(&ok,10);
676 int nVolume = pAction->getValue().toInt(&ok,10);
677
678 auto pInstrList = pSong->getInstrumentList();
679
680 auto pInstr = pInstrList->get( nLine );
681
682 if ( pInstr == nullptr) {
683 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
684 return false;
685 }
686
687 if( nVolume != 0 ) {
688 if ( nVolume == 1 && pInstr->get_volume() < 1.5 ) {
689 pInstr->set_volume( pInstr->get_volume() + 0.1 );
690 }
691 else if( pInstr->get_volume() >= 0.0 ){
692 pInstr->set_volume( pInstr->get_volume() - 0.1 );
693 }
694 }
695 else {
696 pInstr->set_volume( 0 );
697 }
698
699 pHydrogen->setSelectedInstrumentNumber( nLine );
701
702 return true;
703}
704
705// sets the absolute panning of a given mixer channel
706bool MidiActionManager::pan_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
707 auto pSong = pHydrogen->getSong();
708
709 // Preventive measure to avoid bad things.
710 if ( pSong == nullptr ) {
711 ERRORLOG( "No song set yet" );
712 return false;
713 }
714
715 bool ok;
716 int nLine = pAction->getParameter1().toInt(&ok,10);
717 int pan_param = pAction->getValue().toInt(&ok,10);
718
719 auto pInstrList = pSong->getInstrumentList();
720
721 auto pInstr = pInstrList->get( nLine );
722 if( pInstr == nullptr ) {
723 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
724 return false;
725 }
726
727 pInstr->setPanWithRangeFrom0To1( (float) pan_param / 127.f );
728
729 pHydrogen->setSelectedInstrumentNumber(nLine);
730
732
733 return true;
734}
735
736// sets the absolute panning of a given mixer channel
737bool MidiActionManager::pan_absolute_sym( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
738 auto pSong = pHydrogen->getSong();
739
740 // Preventive measure to avoid bad things.
741 if ( pSong == nullptr ) {
742 ERRORLOG( "No song set yet" );
743 return false;
744 }
745
746 bool ok;
747 int nLine = pAction->getParameter1().toInt(&ok,10);
748 int pan_param = pAction->getValue().toInt(&ok,10);
749
750 auto pInstrList = pSong->getInstrumentList();
751
752 auto pInstr = pInstrList->get( nLine );
753 if ( pInstr == nullptr ) {
754 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
755 return false;
756 }
757
758 pInstr->setPan( (float) pan_param / 127.f );
759
760 pHydrogen->setSelectedInstrumentNumber(nLine);
762
763 return true;
764}
765
766
767// changes the panning of a given mixer channel
768// this is useful if the panning is set by a rotary control knob
769bool MidiActionManager::pan_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
770 auto pSong = pHydrogen->getSong();
771
772 // Preventive measure to avoid bad things.
773 if ( pSong == nullptr ) {
774 ERRORLOG( "No song set yet" );
775 return false;
776 }
777
778 bool ok;
779 int nLine = pAction->getParameter1().toInt(&ok,10);
780 int pan_param = pAction->getValue().toInt(&ok,10);
781
782 auto pInstrList = pSong->getInstrumentList();
783
784 auto pInstr = pInstrList->get( nLine );
785 if ( pInstr == nullptr ) {
786 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
787 return false;
788 }
789
790 float fPan = pInstr->getPan();
791
792 if ( pan_param == 1 && fPan < 1.f ) {
793 pInstr->setPan( fPan + 0.1 );
794 }
795 else if ( pan_param != 1 && fPan > -1.f ) {
796 pInstr->setPan( fPan - 0.1 );
797 }
798
799 pHydrogen->setSelectedInstrumentNumber(nLine);
801
802 return true;
803}
804
805bool MidiActionManager::gain_level_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
806 auto pSong = pHydrogen->getSong();
807
808 // Preventive measure to avoid bad things.
809 if ( pSong == nullptr ) {
810 ERRORLOG( "No song set yet" );
811 return false;
812 }
813
814 bool ok;
815 int nLine = pAction->getParameter1().toInt(&ok,10);
816 int gain_param = pAction->getValue().toInt(&ok,10);
817 int component_id = pAction->getParameter2().toInt(&ok,10);
818 int layer_id = pAction->getParameter3().toInt(&ok,10);
819
820 auto pInstrList = pSong->getInstrumentList();
821
822 auto pInstr = pInstrList->get( nLine );
823 if( pInstr == nullptr ) {
824 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
825 return false;
826 }
827
828 auto pComponent = pInstr->get_component( component_id );
829 if( pComponent == nullptr) {
830 ERRORLOG( QString( "Unable to retrieve component (Par. 2) [%1]" ).arg( component_id ) );
831 return false;
832 }
833
834 auto pLayer = pComponent->get_layer( layer_id );
835 if( pLayer == nullptr ) {
836 ERRORLOG( QString( "Unable to retrieve layer (Par. 3) [%1]" ).arg( layer_id ) );
837 return false;
838 }
839
840 if ( gain_param != 0 ) {
841 pLayer->set_gain( 5.0* ( (float) (gain_param / 127.0 ) ) );
842 } else {
843 pLayer->set_gain( 0 );
844 }
845
846 pHydrogen->setSelectedInstrumentNumber( nLine );
848
849 return true;
850}
851
852bool MidiActionManager::pitch_level_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
853 auto pSong = pHydrogen->getSong();
854
855 // Preventive measure to avoid bad things.
856 if ( pSong == nullptr ) {
857 ERRORLOG( "No song set yet" );
858 return false;
859 }
860
861 bool ok;
862 int nLine = pAction->getParameter1().toInt(&ok,10);
863 int pitch_param = pAction->getValue().toInt(&ok,10);
864 int component_id = pAction->getParameter2().toInt(&ok,10);
865 int layer_id = pAction->getParameter3().toInt(&ok,10);
866
867 auto pInstrList = pSong->getInstrumentList();
868
869 auto pInstr = pInstrList->get( nLine );
870 if( pInstr == nullptr ) {
871 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
872 return false;
873 }
874
875 auto pComponent = pInstr->get_component( component_id );
876 if( pComponent == nullptr) {
877 ERRORLOG( QString( "Unable to retrieve component (Par. 2) [%1]" ).arg( component_id ) );
878 return false;
879 }
880
881 auto pLayer = pComponent->get_layer( layer_id );
882 if( pLayer == nullptr ) {
883 ERRORLOG( QString( "Unable to retrieve layer (Par. 3) [%1]" ).arg( layer_id ) );
884 return false;
885 }
886
887 if ( pitch_param != 0 ) {
888 pLayer->set_pitch(
890 ( (float) (pitch_param / 127.0 ) ) + Instrument::fPitchMin );
891 } else {
892 pLayer->set_pitch( Instrument::fPitchMin );
893 }
894
895 pHydrogen->setSelectedInstrumentNumber( nLine );
897
898 return true;
899}
900
901bool MidiActionManager::instrument_pitch( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
902
903 bool ok;
904 float fPitch;
905 const int nInstrument = pAction->getParameter1().toInt(&ok,10);
906 const int nPitchMidi = pAction->getValue().toInt(&ok,10);
907 if ( nPitchMidi != 0 ) {
909 ( (float) (nPitchMidi / 127.0 ) ) + Instrument::fPitchMin;
910 } else {
911 fPitch = Instrument::fPitchMin;
912 }
913
914 return pHydrogen->getCoreActionController()->
915 setInstrumentPitch( nInstrument, fPitch );
916}
917
918bool MidiActionManager::filter_cutoff_level_absolute( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
919 auto pSong = pHydrogen->getSong();
920
921 // Preventive measure to avoid bad things.
922 if ( pSong == nullptr ) {
923 ERRORLOG( "No song set yet" );
924 return false;
925 }
926
927 bool ok;
928 int nLine = pAction->getParameter1().toInt(&ok,10);
929 int filter_cutoff_param = pAction->getValue().toInt(&ok,10);
930
931 auto pInstrList = pSong->getInstrumentList();
932
933 auto pInstr = pInstrList->get( nLine );
934 if( pInstr == nullptr ) {
935 ERRORLOG( QString( "Unable to retrieve instrument (Par. 1) [%1]" ).arg( nLine ) );
936 return false;
937 }
938
939 pInstr->set_filter_active( true );
940 if( filter_cutoff_param != 0 ) {
941 pInstr->set_filter_cutoff( ( (float) (filter_cutoff_param / 127.0 ) ) );
942 } else {
943 pInstr->set_filter_cutoff( 0 );
944 }
945
946 pHydrogen->setSelectedInstrumentNumber( nLine );
948
949 return true;
950}
951
952
953/*
954 * increments/decrements the BPM
955 * this is useful if the bpm is set by a rotary control knob
956 */
957bool MidiActionManager::bpm_cc_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
958 // Preventive measure to avoid bad things.
959 if ( pHydrogen->getSong() == nullptr ) {
960 ERRORLOG( "No song set yet" );
961 return false;
962 }
963
964 auto pAudioEngine = pHydrogen->getAudioEngine();
965 const float fBpm = pAudioEngine->getTransportPosition()->getBpm();
966
967 //this Action should be triggered only by CC commands
968
969 bool ok;
970 int mult = pAction->getParameter1().toInt(&ok,10);
971 //this value should be 1 to decrement and something other then 1 to increment the bpm
972 int cc_param = pAction->getValue().toInt(&ok,10);
973
974 if( m_nLastBpmChangeCCParameter == -1) {
976 }
977
978 if ( m_nLastBpmChangeCCParameter >= cc_param &&
979 fBpm - mult > MIN_BPM ) {
980 // Use tempo in the next process cycle of the audio engine.
981 pAudioEngine->lock( RIGHT_HERE );
982 pAudioEngine->setNextBpm( fBpm - 1*mult );
983 pAudioEngine->unlock();
984 // Store it's value in the .h2song file.
985 pHydrogen->getSong()->setBpm( fBpm - 1*mult );
986 }
987
988 if ( m_nLastBpmChangeCCParameter < cc_param
989 && fBpm + mult < MAX_BPM ) {
990 // Use tempo in the next process cycle of the audio engine.
991 pAudioEngine->lock( RIGHT_HERE );
992 pAudioEngine->setNextBpm( fBpm + 1*mult );
993 pAudioEngine->unlock();
994 // Store it's value in the .h2song file.
995 pHydrogen->getSong()->setBpm( fBpm + 1*mult );
996 }
997
999
1001
1002 return true;
1003}
1004
1005/*
1006 * increments/decrements the BPM
1007 * this is useful if the bpm is set by a rotary control knob
1008 */
1009bool MidiActionManager::bpm_fine_cc_relative( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1010 // Preventive measure to avoid bad things.
1011 if ( pHydrogen->getSong() == nullptr ) {
1012 ERRORLOG( "No song set yet" );
1013 return false;
1014 }
1015
1016 auto pAudioEngine = pHydrogen->getAudioEngine();
1017 const float fBpm = pAudioEngine->getTransportPosition()->getBpm();
1018
1019 //this Action should be triggered only by CC commands
1020 bool ok;
1021 int mult = pAction->getParameter1().toInt(&ok,10);
1022 //this value should be 1 to decrement and something other then 1 to increment the bpm
1023 int cc_param = pAction->getValue().toInt(&ok,10);
1024
1025 if( m_nLastBpmChangeCCParameter == -1) {
1026 m_nLastBpmChangeCCParameter = cc_param;
1027 }
1028
1029 if ( m_nLastBpmChangeCCParameter >= cc_param &&
1030 fBpm - mult > MIN_BPM ) {
1031 // Use tempo in the next process cycle of the audio engine.
1032 pAudioEngine->lock( RIGHT_HERE );
1033 pAudioEngine->setNextBpm( fBpm - 0.01*mult );
1034 pAudioEngine->unlock();
1035 // Store it's value in the .h2song file.
1036 pHydrogen->getSong()->setBpm( fBpm - 0.01*mult );
1037 }
1038 if ( m_nLastBpmChangeCCParameter < cc_param
1039 && fBpm + mult < MAX_BPM ) {
1040 // Use tempo in the next process cycle of the audio engine.
1041 pAudioEngine->lock( RIGHT_HERE );
1042 pAudioEngine->setNextBpm( fBpm + 0.01*mult );
1043 pAudioEngine->unlock();
1044 // Store it's value in the .h2song file.
1045 pHydrogen->getSong()->setBpm( fBpm + 0.01*mult );
1046 }
1047
1048 m_nLastBpmChangeCCParameter = cc_param;
1049
1051
1052 return true;
1053}
1054
1055bool MidiActionManager::bpm_increase( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1056 // Preventive measure to avoid bad things.
1057 if ( pHydrogen->getSong() == nullptr ) {
1058 ERRORLOG( "No song set yet" );
1059 return false;
1060 }
1061
1062 auto pAudioEngine = pHydrogen->getAudioEngine();
1063 const float fBpm = pAudioEngine->getTransportPosition()->getBpm();
1064
1065 bool ok;
1066 int mult = pAction->getParameter1().toInt(&ok,10);
1067
1068 // Use tempo in the next process cycle of the audio engine.
1069 pAudioEngine->lock( RIGHT_HERE );
1070 pAudioEngine->setNextBpm( fBpm + 1*mult );
1071 pAudioEngine->unlock();
1072 // Store it's value in the .h2song file.
1073 pHydrogen->getSong()->setBpm( fBpm + 1*mult );
1074
1076
1077 return true;
1078}
1079
1080bool MidiActionManager::bpm_decrease( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1081 // Preventive measure to avoid bad things.
1082 if ( pHydrogen->getSong() == nullptr ) {
1083 ERRORLOG( "No song set yet" );
1084 return false;
1085 }
1086
1087 auto pAudioEngine = pHydrogen->getAudioEngine();
1088 const float fBpm = pAudioEngine->getTransportPosition()->getBpm();
1089
1090 bool ok;
1091 int mult = pAction->getParameter1().toInt(&ok,10);
1092
1093 // Use tempo in the next process cycle of the audio engine.
1094 pAudioEngine->lock( RIGHT_HERE );
1095 pAudioEngine->setNextBpm( fBpm - 1*mult );
1096 pAudioEngine->unlock();
1097 // Store it's value in the .h2song file.
1098 pHydrogen->getSong()->setBpm( fBpm - 1*mult );
1099
1101
1102 return true;
1103}
1104
1105bool MidiActionManager::next_bar( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
1106 // Preventive measure to avoid bad things.
1107 if ( pHydrogen->getSong() == nullptr ) {
1108 ERRORLOG( "No song set yet" );
1109 return false;
1110 }
1111
1112 int nNewColumn = std::max( 0, pHydrogen->getAudioEngine()->
1113 getTransportPosition()->getColumn() ) + 1;
1114
1115 pHydrogen->getCoreActionController()->locateToColumn( nNewColumn );
1116 return true;
1117}
1118
1119
1120bool MidiActionManager::previous_bar( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
1121 // Preventive measure to avoid bad things.
1122 if ( pHydrogen->getSong() == nullptr ) {
1123 ERRORLOG( "No song set yet" );
1124 return false;
1125 }
1126
1128 pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() -1 );
1129 return true;
1130}
1131
1132bool MidiActionManager::setSong( int nSongNumber, Hydrogen* pHydrogen ) {
1133 int nActiveSongNumber = Playlist::get_instance()->getActiveSongNumber();
1134 if( nSongNumber >= 0 && nSongNumber <= Playlist::get_instance()->size() - 1 ) {
1135 if ( nActiveSongNumber != nSongNumber ) {
1137 }
1138 } else {
1139 // Preventive measure to avoid bad things.
1140 if ( pHydrogen->getSong() == nullptr ) {
1141 ___ERRORLOG( "No song set yet" );
1142 }
1143 else if ( Playlist::get_instance()->size() == 0 ) {
1144 ___ERRORLOG( QString( "No songs added to the current playlist yet" ) );
1145 }
1146 else {
1147 ___ERRORLOG( QString( "Provided song number [%1] out of bound [0,%2]" )
1148 .arg( nSongNumber )
1149 .arg( Playlist::get_instance()->size() - 1 ) );
1150 }
1151 return false;
1152 }
1153 return true;
1154}
1155
1156bool MidiActionManager::playlist_song( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1157 bool ok;
1158 int songnumber = pAction->getParameter1().toInt(&ok,10);
1159 return setSong( songnumber, pHydrogen );
1160}
1161
1162bool MidiActionManager::playlist_next_song( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1163 int songnumber = Playlist::get_instance()->getActiveSongNumber();
1164 return setSong( ++songnumber, pHydrogen );
1165}
1166
1167bool MidiActionManager::playlist_previous_song( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1168 int songnumber = Playlist::get_instance()->getActiveSongNumber();
1169 return setSong( --songnumber, pHydrogen );
1170}
1171
1172bool MidiActionManager::record_ready( std::shared_ptr<Action> pAction, Hydrogen* pHydrogen ) {
1173 // Preventive measure to avoid bad things.
1174 if ( pHydrogen->getSong() == nullptr ) {
1175 ERRORLOG( "No song set yet" );
1176 return false;
1177 }
1178
1179 if ( pHydrogen->getAudioEngine()->getState() != AudioEngine::State::Playing ) {
1180 if (!Preferences::get_instance()->getRecordEvents()) {
1182 }
1183 else {
1185 }
1186 }
1187 return true;
1188}
1189
1190bool MidiActionManager::record_strobe_toggle( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
1191 // Preventive measure to avoid bad things.
1192 if ( pHydrogen->getSong() == nullptr ) {
1193 ERRORLOG( "No song set yet" );
1194 return false;
1195 }
1196
1197 if (!Preferences::get_instance()->getRecordEvents()) {
1199 }
1200 else {
1202 }
1203 return true;
1204}
1205
1206bool MidiActionManager::record_strobe( std::shared_ptr<Action> , Hydrogen* pHydrogen ) {
1207 // Preventive measure to avoid bad things.
1208 if ( pHydrogen->getSong() == nullptr ) {
1209 ERRORLOG( "No song set yet" );
1210 return false;
1211 }
1212
1213 if (!Preferences::get_instance()->getRecordEvents()) {
1215 }
1216 return true;
1217}
1218
1219bool MidiActionManager::record_exit( std::shared_ptr<Action> , Hydrogen* pHydrogen) {
1220 // Preventive measure to avoid bad things.
1221 if ( pHydrogen->getSong() == nullptr ) {
1222 ERRORLOG( "No song set yet" );
1223 return false;
1224 }
1225
1226 if (Preferences::get_instance()->getRecordEvents()) {
1228 }
1229 return true;
1230}
1231
1232bool MidiActionManager::toggle_metronome( std::shared_ptr<Action> , Hydrogen* pHydrogen) {
1233 // Preventive measure to avoid bad things.
1234 if ( pHydrogen->getSong() == nullptr ) {
1235 ERRORLOG( "No song set yet" );
1236 return false;
1237 }
1238
1239 // Use the wrapper in CAC over a plain setting of the parameter in
1240 // order to send MIDI feedback
1242 ! Preferences::get_instance()->m_bUseMetronome );
1243
1244 return true;
1245}
1246
1247bool MidiActionManager::undo_action( std::shared_ptr<Action> , Hydrogen* ) {
1249 return true;
1250}
1251
1252bool MidiActionManager::redo_action( std::shared_ptr<Action> , Hydrogen* ) {
1254 return true;
1255}
1256
1257int MidiActionManager::getParameterNumber( const QString& sActionType ) const {
1258 auto foundActionPair = m_actionMap.find( sActionType );
1259 if ( foundActionPair != m_actionMap.end() ) {
1260 return foundActionPair->second.second;
1261 } else {
1262 ERRORLOG( QString( "MIDI Action type [%1] couldn't be found" ).arg( sActionType ) );
1263 }
1264
1265 return -1;
1266}
1267
1268bool MidiActionManager::clear_selected_instrument( std::shared_ptr<Action> pAction,
1269 Hydrogen* pHydrogen ) {
1270 auto pSong = pHydrogen->getSong();
1271 if ( pSong == nullptr ) {
1272 ERRORLOG( "no song set" );
1273 return false;
1274 }
1275
1276 const int nInstr = pHydrogen->getSelectedInstrumentNumber();
1277 if ( nInstr == -1 ) {
1278 WARNINGLOG( "No instrument selected" );
1279 return false;
1280 }
1281
1282 return pHydrogen->getCoreActionController()->clearInstrumentInPattern( nInstr );
1283}
1284
1285bool MidiActionManager::clear_pattern( std::shared_ptr<Action> pAction,
1286 Hydrogen* pHydrogen ) {
1287 auto pSong = pHydrogen->getSong();
1288 if ( pSong == nullptr ) {
1289 ERRORLOG( "no song set" );
1290 return false;
1291 }
1292
1293 int nPattern = pHydrogen->getSelectedPatternNumber();
1294
1295 auto pPattern = pSong->getPatternList()->get( nPattern );
1296 if ( pPattern == nullptr ) {
1297 ERRORLOG( QString( "Couldn't find pattern [%1]" ).arg( nPattern ) );
1298 return false;
1299 }
1300
1301 pPattern->clear( true );
1302
1303 if ( pHydrogen->getGUIState() != Hydrogen::GUIState::unavailable ) {
1305 }
1306
1307 return true;
1308}
1309
1310bool MidiActionManager::handleActions( std::vector<std::shared_ptr<Action>> actions ) {
1311
1312 bool bResult = false;
1313
1314 for ( const auto& action : actions ) {
1315 if ( action != nullptr ) {
1316 if ( handleAction( action ) ) {
1317 bResult = true;
1318 }
1319 }
1320 }
1321
1322 return bResult;
1323}
1324
1325bool MidiActionManager::handleAction( std::shared_ptr<Action> pAction ) {
1326
1327 Hydrogen *pHydrogen = Hydrogen::get_instance();
1328 /*
1329 return false if action is null
1330 (for example if no Action exists for an event)
1331 */
1332 if( pAction == nullptr ) {
1333 return false;
1334 }
1335
1336 QString sActionString = pAction->getType();
1337
1338 auto foundActionPair = m_actionMap.find( sActionString );
1339 if( foundActionPair != m_actionMap.end() ) {
1340 action_f action = foundActionPair->second.first;
1341 return (this->*action)(pAction, pHydrogen);
1342 } else {
1343 ERRORLOG( QString( "MIDI Action type [%1] couldn't be found" ).arg( sActionString ) );
1344 }
1345
1346 return false;
1347}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:61
#define INFOLOG(x)
Definition Object.h:240
#define WARNINGLOG(x)
Definition Object.h:241
#define ERRORLOG(x)
Definition Object.h:242
#define ___ERRORLOG(x)
Definition Object.h:260
static QString getNullActionType()
Definition MidiAction.h:34
QString m_sValue
Definition MidiAction.h:132
QString m_sParameter1
Definition MidiAction.h:129
QString m_sParameter2
Definition MidiAction.h:130
QString m_sType
Definition MidiAction.h:128
bool isEquivalentTo(std::shared_ptr< Action > pOther)
bool isNull() const
Checks whether m_sType is of getNullActionType()
QString toQString(const QString &sPrefix="", bool bShort=true) const override
Formatted string version for debugging purposes.
Action(QString sType=getNullActionType())
QString m_sParameter3
Definition MidiAction.h:131
@ Playing
Transport is rolling.
@ Ready
Ready to process audio.
State getState() const
const std::shared_ptr< TransportPosition > getTransportPosition() const
static QString sPrintIndention
String used to format the debugging string output of some core classes.
Definition Object.h:127
bool locateToColumn(int nPatternGroup)
Relocates transport to the beginning of a particular column/Pattern group.
bool clearInstrumentInPattern(int nInstrumentNumber, int nPatternNumber=-1)
Deletes all notes for instrument pInstrument in a specified pattern.
bool setStripIsMuted(int nStrip, bool isMuted)
bool setStripIsSoloed(int nStrip, bool isSoloed)
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
Hydrogen Audio Engine.
Definition Hydrogen.h:54
void sequencer_stop()
Stop the internal sequencer.
Definition Hydrogen.cpp:231
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:123
int getSelectedInstrumentNumber() const
Definition Hydrogen.h:678
void onTapTempoAccelEvent()
Definition Hydrogen.cpp:805
@ unavailable
No GUI available.
Definition Hydrogen.h:403
int getSelectedPatternNumber() const
Definition Hydrogen.h:674
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
Definition Hydrogen.cpp:944
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
bool handleBeatCounter()
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:663
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:653
void sequencer_play()
Start the internal sequencer.
Definition Hydrogen.cpp:221
GUIState getGUIState() const
Definition Hydrogen.h:667
static constexpr float fPitchMin
Minimum support pitch value.
Definition Instrument.h:322
static constexpr float fPitchMax
Maximum support pitch value.
Definition Instrument.h:320
void setNextSongByNumber(int SongNumber)
Definition Playlist.cpp:207
int getActiveSongNumber()
Definition Playlist.h:148
static Playlist * get_instance()
Returns a pointer to the current Playlist singleton stored in __instance.
Definition Playlist.h:60
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setRecordEvents(bool value)
@ Stacked
An arbitrary number of pattern can be played.
Definition Song.h:103
@ Selected
Only one pattern - the one currently selected in the GUI - will be played back.
Definition Song.h:106
The MidiActionManager cares for the execution of MidiActions.
Definition MidiAction.h:142
bool previous_bar(std::shared_ptr< Action >, H2Core::Hydrogen *)
static MidiActionManager * __instance
Object holding the current MidiActionManager singleton.
Definition MidiAction.h:151
bool bpm_decrease(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool record_strobe(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool playlist_next_song(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool setSong(int nSongNumber, H2Core::Hydrogen *pHydrogen)
bool playlist_song(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool unmute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool strip_volume_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool play(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool playlist_previous_song(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_instrument(std::shared_ptr< Action >, H2Core::Hydrogen *)
int m_nLastBpmChangeCCParameter
Definition MidiAction.h:219
bool mute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool record_exit(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool master_volume_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool pitch_level_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool tap_tempo(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_next_pattern_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool handleAction(std::shared_ptr< Action > action)
The handleAction method is the heart of the MidiActionManager class.
bool strip_solo_toggle(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool beatcounter(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool clear_pattern(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool pan_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool instrument_pitch(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool onlyNextPatternSelection(int nPatternNumber)
static void create_instance()
If __instance equals 0, a new MidiActionManager singleton will be created and stored in it.
bool pan_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool pan_absolute_sym(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_next_pattern(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool bpm_fine_cc_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_and_play_pattern(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool effect_level_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool redo_action(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool handleActions(std::vector< std::shared_ptr< Action > > actions)
Handles multiple actions at once and calls handleAction() on them.
bool filter_cutoff_level_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool strip_volume_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool clear_selected_instrument(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool pause(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool next_bar(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool toggle_metronome(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool play_stop_pause_toggle(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool record_strobe_toggle(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_only_next_pattern_cc_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool bpm_cc_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool stop(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool record_ready(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool undo_action(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool select_only_next_pattern(std::shared_ptr< Action >, H2Core::Hydrogen *)
QStringList m_actionList
Holds the names of all Action identifiers which Hydrogen is able to interpret.
Definition MidiAction.h:157
bool mute_toggle(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool nextPatternSelection(int nPatternNumber)
bool master_volume_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
int getParameterNumber(const QString &sActionType) const
bool select_next_pattern_cc_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool(MidiActionManager::* action_f)(std::shared_ptr< Action >, H2Core::Hydrogen *)
Definition MidiAction.h:159
std::map< QString, std::pair< action_f, int > > m_actionMap
Holds all Action identifiers which Hydrogen is able to interpret.
Definition MidiAction.h:168
bool bpm_increase(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool strip_mute_toggle(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool effect_level_relative(std::shared_ptr< Action >, H2Core::Hydrogen *)
bool gain_level_absolute(std::shared_ptr< Action >, H2Core::Hydrogen *)
#define MAX_BPM
Definition Globals.h:36
#define MIN_BPM
Definition Globals.h:35
@ EVENT_INSTRUMENT_PARAMETERS_CHANGED
Some parameters of an instrument have been changed.
Definition EventQueue.h:83
@ EVENT_UNDO_REDO
Definition EventQueue.h:101
@ EVENT_TEMPO_CHANGED
Definition EventQueue.h:103
@ EVENT_PATTERN_MODIFIED
A pattern was added, deleted, or modified.
Definition EventQueue.h:68