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