hydrogen 1.2.3
Mixer.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-2024 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
23#include "Mixer.h"
24#include "MixerLine.h"
25
26#include "../CommonStrings.h"
27#include "../HydrogenApp.h"
30#include "../Widgets/Button.h"
32#include "MixerSettingsDialog.h"
33
35#include <core/Hydrogen.h>
40#include <core/Basics/Song.h>
41#include <core/Basics/Note.h>
42#include <core/FX/Effects.h>
43using namespace H2Core;
44
45#include <cassert>
46
47#define MIXER_STRIP_WIDTH 56
48#define MASTERMIXER_STRIP_WIDTH 126
49
50Mixer::Mixer( QWidget* pParent )
51 : QWidget( pParent )
52{
53 setWindowTitle( tr( "Mixer" ) );
54 setMaximumHeight( 284 );
55 setMinimumHeight( 284 );
56 setFixedHeight( 284 );
57
58// fader Panel
59 m_pFaderHBox = new QHBoxLayout();
60 m_pFaderHBox->setSpacing( 0 );
61 m_pFaderHBox->setMargin( 0 );
62
63 m_pFaderPanel = new QWidget( nullptr );
64 m_pFaderPanel->resize( MIXER_STRIP_WIDTH * MAX_INSTRUMENTS, height() );
65
66 m_pFaderPanel->setLayout( m_pFaderHBox );
67
68 m_pFaderScrollArea = new QScrollArea( nullptr );
69 m_pFaderScrollArea->setFrameShape( QFrame::NoFrame );
70 m_pFaderScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
71 m_pFaderScrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
72 m_pFaderScrollArea->setMinimumWidth( MIXER_STRIP_WIDTH * 4 );
74
75 for ( uint i = 0; i < MAX_INSTRUMENTS; ++i ) {
76 m_pMixerLine[ i ] = nullptr;
77 }
78
79// ~ fader panel
80
81
82// fX frame
83#ifdef H2CORE_HAVE_LADSPA
84 auto pEffects = Effects::get_instance();
85#endif
86 m_pFXFrame = new PixmapWidget( nullptr );
87 m_pFXFrame->setObjectName( "MixerFXRack" );
88 m_pFXFrame->setFixedSize( 213, height() );
89 m_pFXFrame->setPixmap( "/mixerPanel/background_FX.png" );
90 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
92 m_pLadspaFXLine[nFX]->setObjectName( "LadspaFXMixerLine" );
93 m_pLadspaFXLine[nFX]->move( 13, 43 * nFX + 84 );
94#ifdef H2CORE_HAVE_LADSPA
95 if ( pEffects != nullptr ) {
96 auto pFx = pEffects->getLadspaFX( nFX );
97 if ( pFx != nullptr ) {
98 m_pLadspaFXLine[nFX]->setFxBypassed( pEffects->getLadspaFX( nFX )->isEnabled() );
99 }
100 }
101#endif
102 connect( m_pLadspaFXLine[nFX], SIGNAL( bypassBtnClicked(LadspaFXMixerLine*) ), this, SLOT( ladspaBypassBtnClicked( LadspaFXMixerLine*) ) );
103 connect( m_pLadspaFXLine[nFX], SIGNAL( editBtnClicked(LadspaFXMixerLine*) ), this, SLOT( ladspaEditBtnClicked( LadspaFXMixerLine*) ) );
104 connect( m_pLadspaFXLine[nFX], SIGNAL( volumeChanged(LadspaFXMixerLine*) ), this, SLOT( ladspaVolumeChanged( LadspaFXMixerLine*) ) );
105 }
106
107 if ( Preferences::get_instance()->isFXTabVisible() ) {
108 m_pFXFrame->show();
109 }
110 else {
111 m_pFXFrame->hide();
112 }
113// ~ fX frame
114
115
116// Master frame
117 m_pMasterLine = new MasterMixerLine( nullptr );
118 m_pMasterLine->setObjectName( "MasterMixerLine" );
119 m_pMasterLine->move( 0, 0 );
120 connect( m_pMasterLine, SIGNAL( volumeChanged(MasterMixerLine*) ), this, SLOT( masterVolumeChanged(MasterMixerLine*) ) );
121
122 m_pOpenMixerSettingsBtn = new Button( m_pMasterLine, QSize( 17, 17 ), Button::Type::Push, "cog.svg", "", false, QSize( 13, 13 ), tr( "Mixer Settings" ) );
123 m_pOpenMixerSettingsBtn->setObjectName( "MixerSettingsButton" );
124 m_pOpenMixerSettingsBtn->move( 96, 6 );
125 connect( m_pOpenMixerSettingsBtn, SIGNAL( clicked() ), this, SLOT( openMixerSettingsDialog() ) );
126
127
128 m_pShowFXPanelBtn = new Button( m_pMasterLine, QSize( 49, 15 ), Button::Type::Toggle, "", HydrogenApp::get_instance()->getCommonStrings()->getFXButton(), false, QSize(), tr( "Show FX panel" ) );
129 m_pShowFXPanelBtn->setObjectName( "MixerShowFXButton" );
130 m_pShowFXPanelBtn->move( 63, 243 );
131 m_pShowFXPanelBtn->setChecked(false);
132 connect( m_pShowFXPanelBtn, SIGNAL( clicked() ), this, SLOT( showFXPanelClicked() ));
133 m_pShowFXPanelBtn->setChecked( Preferences::get_instance()->isFXTabVisible() );
134
135#ifndef H2CORE_HAVE_LADSPA
136 m_pShowFXPanelBtn->hide();
137#endif
138
139 m_pShowPeaksBtn = new Button( m_pMasterLine, QSize( 49, 15 ), Button::Type::Toggle, "", HydrogenApp::get_instance()->getCommonStrings()->getPeakButton(), false, QSize(), tr( "Show instrument peaks" ) );
140 m_pShowPeaksBtn->setObjectName( "MixerShowPeaksButton" );
141 m_pShowPeaksBtn->move( 63, 259 );
142 m_pShowPeaksBtn->setChecked( (Preferences::get_instance())->showInstrumentPeaks() );
143 connect( m_pShowPeaksBtn, SIGNAL( clicked() ), this, SLOT( showPeaksBtnClicked() ));
144// ~ Master frame
145
146
147 // LAYOUT!
148 QHBoxLayout *pLayout = new QHBoxLayout();
149 pLayout->setSpacing( 0 );
150 pLayout->setMargin( 0 );
151
152 pLayout->addWidget( m_pFaderScrollArea );
153 pLayout->addWidget( m_pFXFrame );
154 pLayout->addWidget( m_pMasterLine );
155 this->setLayout( pLayout );
156
157
158 m_pUpdateTimer = new QTimer( this );
159 connect( m_pUpdateTimer, SIGNAL( timeout() ), this, SLOT( updateMixer() ) );
160 m_pUpdateTimer->start(50);
161
163
164
166}
167
169{
170 m_pUpdateTimer->stop();
171}
172
174{
175 MixerLine *pMixerLine = new MixerLine( nullptr , nInstr);
176 pMixerLine->setObjectName( "MixerLine" );
177 pMixerLine->setVolume( 0.2 );
178 pMixerLine->setMuteClicked( false );
179 pMixerLine->setSoloClicked( false );
180
181 connect( pMixerLine, SIGNAL( noteOnClicked(MixerLine*) ), this, SLOT( noteOnClicked(MixerLine*) ) );
182 connect( pMixerLine, SIGNAL( noteOffClicked(MixerLine*) ), this, SLOT( noteOffClicked(MixerLine*) ) );
183 connect( pMixerLine, SIGNAL( muteBtnClicked(MixerLine*) ), this, SLOT( muteClicked(MixerLine*) ) );
184 connect( pMixerLine, SIGNAL( soloBtnClicked(MixerLine*) ), this, SLOT( soloClicked(MixerLine*) ) );
185 connect( pMixerLine, SIGNAL( volumeChanged(MixerLine*) ), this, SLOT( volumeChanged(MixerLine*) ) );
186 connect( pMixerLine, SIGNAL( instrumentNameClicked(MixerLine*) ), this, SLOT( nameClicked(MixerLine*) ) );
187 connect( pMixerLine, SIGNAL( instrumentNameSelected(MixerLine*) ), this, SLOT( nameSelected(MixerLine*) ) );
188 connect( pMixerLine, SIGNAL( panChanged(MixerLine*) ), this, SLOT( panChanged( MixerLine*) ) );
189 connect( pMixerLine, SIGNAL( knobChanged(MixerLine*, int) ), this, SLOT( knobChanged( MixerLine*, int) ) );
190
191 return pMixerLine;
192}
193
194void Mixer::closeEvent( QCloseEvent* ev )
195{
197}
198
199
201{
202 ComponentMixerLine *pMixerLine = new ComponentMixerLine( nullptr , theCompoID);
203 pMixerLine->setObjectName( "ComponentMixerLine" );
204 pMixerLine->setVolume( 0.2 );
205 pMixerLine->setMuteClicked( false );
206 pMixerLine->setSoloClicked( false );
207
208 connect( pMixerLine, SIGNAL( muteBtnClicked(ComponentMixerLine*) ), this, SLOT( muteClicked(ComponentMixerLine*) ) );
209 connect( pMixerLine, SIGNAL( soloBtnClicked(ComponentMixerLine*) ), this, SLOT( soloClicked(ComponentMixerLine*) ) );
210 connect( pMixerLine, SIGNAL( volumeChanged(ComponentMixerLine*) ), this, SLOT( volumeChanged(ComponentMixerLine*) ) );
211
212 return pMixerLine;
213}
214
215
217{
218 int nLine = findMixerLineByRef(ref);
219 bool isMuteClicked = ref->isMuteClicked();
220
221 Hydrogen *pHydrogen = Hydrogen::get_instance();
222 CoreActionController* pController = pHydrogen->getCoreActionController();
223 pHydrogen->setSelectedInstrumentNumber( nLine );
224
225 pController->setStripIsMuted( nLine, isMuteClicked );
226}
227
229{
230 auto pSong = Hydrogen::get_instance()->getSong();
231 bool isMuteClicked = ref->isMuteClicked();
232
233 auto pCompo = pSong->getComponent( ref->getComponentID() );
234
235 pCompo->set_muted( isMuteClicked );
237}
238
240{
241 bool isSoloClicked = ref->isSoloClicked();
242 int nLine = findCompoMixerLineByRef(ref);
243
244 ComponentMixerLine* pComponentMixerLine = m_pComponentMixerLine[nLine];
245
246 pComponentMixerLine->setSoloClicked( isSoloClicked );
248}
249
251{
252 auto pSong = Hydrogen::get_instance()->getSong();
253 float newVolume = ref->getVolume();
254
255 auto pCompo = pSong->getComponent( ref->getComponentID() );
256
257 pCompo->set_volume( newVolume );
259}
260
262{
263 Hydrogen *pHydrogen = Hydrogen::get_instance();
264 CoreActionController* pController = pHydrogen->getCoreActionController();
265 std::shared_ptr<Song> pSong = pHydrogen->getSong();
266 auto pInstrList = pSong->getInstrumentList();
267 int nInstruments = std::min( pInstrList->size(), MAX_INSTRUMENTS );
268
269 int nLine = findMixerLineByRef(ref);
270
271 pController->setStripIsSoloed( nLine, ref->isSoloClicked() );
272
273 for ( int i = 0; i < nInstruments; ++i ) {
274 if ( m_pMixerLine[i] != nullptr ){
275 auto pInstrument = pInstrList->get(i);
276 if ( pInstrument != nullptr ) {
277 m_pMixerLine[i]->setSoloClicked( pInstrument->is_soloed() );
278 }
279 }
280 }
281
283}
284
285
286
288void Mixer::soloClicked(uint nLine)
289{
290 if ( nLine < 0 || nLine >= MAX_INSTRUMENTS ) {
291 ERRORLOG( QString( "Selected MixerLine [%1] out of bound [0,%2)" )
292 .arg( nLine ).arg( MAX_INSTRUMENTS ) );
293 return;
294 }
295
296 MixerLine * pMixerLine = m_pMixerLine[ nLine ];
297
298 if( pMixerLine != nullptr ){
299 pMixerLine->setSoloClicked( !pMixerLine->isSoloClicked() );
300 soloClicked( pMixerLine );
301 }
302
303
304}
305
306bool Mixer::isSoloClicked( uint nLine )
307{
308 if ( nLine < 0 || nLine >= MAX_INSTRUMENTS ) {
309 ERRORLOG( QString( "Selected MixerLine [%1] out of bound [0,%2)" )
310 .arg( nLine ).arg( MAX_INSTRUMENTS ) );
311 return false;
312 }
313 if ( m_pMixerLine[ nLine ] == nullptr ) {
314 return false;
315 }
316 return m_pMixerLine[ nLine ]->isSoloClicked();
317}
318
320{
321 Hydrogen *pHydrogen = Hydrogen::get_instance();
322 std::shared_ptr<Song> pSong = pHydrogen->getSong();
323
324 int nLine = findMixerLineByRef( ref );
325 pHydrogen->setSelectedInstrumentNumber( nLine );
326 auto pSelectedInstrument = pHydrogen->getSelectedInstrument();
327 if ( pSelectedInstrument == nullptr ) {
328 ERRORLOG( "No instrument selected" );
329 return;
330 }
331
332 if ( ! pSelectedInstrument->hasSamples() ) {
333 INFOLOG( QString( "Instrument [%1] does not contain any samples. No preview available" )
334 .arg( pSelectedInstrument->get_name() ) );
335 return;
336 }
337
338 Note *pNote = new Note( pSelectedInstrument, 0, 1.0 );
339 pHydrogen->getAudioEngine()->getSampler()->noteOn(pNote);
340}
341
342
343
346{
347 Hydrogen *pHydrogen = Hydrogen::get_instance();
348 std::shared_ptr<Song> pSong = pHydrogen->getSong();
349
350 int nLine = findMixerLineByRef( ref );
351 pHydrogen->setSelectedInstrumentNumber( nLine );
352 auto pSelectedInstrument = pHydrogen->getSelectedInstrument();
353 if ( pSelectedInstrument == nullptr ) {
354 ERRORLOG( "No instrument selected" );
355 return;
356 }
357
358 Note *pNote = new Note( pSelectedInstrument, 0, 0.0 );
359 pNote->set_note_off( true );
360 pHydrogen->getAudioEngine()->getSampler()->noteOff(pNote);
361}
362
363
364
366{
367 for (uint i = 0; i < MAX_INSTRUMENTS; i++) {
368 if (m_pMixerLine[i] == ref) {
369 return i;
370 }
371 }
372 return 0;
373}
374
375
377{
378 for (std::map<int, ComponentMixerLine*>::iterator it=m_pComponentMixerLine.begin(); it!=m_pComponentMixerLine.end(); ++it) {
379 if(it->second == ref) {
380 return it->first;
381 }
382 }
383
384 return 0;
385}
386
387
389{
390 Hydrogen *pHydrogen = Hydrogen::get_instance();
391 CoreActionController* pController = pHydrogen->getCoreActionController();
392
393 int nLine = findMixerLineByRef(ref);
394 pController->setStripVolume( nLine, ref->getVolume(), true );
395}
396
398{
399 Hydrogen *pHydrogen = Hydrogen::get_instance();
400 CoreActionController* pController = pHydrogen->getCoreActionController();
401
402 float Volume = ref->getVolume();
403 pController->setMasterVolume( Volume );
404}
405
406
407
409{
410 if ( ! isVisible() ) {
411 // Skip redundant updates if mixer is not visible.
412 return;
413 }
415 bool bShowPeaks = pPref->showInstrumentPeaks();
416
417 Hydrogen *pHydrogen = Hydrogen::get_instance();
418 AudioEngine *pAudioEngine = pHydrogen->getAudioEngine();
419 std::shared_ptr<Song> pSong = pHydrogen->getSong();
420 auto pInstrList = pSong->getInstrumentList();
421 auto pDrumkitComponentList = pSong->getComponents();
422
423 uint nSelectedInstr = pHydrogen->getSelectedInstrumentNumber();
424
425 float fallOff = pPref->getMixerFalloffSpeed();
426
427 int nInstruments = pInstrList->size();
428 int nCompo = pDrumkitComponentList->size();
429 for ( unsigned nInstr = 0; nInstr < MAX_INSTRUMENTS; ++nInstr ) {
430
431 if ( nInstr >= nInstruments ) { // unused instrument! let's hide and destroy the mixerline!
432 if ( m_pMixerLine[ nInstr ] ) {
433 delete m_pMixerLine[ nInstr ];
434 m_pMixerLine[ nInstr ] = nullptr;
435
436 int newWidth = MIXER_STRIP_WIDTH * ( nInstruments + nCompo );
437 if ( m_pFaderPanel->width() != newWidth ) {
438 m_pFaderPanel->resize( newWidth, height() );
439 }
440 }
441 continue;
442 }
443 else {
444 if ( m_pMixerLine[ nInstr ] == nullptr ) {
445 // the mixerline doesn't exists..I'll create a new one!
446 m_pMixerLine[ nInstr ] = createMixerLine( nInstr );
447 m_pFaderHBox->insertWidget( nInstr, m_pMixerLine[ nInstr ] );
448
449 int newWidth = MIXER_STRIP_WIDTH * ( nInstruments + nCompo );
450 if ( m_pFaderPanel->width() != newWidth ) {
451 m_pFaderPanel->resize( newWidth, height() );
452 }
453 }
454 MixerLine *pLine = m_pMixerLine[ nInstr ];
455
456 auto pInstr = pInstrList->get( nInstr );
457 assert( pInstr );
458
459 float fNewPeak_L = pInstr->get_peak_l();
460 pInstr->set_peak_l( 0.0f ); // reset instrument peak
461
462 float fNewPeak_R = pInstr->get_peak_r();
463 pInstr->set_peak_r( 0.0f ); // reset instrument peak
464
465 QString sName = pInstr->get_name();
466
467 // fader
468 float fOldPeak_L = pLine->getPeak_L();
469 float fOldPeak_R = pLine->getPeak_R();
470
471 if (!bShowPeaks) {
472 fNewPeak_L = 0.0f;
473 fNewPeak_R = 0.0f;
474 }
475
476 if ( fNewPeak_L >= fOldPeak_L) { // LEFT peak
477 pLine->setPeak_L( fNewPeak_L );
478 }
479 else {
480 pLine->setPeak_L( fOldPeak_L / fallOff );
481 }
482 if ( fNewPeak_R >= fOldPeak_R) { // Right peak
483 pLine->setPeak_R( fNewPeak_R );
484 }
485 else {
486 pLine->setPeak_R( fOldPeak_R / fallOff );
487 }
488
489 // fader position
490 float fNewVolume = pInstr->get_volume();
491 float fOldVolume = pLine->getVolume();
492 if ( fOldVolume != fNewVolume ) {
493 pLine->setVolume( fNewVolume );
494 }
495
496 // mute / solo
497 pLine->setMuteClicked( pInstr->is_muted() );
498 pLine->setSoloClicked( pInstr->is_soloed() );
499
500 // instr name
501 pLine->setName( sName );
502
503 // pan
504 float fPan = pInstr->getPan();
505 if ( fPan != pLine->getPan() ) {
506 pLine->setPan( fPan );
507 }
508
509 // activity
510 if ( pLine->getActivity() > 0 ) {
511 pLine->setActivity( m_pMixerLine[ nInstr ]->getActivity() - 30 );
512 pLine->setPlayClicked( true );
513 }
514 else {
515 pLine->setPlayClicked( false );
516 }
517
518 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
519 pLine->setFXLevel( nFX, pInstr->get_fx_level( nFX ) );
520 }
521
522 pLine->setSelected( nInstr == nSelectedInstr );
523
524 pLine->updateMixerLine();
525 }
526 }
527
528 for (auto& pDrumkitComponent : *pDrumkitComponentList) {
529
530 if( m_pComponentMixerLine.find(pDrumkitComponent->get_id()) == m_pComponentMixerLine.end() ) {
531 // the mixerline doesn't exists..I'll create a new one!
532 m_pComponentMixerLine[ pDrumkitComponent->get_id() ] = createComponentMixerLine( pDrumkitComponent->get_id() );
533 m_pFaderHBox->addWidget( m_pComponentMixerLine[ pDrumkitComponent->get_id() ] );
534
535 int newWidth = MIXER_STRIP_WIDTH * ( nInstruments + nCompo );
536 if ( m_pFaderPanel->width() != newWidth ) {
537 m_pFaderPanel->resize( newWidth, height() );
538 }
539 }
540
541 ComponentMixerLine *pLine = m_pComponentMixerLine[ pDrumkitComponent->get_id() ];
542
543 float fNewPeak_L = pDrumkitComponent->get_peak_l();
544 pDrumkitComponent->set_peak_l( 0.0f ); // reset instrument peak
545
546 float fNewPeak_R = pDrumkitComponent->get_peak_r();
547 pDrumkitComponent->set_peak_r( 0.0f ); // reset instrument peak
548
549 bool bMuted = pDrumkitComponent->is_muted();
550
551 QString sName = pDrumkitComponent->get_name();
552
553 float fOldPeak_L = pLine->getPeak_L();
554 float fOldPeak_R = pLine->getPeak_R();
555
556 if (!bShowPeaks) {
557 fNewPeak_L = 0.0f;
558 fNewPeak_R = 0.0f;
559 }
560
561 if ( fNewPeak_L >= fOldPeak_L) { // LEFT peak
562 pLine->setPeak_L( fNewPeak_L );
563 }
564 else {
565 pLine->setPeak_L( fOldPeak_L / fallOff );
566 }
567 if ( fNewPeak_R >= fOldPeak_R) { // Right peak
568 pLine->setPeak_R( fNewPeak_R );
569 }
570 else {
571 pLine->setPeak_R( fOldPeak_R / fallOff );
572 }
573
574 // fader position
575 float fNewVolume = pDrumkitComponent->get_volume();
576 float fOldVolume = pLine->getVolume();
577 if (fOldVolume != fNewVolume) {
578 pLine->setVolume(fNewVolume);
579 }
580
581 // mute
582 pLine->setMuteClicked( bMuted );
583
584 // instr name
585 pLine->setName( sName );
586
587 pLine->updateMixerLine();
588 }
589
590 if( pDrumkitComponentList->size() < m_pComponentMixerLine.size() ) {
591 std::vector<int> IdsToDelete;
592 for (std::map<int, ComponentMixerLine*>::iterator it=m_pComponentMixerLine.begin(); it!=m_pComponentMixerLine.end(); ++it) {
593
594 bool bFoundExistingRelatedComponent = false;
595 for ( const auto& pComponent : *pDrumkitComponentList ) {
596 if ( pComponent->get_id() == it->first ) {
597 bFoundExistingRelatedComponent = true;
598 break;
599 }
600 }
601 if ( !bFoundExistingRelatedComponent ) {
602 IdsToDelete.push_back( it->first ) ;
603 }
604 }
605
606 for ( const int nCompoID : IdsToDelete ) {
607 delete m_pComponentMixerLine[nCompoID];
608 m_pComponentMixerLine.erase( nCompoID );
609
610 int newWidth = MIXER_STRIP_WIDTH * ( nInstruments + nCompo );
611 if ( m_pFaderPanel->width() != newWidth ) {
612 m_pFaderPanel->resize( newWidth, height() );
613 }
614 }
615 }
616
617
618 // update MasterPeak
619 float fOldPeak_L = m_pMasterLine->getPeak_L();
620 float fNewPeak_L = pAudioEngine->getMasterPeak_L();
621 pAudioEngine->setMasterPeak_L(0.0);
622 float fOldPeak_R = m_pMasterLine->getPeak_R();
623 float fNewPeak_R = pAudioEngine->getMasterPeak_R();
624 pAudioEngine->setMasterPeak_R(0.0);
625
626 if (!bShowPeaks) {
627 fNewPeak_L = 0.0;
628 fNewPeak_R = 0.0;
629 }
630
631 if (fNewPeak_L >= fOldPeak_L) {
632 m_pMasterLine->setPeak_L( fNewPeak_L );
633 }
634 else {
635 m_pMasterLine->setPeak_L( fOldPeak_L / fallOff );
636 }
637 if (fNewPeak_R >= fOldPeak_R) {
638 m_pMasterLine->setPeak_R(fNewPeak_R);
639 }
640 else {
641 m_pMasterLine->setPeak_R( fOldPeak_R / fallOff );
642 }
643
644
645 // set master fader position
646 float fNewVolume = pSong->getVolume();
647 float fOldVolume = m_pMasterLine->getVolume();
648 if (fOldVolume != fNewVolume) {
649 m_pMasterLine->setVolume(fNewVolume);
650 }
652
653
654#ifdef H2CORE_HAVE_LADSPA
655 // LADSPA
656 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
658 if ( pFX ) {
659 m_pLadspaFXLine[nFX]->setName( pFX->getPluginName() );
660 float fNewPeak_L = 0.0;
661 float fNewPeak_R = 0.0;
662
663 float fOldPeak_L = 0.0;
664 float fOldPeak_R = 0.0;
665 m_pLadspaFXLine[nFX]->getPeaks( &fOldPeak_L, &fOldPeak_R );
666
667 if (fNewPeak_L < fOldPeak_L) fNewPeak_L = fOldPeak_L / fallOff;
668 if (fNewPeak_R < fOldPeak_R) fNewPeak_R = fOldPeak_R / fallOff;
669 m_pLadspaFXLine[nFX]->setPeaks( fNewPeak_L, fNewPeak_R );
670 m_pLadspaFXLine[nFX]->setFxBypassed( ! pFX->isEnabled() );
671 m_pLadspaFXLine[nFX]->setVolume( pFX->getVolume() );
672 }
673 else {
674 m_pLadspaFXLine[nFX]->setName( "No plugin" );
675 m_pLadspaFXLine[nFX]->setFxBypassed( true );
676 m_pLadspaFXLine[nFX]->setVolume( 0.0 );
677 }
678 }
679 // ~LADSPA
680#endif
681}
682
683
684
686void Mixer::showEvent ( QShowEvent *ev )
687{
688 UNUSED( ev );
689 updateMixer();
690}
691
692
693
695void Mixer::hideEvent ( QHideEvent *ev )
696{
697 UNUSED( ev );
698}
699
700
701
703{
704 UNUSED( ref );
706}
707
708
709
715
716
717
719 float fPan = ref->getPan();
720 int nLine = findMixerLineByRef(ref);
721
722 Hydrogen *pHydrogen = Hydrogen::get_instance();
723 CoreActionController* pController = pHydrogen->getCoreActionController();
724
725 pController->setStripPanSym( nLine, fPan, true );
726}
727
728
729
730void Mixer::knobChanged(MixerLine* ref, int nKnob) {
731 int nLine = findMixerLineByRef(ref);
732 Hydrogen *pHydrogen = Hydrogen::get_instance();
733 pHydrogen->setSelectedInstrumentNumber( nLine );
734 auto pSelectedInstrument = pHydrogen->getSelectedInstrument();
735 if ( pSelectedInstrument == nullptr ) {
736 ERRORLOG( "No instrument selected" );
737 return;
738 }
739
740 pSelectedInstrument->set_fx_level( ref->getFXLevel(nKnob), nKnob );
741
742 QString sMessage = tr( "Set FX %1 level [%2] of instrument" )
743 .arg( nKnob )
744 .arg( ref->getFXLevel(nKnob), 0, 'f', 2 );
745 sMessage.append( QString( " [%1]" )
746 .arg( ref->getName() ) );
747 QString sCaller = QString( "%1:knobChanged:%2" )
748 .arg( class_name() ).arg( ref->getName() );
749
751 showStatusBarMessage( sMessage, sCaller );
752
753 pHydrogen->setIsModified( true );
754}
755
756
757
758void Mixer::noteOnEvent( int nInstrument )
759{
760 if ( nInstrument >= 0 && nInstrument < MAX_INSTRUMENTS ) {
761 if ( m_pMixerLine[ nInstrument ] != nullptr ) {
762 m_pMixerLine[ nInstrument ]->setActivity( 100 );
763 }
764 } else {
765 ERRORLOG( QString( "Selected MixerLine [%1] out of bound [0,%2)" )
766 .arg( nInstrument ).arg( MAX_INSTRUMENTS ) );
767 }
768}
769
770
771
772void Mixer::resizeEvent ( QResizeEvent *ev )
773{
774 UNUSED( ev );
775}
776
778{
779 if ( m_pShowFXPanelBtn->isChecked() ) {
780 m_pFXFrame->show();
782 } else {
783 m_pFXFrame->hide();
785 }
786
787 resizeEvent( nullptr ); // force an update
788}
789
791{
793
794 if ( m_pShowPeaksBtn->isChecked() ) {
795 pPref->setInstrumentPeaks( true );
796 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Show instrument peaks = On") );
797 } else {
798 pPref->setInstrumentPeaks( false );
799 ( HydrogenApp::get_instance() )->showStatusBarMessage( tr( "Show instrument peaks = Off") );
800 }
801}
802
803
804
806{
807#ifdef H2CORE_HAVE_LADSPA
808 bool bActive = ! ref->isFxBypassed();
809
810 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
811 if (ref == m_pLadspaFXLine[ nFX ] ) {
813 if (pFX) {
814 pFX->setEnabled( bActive );
815 }
816 break;
817 }
818 }
819#else
820 QMessageBox::critical( this, "Hydrogen", tr("LADSPA effects are not available in this version of Hydrogen.") );
821#endif
822}
823
824
825
827{
828#ifdef H2CORE_HAVE_LADSPA
829
830 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
831 if (ref == m_pLadspaFXLine[ nFX ] ) {
832 HydrogenApp::get_instance()->getLadspaFXProperties(nFX)->hide();
833 HydrogenApp::get_instance()->getLadspaFXProperties(nFX)->show();
834 }
835 }
837#else
838 QMessageBox::critical( this, "Hydrogen", tr("LADSPA effects are not available in this version of Hydrogen.") );
839#endif
840}
841
843{
844#ifdef H2CORE_HAVE_LADSPA
845 for (uint nFX = 0; nFX < MAX_FX; nFX++) {
846 if (ref == m_pLadspaFXLine[ nFX ] ) {
848 if ( pFX != nullptr ) {
849 pFX->setVolume( ref->getVolume() );
850
851 QString sMessage = tr( "Set volume [%1] of FX" )
852 .arg( ref->getVolume(), 0, 'f', 2 );
853 sMessage.append( QString( " [%1]" ).arg( pFX->getPluginName() ) );
854 QString sCaller = QString( "%1:rotaryChanged:%2" )
855 .arg( class_name() ).arg( pFX->getPluginName() );
856
858 showStatusBarMessage( sMessage, sCaller );
859
861 }
862 }
863 }
864#endif
865}
866
867void Mixer::getPeaksInMixerLine( uint nMixerLine, float& fPeak_L, float& fPeak_R )
868{
869 if ( nMixerLine < 0 || nMixerLine >= MAX_INSTRUMENTS ) {
870 ERRORLOG( QString( "Selected MixerLine [%1] out of bound [0,%2)" )
871 .arg( nMixerLine ).arg( MAX_INSTRUMENTS ) );
872 return;
873 }
874 if ( m_pMixerLine[ nMixerLine ] != nullptr ) {
875 fPeak_L = m_pMixerLine[ nMixerLine ]->getPeak_L();
876 fPeak_R = m_pMixerLine[ nMixerLine ]->getPeak_R();
877 }
878 else {
879 fPeak_L = 0;
880 fPeak_R = 0;
881 }
882}
883
885 MixerSettingsDialog mixerSettingsDialog( this ); // use this as *parent because button makes smaller fonts
886 mixerSettingsDialog.exec();
887}
888
889
892
893 if ( changes & H2Core::Preferences::Changes::Font ) {
894 setFont( QFont( pPref->getApplicationFontFamily(), 10 ) );
895 }
896}
#define MIXER_STRIP_WIDTH
Definition Mixer.cpp:47
#define INFOLOG(x)
Definition Object.h:237
#define ERRORLOG(x)
Definition Object.h:239
Generic Button with SVG icons or text.
Definition Button.h:60
@ Push
Button is not set checkable.
@ Toggle
Button is set checkable.
void setMuteClicked(bool isClicked)
void setSoloClicked(bool isClicked)
void setVolume(float value)
void setName(QString name)
Definition MixerLine.h:195
void setPeak_R(float peak)
void setPeak_L(float peak)
The audio engine deals with two distinct #TransportPosition.
Definition AudioEngine.h:97
float getMasterPeak_L() const
void setMasterPeak_R(float value)
float getMasterPeak_R() const
Sampler * getSampler() const
void setMasterPeak_L(float value)
virtual const char * class_name() const
Definition Object.h:79
bool setStripVolume(int nStrip, float fVolumeValue, bool bSelectStrip)
bool setStripPanSym(int nStrip, float fValue, bool bSelectStrip)
bool setStripIsMuted(int nStrip, bool isMuted)
bool setMasterVolume(float masterVolumeValue)
bool setStripIsSoloed(int nStrip, bool isSoloed)
static Effects * get_instance()
Returns a pointer to the current Effects singleton stored in __instance.
Definition Effects.h:54
LadspaFX * getLadspaFX(int nFX) const
Definition Effects.cpp:91
Hydrogen Audio Engine.
Definition Hydrogen.h:54
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
int getSelectedInstrumentNumber() const
Definition Hydrogen.h:664
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
Definition Hydrogen.cpp:918
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
std::shared_ptr< Instrument > getSelectedInstrument() const
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:639
void setEnabled(bool bEnabled)
Definition LadspaFx.cpp:201
const QString & getPluginName() const
Definition LadspaFX.h:146
void setVolume(float fVolume)
Definition LadspaFx.cpp:472
bool isEnabled() const
Definition LadspaFX.h:155
float getVolume() const
Definition LadspaFX.h:166
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:102
void set_note_off(bool value)
__note_off setter
Definition Note.h:575
Manager for User Preferences File (singleton)
Definition Preferences.h:78
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setFXTabVisible(bool value)
void setInstrumentPeaks(bool value)
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ Font
Either the font size or font family have changed.
void noteOff(Note *pNote)
Stop playing a note.
Definition Sampler.cpp:241
void noteOn(Note *pNote)
Start playing a note.
Definition Sampler.cpp:190
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
void showMixer(bool bShow)
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
static InstrumentEditorPanel * get_instance()
void setPeaks(float fPeak_L, float fPeak_R)
void setVolume(float value)
void setName(QString name)
void setFxBypassed(bool active)
void getPeaks(float *fPeak_L, float *fPeak_R)
void setVolume(float value)
void setPeak_R(float peak)
void setPeak_L(float peak)
void updateMixerLine()
A mixer strip.
Definition MixerLine.h:84
bool isMuteClicked()
void setMuteClicked(bool isClicked)
float getPeak_L()
void setSelected(bool bIsSelected)
void setSoloClicked(bool isClicked)
void setPlayClicked(bool clicked)
void setFXLevel(uint nFX, float fValue)
void setVolume(float value)
bool isSoloClicked()
float getPan()
void setName(QString name)
Definition MixerLine.h:109
float getFXLevel(uint nFX)
void setPeak_R(float peak)
float getPeak_R()
void setPan(float value)
QString getName()
Definition MixerLine.h:110
float getVolume()
void setActivity(uint value)
Definition MixerLine.h:116
void setPeak_L(float peak)
void updateMixerLine()
int getActivity()
Definition MixerLine.h:115
Mixer Settings Dialog.
void hideEvent(QHideEvent *ev) override
hide event
Definition Mixer.cpp:695
void openMixerSettingsDialog()
Definition Mixer.cpp:884
QScrollArea * m_pFaderScrollArea
Definition Mixer.h:87
PixmapWidget * m_pFXFrame
Definition Mixer.h:97
QTimer * m_pUpdateTimer
Definition Mixer.h:99
QWidget * m_pFaderPanel
Definition Mixer.h:93
void masterVolumeChanged(MasterMixerLine *)
Definition Mixer.cpp:397
uint findCompoMixerLineByRef(ComponentMixerLine *ref)
Definition Mixer.cpp:376
LadspaFXMixerLine * m_pLadspaFXLine[MAX_FX]
Definition Mixer.h:85
void panChanged(MixerLine *ref)
Definition Mixer.cpp:718
void noteOffClicked(MixerLine *ref)
Play sample button, right-clicked (note off)
Definition Mixer.cpp:345
void noteOnClicked(MixerLine *ref)
Definition Mixer.cpp:319
void resizeEvent(QResizeEvent *ev) override
Definition Mixer.cpp:772
MixerLine * m_pMixerLine[MAX_INSTRUMENTS]
Definition Mixer.h:94
void onPreferencesChanged(H2Core::Preferences::Changes changes)
Definition Mixer.cpp:890
void muteClicked(MixerLine *ref)
Definition Mixer.cpp:216
void showPeaksBtnClicked()
Definition Mixer.cpp:790
Button * m_pOpenMixerSettingsBtn
Definition Mixer.h:90
void closeEvent(QCloseEvent *event) override
Definition Mixer.cpp:194
void getPeaksInMixerLine(uint nMixerLine, float &fPeak_L, float &fPeak_R)
Definition Mixer.cpp:867
virtual void noteOnEvent(int nInstrument) override
Definition Mixer.cpp:758
~Mixer()
Definition Mixer.cpp:168
bool isSoloClicked(uint nLine)
Definition Mixer.cpp:306
void ladspaEditBtnClicked(LadspaFXMixerLine *ref)
Definition Mixer.cpp:826
void showEvent(QShowEvent *ev) override
show event
Definition Mixer.cpp:686
Button * m_pShowFXPanelBtn
Definition Mixer.h:88
MasterMixerLine * m_pMasterLine
Definition Mixer.h:91
std::map< int, ComponentMixerLine * > m_pComponentMixerLine
Definition Mixer.h:95
MixerLine * createMixerLine(int)
Definition Mixer.cpp:173
void showFXPanelClicked()
Definition Mixer.cpp:777
void nameSelected(MixerLine *ref)
Definition Mixer.cpp:710
void knobChanged(MixerLine *ref, int nKnob)
Definition Mixer.cpp:730
void ladspaBypassBtnClicked(LadspaFXMixerLine *ref)
Definition Mixer.cpp:805
void nameClicked(MixerLine *ref)
Definition Mixer.cpp:702
uint findMixerLineByRef(MixerLine *ref)
Definition Mixer.cpp:365
Mixer(QWidget *parent)
Definition Mixer.cpp:50
void soloClicked(uint nLine)
used in PatternEditorInstrumentList
Definition Mixer.cpp:288
void updateMixer()
Definition Mixer.cpp:408
Button * m_pShowPeaksBtn
Definition Mixer.h:89
void ladspaVolumeChanged(LadspaFXMixerLine *ref)
Definition Mixer.cpp:842
void volumeChanged(MixerLine *ref)
Definition Mixer.cpp:388
QHBoxLayout * m_pFaderHBox
Definition Mixer.h:84
ComponentMixerLine * createComponentMixerLine(int)
Definition Mixer.cpp:200
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
Definition config.dox:70
#define MAX_FX
Maximum number of effects.
Definition config.dox:83
#define UNUSED(v)
Definition Globals.h:42