hydrogen 1.2.6
PlayerControl.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
20https://www.gnu.org/licenses
21 *
22 */
23
24
25#include "Skin.h"
26#include "CommonStrings.h"
27#include "PlayerControl.h"
28#include "InstrumentRack.h"
29#include "HydrogenApp.h"
30
32#include "Widgets/LCDDisplay.h"
33#include "Widgets/LCDSpinBox.h"
34#include "Widgets/LED.h"
35#include "Widgets/Button.h"
39
40#include "Mixer/Mixer.h"
44
45#include <core/Hydrogen.h>
46#include <core/Basics/Song.h>
50#include <core/EventQueue.h>
51using namespace H2Core;
52
53
54//beatconter global
56// ~ beatcounter
57
59 : QLabel(parent)
62{
63
65
66 setObjectName( "PlayerControl" );
68
70 auto pSong = m_pHydrogen->getSong();
71 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
72
73 // Background image
74 setPixmap( QPixmap( Skin::getImagePath() + "/playerControlPanel/background.png" ) );
75 setScaledContents( true );
76
77 QHBoxLayout *hbox = new QHBoxLayout();
78 hbox->setSpacing( 0 );
79 hbox->setContentsMargins( 0, 0, 0, 0 );
80 setLayout( hbox );
81
82// CONTROLS
83 PixmapWidget *pControlsPanel = new PixmapWidget( nullptr );
84 pControlsPanel->setFixedSize( 344, m_nMinimumHeight );
85 pControlsPanel->setPixmap( "/playerControlPanel/background_Control.png" );
86 pControlsPanel->setObjectName( "ControlsPanel" );
87 hbox->addWidget( pControlsPanel );
88
89 m_pTimeDisplay = new LCDDisplay( pControlsPanel, QSize( 146, 22 ), true, false );
90 m_pTimeDisplay->move( 13, 7 );
91 m_pTimeDisplay->setAlignment( Qt::AlignRight );
92 m_pTimeDisplay->setText( "00:00:00:000" );
93 m_pTimeDisplay->setStyleSheet( m_pTimeDisplay->styleSheet().
94 append(" QLineEdit { font-size: 19px; }" ) );
95
96 m_pTimeHoursLbl = new ClickableLabel( pControlsPanel, QSize( 33, 9 ),
97 pCommonStrings->getTimeHoursLabel() );
98 m_pTimeHoursLbl->move( 22, 30 );
99 m_pTimeMinutesLbl = new ClickableLabel( pControlsPanel, QSize( 33, 9 ),
100 pCommonStrings->getTimeMinutesLabel() );
101 m_pTimeMinutesLbl->move( 53, 30 );
102 m_pTimeSecondsLbl = new ClickableLabel( pControlsPanel, QSize( 33, 9 ),
103 pCommonStrings->getTimeSecondsLabel() );
104 m_pTimeSecondsLbl->move( 83, 30 );
105 m_pTimeMilliSecondsLbl = new ClickableLabel( pControlsPanel, QSize( 34, 9 ),
106 pCommonStrings->getTimeMilliSecondsLabel() );
107 m_pTimeMilliSecondsLbl->move( 119, 30 );
108
109 // Rewind button
110 m_pRwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push,
111 "rewind.svg", "", false, QSize( 13, 13 ), tr("Rewind") );
112 m_pRwdBtn->setObjectName( "PlayerControlRewindButton" );
113 m_pRwdBtn->move( 166, 15 );
114 connect(m_pRwdBtn, SIGNAL( clicked() ), this, SLOT( rewindBtnClicked() ));
115 std::shared_ptr<Action> pAction = std::make_shared<Action>("<<_PREVIOUS_BAR");
116 m_pRwdBtn->setAction( pAction );
117
118 // Record button
119 m_pRecBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Toggle,
120 "record.svg", "", false, QSize( 11, 11 ), tr("Record"), true );
121 m_pRecBtn->setObjectName( "PlayerControlRecordButton" );
122 m_pRecBtn->move( 193, 15 );
123 m_pRecBtn->setChecked(false);
124 m_pRecBtn->setHidden(false);
125 connect(m_pRecBtn, SIGNAL( clicked() ), this, SLOT( recBtnClicked() ));
126 pAction = std::make_shared<Action>("RECORD_READY");
127 m_pRecBtn->setAction( pAction );
128
129 // Play button
130 m_pPlayBtn = new Button( pControlsPanel, QSize( 30, 21 ), Button::Type::Toggle,
131 "play_pause.svg", "", false, QSize( 30, 21 ), tr("Play/ Pause") );
132 m_pPlayBtn->setObjectName( "PlayerControlPlayButton" );
133 m_pPlayBtn->move( 220, 15 );
134 m_pPlayBtn->setChecked(false);
135 connect(m_pPlayBtn, SIGNAL( clicked() ), this, SLOT( playBtnClicked() ));
136 pAction = std::make_shared<Action>("PLAY/PAUSE_TOGGLE");
137 m_pPlayBtn->setAction( pAction );
138
139 // Stop button
140 m_pStopBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push,
141 "stop.svg", "", false, QSize( 11, 11 ), tr("Stop") );
142 m_pStopBtn->setObjectName( "PlayerControlStopButton" );
143 m_pStopBtn->move( 252, 15 );
144 connect(m_pStopBtn, SIGNAL( clicked() ), this, SLOT( stopBtnClicked() ));
145 pAction = std::make_shared<Action>("STOP");
146 m_pStopBtn->setAction( pAction );
147
148 // Fast forward button
149 m_pFfwdBtn = new Button( pControlsPanel, QSize( 25, 19 ), Button::Type::Push,
150 "fast_forward.svg", "", false, QSize( 13, 13 ), tr("Fast Forward") );
151 m_pFfwdBtn->setObjectName( "PlayerControlForwardButton" );
152 m_pFfwdBtn->move( 279, 15 );
153 connect(m_pFfwdBtn, SIGNAL( clicked() ), this, SLOT( fastForwardBtnClicked() ));
154 pAction = std::make_shared<Action>(">>_NEXT_BAR");
155 m_pFfwdBtn->setAction( pAction );
156
157 // Loop song button button
158 m_pSongLoopBtn = new Button( pControlsPanel, QSize( 25, 19 ),
159 Button::Type::Toggle, "loop.svg", "", false,
160 QSize( 17, 13 ), tr("Loop song"),
161 false, true );
162 m_pSongLoopBtn->setObjectName( "PlayerControlLoopButton" );
163 m_pSongLoopBtn->move( 308, 15);
164 connect( m_pSongLoopBtn, &QPushButton::clicked,
165 [=]( bool bChecked ) { Hydrogen::get_instance()->getCoreActionController()->
166 activateLoopMode( bChecked );
167 });
168 if ( pSong->getLoopMode() == Song::LoopMode::Enabled ) {
169 m_pSongLoopBtn->setChecked( true );
170 }
171
172 // Live mode button
173 m_pPatternModeLED = new LED( pControlsPanel, QSize( 11, 9 ) );
174 m_pPatternModeLED->move( 179, 4 );
175 m_pPatternModeLED->setActivated( true );
176 m_pPatternModeBtn = new Button( pControlsPanel, QSize( 59, 11 ),
178 pCommonStrings->getPatternModeButton(),
179 false, QSize(), tr("Pattern Mode"),
180 false, true );
181 m_pPatternModeBtn->setObjectName( "PlayerControlPatternModeButton" );
182 m_pPatternModeBtn->move( 190, 3 );
183 m_pPatternModeBtn->setChecked(true);
184 connect( m_pPatternModeBtn, &QPushButton::clicked,
185 [=]() { activateSongMode( false ); } );
186
187 // Song mode button
188 m_pSongModeLED = new LED( pControlsPanel, QSize( 11, 9 ) );
189 m_pSongModeLED->move( 252, 4 );
190 m_pSongModeBtn = new Button( pControlsPanel, QSize( 59, 11 ),
192 pCommonStrings->getSongModeButton(),
193 false, QSize(), tr("Song Mode"),
194 false, true );
195 m_pSongModeBtn->setObjectName( "PlayerControlSongModeButton" );
196 m_pSongModeBtn->move( 263, 3 );
197 connect( m_pSongModeBtn, &QPushButton::clicked,
198 [=]() { activateSongMode( true ); } );
199
200 if ( m_pHydrogen->getMode() == Song::Mode::Song ) {
201 m_pSongModeBtn->setChecked( true );
202 m_pPatternModeBtn->setChecked( false );
203 m_pSongModeLED->setActivated( true );
204 m_pPatternModeLED->setActivated( false );
205 } else {
206 m_pSongModeBtn->setChecked( false );
207 m_pPatternModeBtn->setChecked( true );
208 m_pSongModeLED->setActivated( false );
209 m_pPatternModeLED->setActivated( true );
210
211 m_pSongLoopBtn->setIsActive( false );
212 }
213
214
215
216// ~ CONTROLS
217
218// BC on off
219 QWidget *pControlsBBTBConoffPanel = new QWidget( nullptr );
220 pControlsBBTBConoffPanel->setFixedSize( 15, 43 );
221 pControlsBBTBConoffPanel->setObjectName( "BeatCounterOnOff" );
222 hbox->addWidget( pControlsBBTBConoffPanel );
223
224 m_sBCOnOffBtnToolTip = tr("Toggle the BeatCounter Panel");
225 m_sBCOnOffBtnTimelineToolTip = tr( "Please deactivate the Timeline first in order to use the BeatCounter" );
226 m_sBCOnOffBtnJackTimebaseToolTip = tr( "In the presence of an external JACK Timebase controller the BeatCounter can not be used" );
227 m_pBCOnOffBtn = new Button( pControlsBBTBConoffPanel, QSize( 13, 42 ),
229 pCommonStrings->getBeatCounterButton(), false,
230 QSize(), m_sBCOnOffBtnToolTip,
231 false, true );
232 m_pBCOnOffBtn->move(0, 0);
233 if ( pPref->m_bbc == Preferences::BC_ON ) {
235 } else {
237 }
238 if ( m_pHydrogen->getTempoSource() != H2Core::Hydrogen::Tempo::Song ) {
239 m_pBCOnOffBtn->setChecked( false );
240 m_pBCOnOffBtn->setIsActive( false );
241 } else {
243 }
245
246 connect(m_pBCOnOffBtn, SIGNAL( clicked(bool) ), this, SLOT( activateBeatCounter(bool) ));
247 pAction = std::make_shared<Action>("BEATCOUNTER");
248 m_pBCOnOffBtn->setAction( pAction );
249// ~ BC on off
250
251//beatcounter
252 m_pControlsBCPanel = new PixmapWidget( nullptr );
253 m_pControlsBCPanel->setFixedSize( 86, 43 );
254 m_pControlsBCPanel->setPixmap( "/playerControlPanel/beatConter_BG.png" );
255 m_pControlsBCPanel->setObjectName( "BeatCounter" );
256 hbox->addWidget( m_pControlsBCPanel );
257
258
259 m_pBCDisplayZ = new QLabel( m_pControlsBCPanel );
260 m_pBCDisplayZ->resize( QSize( 23, 13 ) );
261 m_pBCDisplayZ->move( 45, 8 );
262 m_pBCDisplayZ->setText( "--" );
263
264 QLabel* pLabelBC1 = new QLabel( m_pControlsBCPanel );
265 pLabelBC1->resize( QSize( 9, 11 ) );
266 pLabelBC1->move( 25, 9 );
267 pLabelBC1->setText( "1" );
268 QLabel* pLabelBC2 = new QLabel( m_pControlsBCPanel );
269 pLabelBC2->resize( QSize( 9, 3 ) );
270 pLabelBC2->move( 25, 20 );
271 pLabelBC2->setText( "—" );
272
273 m_pBCDisplayT = new QLabel( m_pControlsBCPanel );
274 m_pBCDisplayT->resize( QSize( 9, 11 ) );
275 m_pBCDisplayT->move( 25, 25 );
276 m_pBCDisplayT->setText( "4" );
277
278 m_pBCDisplayB = new QLabel( m_pControlsBCPanel );
279 m_pBCDisplayB->resize( QSize( 23, 11 ) );
280 m_pBCDisplayB->move( 45, 25 );
281 m_pBCDisplayB->setText( "04" );
282
283 m_pBCTUpBtn = new Button( m_pControlsBCPanel, QSize( 19, 12 ),
284 Button::Type::Push, "plus.svg", "", false,
285 QSize( 8, 8 ), "", false, true );
286 m_pBCTUpBtn->move( 2, 3 );
287 connect( m_pBCTUpBtn, SIGNAL( clicked() ), this, SLOT( bctUpButtonClicked() ) );
288
289 m_pBCTDownBtn = new Button( m_pControlsBCPanel, QSize( 19, 12 ),
290 Button::Type::Push, "minus.svg", "", false,
291 QSize( 8, 8 ), "", false, true );
292 m_pBCTDownBtn->move( 2, 14 );
293 connect( m_pBCTDownBtn, SIGNAL( clicked() ), this, SLOT( bctDownButtonClicked() ) );
294
295 m_pBCBUpBtn = new Button( m_pControlsBCPanel, QSize( 19, 12 ),
296 Button::Type::Push, "plus.svg", "", false,
297 QSize( 8, 8 ), "", false, true );
298 m_pBCBUpBtn->move( 64, 3 );
299 connect( m_pBCBUpBtn, SIGNAL( clicked() ), this, SLOT( bcbUpButtonClicked() ) );
300
301 m_pBCBDownBtn = new Button( m_pControlsBCPanel, QSize( 19, 12 ),
302 Button::Type::Push, "minus.svg", "", false,
303 QSize( 8, 8 ), "", false, true );
304 m_pBCBDownBtn->move( 64, 14 );
305 connect( m_pBCBDownBtn, SIGNAL( clicked() ), this, SLOT( bcbDownButtonClicked() ) );
306
307 m_pBCSetPlayBtn = new Button( m_pControlsBCPanel, QSize( 19, 15 ),
309 pCommonStrings->getBeatCounterSetPlayButtonOff(),
310 false, QSize(),
311 tr("Set BPM / Set BPM and play"),
312 false, true );
313 m_pBCSetPlayBtn->setObjectName( "BeatCounterSetPlayButton" );
314 m_pBCSetPlayBtn->move( 64, 25 );
315 connect(m_pBCSetPlayBtn, SIGNAL( clicked() ), this, SLOT( bcSetPlayBtnClicked() ));
316// ~ beatcounter
317
318
319// BPM
320 m_sLCDBPMSpinboxToolTip = tr("Alter the Playback Speed");
321 m_sLCDBPMSpinboxTimelineToolTip = tr( "While the Timeline is active this widget is in read-only mode and just displays the tempo set using the current Timeline position" );
322 m_sLCDBPMSpinboxJackTimebaseToolTip = tr( "In the presence of an external JACK Timebase controller this widget just displays the tempo broadcasted by JACK" );
323
324 PixmapWidget *pBPMPanel = new PixmapWidget( nullptr );
325 pBPMPanel->setFixedSize( 145, 43 );
326 pBPMPanel->setPixmap( "/playerControlPanel/background_BPM.png" );
327 pBPMPanel->setObjectName( "BPM" );
328 hbox->addWidget( pBPMPanel );
329 m_pBPMLbl = new ClickableLabel( pBPMPanel, QSize( 26, 10 ),
330 pCommonStrings->getBPMLabel(), ClickableLabel::Color::Dark );
331 m_pBPMLbl->move( 36, 31 );
332
333 // LCD BPM SpinBox
334 m_pLCDBPMSpinbox = new LCDSpinBox( pBPMPanel, QSize( 95, 30), LCDSpinBox::Type::Double,
335 static_cast<double>( MIN_BPM ),
336 static_cast<double>( MAX_BPM ), true );
337 m_pLCDBPMSpinbox->move( 36, 1 );
338 m_pLCDBPMSpinbox->setStyleSheet( m_pLCDBPMSpinbox->styleSheet().
339 append( " QAbstractSpinBox {font-size: 16px;}" ) );
340 connect( m_pLCDBPMSpinbox, SIGNAL( valueChanged( double ) ),
341 this, SLOT( bpmChanged( double ) ) );
342 // initialize BPM widget
343 m_pLCDBPMSpinbox->setIsActive( m_pHydrogen->getTempoSource() ==
345 m_pLCDBPMSpinbox->setValue( m_pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
347
348 m_pRubberBPMChange = new Button( pBPMPanel, QSize( 13, 42 ),
350 pCommonStrings->getRubberbandButton(),
351 false, QSize(),
352 tr("Recalculate Rubberband modified samples if bpm will change"),
353 false, true );
354 m_pRubberBPMChange->setObjectName( "PlayerControlRubberbandButton" );
355 m_pRubberBPMChange->move( 131, 0 );
356 m_pRubberBPMChange->setChecked( pPref->getRubberBandBatchMode());
357 connect( m_pRubberBPMChange, SIGNAL( clicked() ), this, SLOT( rubberbandButtonToggle() ) );
358 QString program = pPref->m_rubberBandCLIexecutable;
359 //test the path. if test fails, no button
360 if ( QFile( program ).exists() == false) {
361 m_pRubberBPMChange->hide();
362 }
363
364 m_pMetronomeLED = new MetronomeLED( pBPMPanel, QSize( 22, 7 ) );
365 m_pMetronomeLED->move( 7, 32 );
366
367 m_pMetronomeBtn = new Button( pBPMPanel, QSize( 24, 28 ),
368 Button::Type::Toggle, "metronome.svg", "",
369 false, QSize( 20, 20 ),
370 tr("Switch metronome on/off"),
371 false, true );
372 m_pMetronomeBtn->setObjectName( "MetronomeButton" );
373 m_pMetronomeBtn->move( 6, 2 );
374 connect( m_pMetronomeBtn, SIGNAL( clicked() ), this, SLOT( metronomeButtonClicked() ) );
375 pAction = std::make_shared<Action>("TOGGLE_METRONOME");
376 m_pMetronomeBtn->setAction( pAction );
377 m_pMetronomeBtn->setChecked( pPref->m_bUseMetronome );
378
379// ~ BPM
380
381
382// JACK
383 PixmapWidget *pJackPanel = new PixmapWidget( nullptr );
384 pJackPanel->setFixedSize( 124, 43 );
385 pJackPanel->setPixmap( "/playerControlPanel/background_Jack.png" );
386 pJackPanel->setObjectName( "JackPanel" );
387 hbox->addWidget( pJackPanel );
388
389 // Jack transport mode button
390
391 /*: Using the JACK the audio/midi input and output ports of any
392 number of application can be connected.*/
393 m_pJackTransportBtn = new Button( pJackPanel, QSize( 53, 16 ),
395 pCommonStrings->getJackTransportButton(),
396 false, QSize(),
397 tr("JACK transport on/off"),
398 false, true );
399 m_pJackTransportBtn->setObjectName( "PlayerControlJackTransportButton" );
400 if ( ! m_pHydrogen->hasJackAudioDriver() ) {
401 m_pJackTransportBtn->hide();
402 }
403 if ( m_pHydrogen->hasJackTransport() ) {
404 m_pJackTransportBtn->setChecked( true );
405 } else {
406 m_pJackTransportBtn->setChecked( false );
407 }
408 connect(m_pJackTransportBtn, SIGNAL( clicked() ), this, SLOT( jackTransportBtnClicked() ));
409 m_pJackTransportBtn->move( 3, 24 );
410
412 pJackPanel, QSize( 64, 16 ), Button::Type::Toggle, "",
413 pCommonStrings->getJackTimebaseButton(), false, QSize(),
414 pCommonStrings->getJackTimebaseTooltip(), false, true );
415 m_pJackTimebaseBtn->setObjectName( "PlayerControlJackTimebaseButton" );
416 if ( ! m_pHydrogen->hasJackAudioDriver() ) {
417 m_pJackTimebaseBtn->hide();
418 }
419
420 if ( pPref->m_bJackTimebaseEnabled ) {
421 if ( m_pHydrogen->hasJackTransport() ) {
422 if ( m_pHydrogen->getJackTimebaseState() ==
424 m_pJackTimebaseBtn->setChecked( true );
425 }
426 else if ( m_pHydrogen->getJackTimebaseState() ==
428 m_pJackTimebaseBtn->setChecked( true );
429 m_pJackTimebaseBtn->setUseRedBackground( true );
430 m_pJackTimebaseBtn->setToolTip(
431 pCommonStrings->getJackTimebaseListenerTooltip() );
432 }
433 else {
434 m_pJackTimebaseBtn->setChecked( false );
435 }
436 }
437 else {
438 m_pJackTimebaseBtn->setIsActive( false );
439 }
440 }
441 else {
442 m_pJackTimebaseBtn->setIsActive( false );
443 m_pJackTimebaseBtn->setBaseToolTip(
444 pCommonStrings->getJackTimebaseDisabledTooltip() );
445 }
446
447 connect( m_pJackTimebaseBtn, SIGNAL( clicked() ), this,
448 SLOT( jackTimebaseBtnClicked() ) );
449 m_pJackTimebaseBtn->move( 56, 24 );
450
451 // CPU load widget
452 m_pCpuLoadWidget = new CpuLoadWidget( pJackPanel );
453 m_pCpuLoadWidget->setObjectName( "CpuLoadWidget" );
454
455 // Midi Activity widget
456 m_pMidiActivityLED = new LED( pJackPanel, QSize( 11, 9 ) );
457 m_pMidiActivityLED->setObjectName( "MidiActivityLED" );
458 m_pMidiActivityTimer = new QTimer( this );
459 connect( m_pMidiActivityTimer, SIGNAL( timeout() ),
460 this, SLOT( deactivateMidiActivityLED() ) );
461 m_pMidiInLbl = new ClickableLabel( pJackPanel, QSize( 45, 9 ),
462 pCommonStrings->getMidiInLabel() );
463 m_pMidiInLbl->move( 22, 14 );
464 m_pCpuLbl = new ClickableLabel( pJackPanel, QSize( 30, 9 ),
465 pCommonStrings->getCpuLabel() );
466 m_pCpuLbl->move( 71, 14 );
467
468 m_pMidiActivityLED->move( 11, 14 );
469 m_pCpuLoadWidget->move( 10, 3 );
470// ~ JACK
471
472
473 QWidget *pLcdBackGround = new QWidget( nullptr );
474 pLcdBackGround->setFixedSize( 256, 43 );
475 pLcdBackGround->setObjectName( "LcdBackground" );
476 hbox->addWidget( pLcdBackGround );
477
478 m_pShowMixerBtn = new Button( pLcdBackGround, QSize( 88, 23 ), Button::Type::Toggle,
479 "", pCommonStrings->getMixerButton(), false, QSize(),
480 tr( "Show mixer" ) );
481 m_pShowMixerBtn->move( 0, 0 );
482 connect(m_pShowMixerBtn, SIGNAL( clicked() ), this, SLOT( showMixerButtonClicked() ));
483
484 m_pShowInstrumentRackBtn = new Button( pLcdBackGround, QSize( 168, 23 ), Button::Type::Toggle,
485 "", pCommonStrings->getInstrumentRackButton(), false, QSize(),
486 tr( "Show Instrument Rack" ) );
487 m_pShowInstrumentRackBtn->move( 88, 0 );
488 connect( m_pShowInstrumentRackBtn, SIGNAL( clicked() ),
489 this, SLOT( showInstrumentRackButtonClicked() ) );
490
491 m_pStatusLabel = new StatusMessageDisplay( pLcdBackGround, QSize( 255, 18 ) );
492 m_pStatusLabel->move( 0, 24 );
493
494 hbox->addStretch( 1000 ); // this must be the last widget in the HBOX!!
495
496 QTimer *timer = new QTimer( this );
497 connect(timer, SIGNAL(timeout()), this, SLOT(updatePlayerControl()));
498 timer->start(100); // update player control at 10 fps
499
502}
503
504
505
506
509
510
511
512
513
515{
518
519 if ( ! m_pShowMixerBtn->isDown() ) {
520 m_pShowMixerBtn->setChecked( pH2App->getMixer()->isVisible() );
521 }
522 if ( ! m_pShowInstrumentRackBtn->isDown() ) {
523 m_pShowInstrumentRackBtn->setChecked( pH2App->getInstrumentRack()->isVisible() );
524 }
525
526 auto state = m_pHydrogen->getAudioEngine()->getState();
527 if ( ! m_pPlayBtn->isDown() && ! m_pStopBtn->isDown() &&
528 ! m_pFfwdBtn->isDown() && ! m_pRwdBtn->isDown() ) {
530 m_pPlayBtn->setChecked(true);
531 } else {
532 m_pPlayBtn->setChecked(false);
533 }
534 }
535
536 if ( ! m_pRecBtn->isDown() ) {
537 if (pPref->getRecordEvents()) {
538 m_pRecBtn->setChecked(true);
539 } else {
540 m_pRecBtn->setChecked(false);
541 }
542 }
543
544 std::shared_ptr<Song> song = m_pHydrogen->getSong();
545
546 if ( ! m_pLCDBPMSpinbox->hasFocus() &&
547 ! m_pLCDBPMSpinbox->getIsHovered() ) {
549 m_pLCDBPMSpinbox->setValue( m_pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
551 }
552
553 //beatcounter
554 if ( pPref->m_bbc == Preferences::BC_OFF ) {
555 m_pControlsBCPanel->hide();
556 if ( ! m_pBCOnOffBtn->isDown() ) {
557 m_pBCOnOffBtn->setChecked(false);
558 }
559 } else {
560 m_pControlsBCPanel->show();
561 if ( ! m_pBCOnOffBtn->isDown() ) {
562 m_pBCOnOffBtn->setChecked(true);
563 }
564 }
565
566 if ( ! m_pBCSetPlayBtn->isDown() ) {
568 m_pBCSetPlayBtn->setChecked(false);
569 } else {
570 m_pBCSetPlayBtn->setChecked(true);
571 }
572 }
573 // ~ beatcounter
574
575 // time
576 float fSeconds = m_pHydrogen->getAudioEngine()->getElapsedTime();
577
578 int nMSec = (int)( (fSeconds - (int)fSeconds) * 1000.0 );
579 int nSeconds = ( (int)fSeconds ) % 60;
580 int nMins = (int)( fSeconds / 60.0 ) % 60;
581 int nHours = (int)( fSeconds / 3600.0 );
582
583 QString sTime = QString( "%1:%2:%3.%4" )
584 .arg( nHours, 2, 10, QLatin1Char( '0' ) )
585 .arg( nMins, 2, 10, QLatin1Char( '0' ) )
586 .arg( nSeconds, 2, 10, QLatin1Char( '0' ) )
587 .arg( nMSec, 3, 10, QLatin1Char( '0' ) );
588
589 if ( m_pTimeDisplay->text() != sTime ) {
590 m_pTimeDisplay->setText( sTime );
591 }
592
593 if ( ! m_pMetronomeBtn->isDown() ) {
594 m_pMetronomeBtn->setChecked(pPref->m_bUseMetronome);
595 }
596
597
598 //beatcounter get BC message
599 char bcstatus[4];
600 int beatstocountondisplay = 1;
601 beatstocountondisplay = m_pHydrogen->getBcStatus();
602
603 switch (beatstocountondisplay){
604 case 1 :
605 if (bcDisplaystatus == 1){
607 bcDisplaystatus = 0;
608 }
609 sprintf(bcstatus, "R");
610 if ( m_pBCDisplayZ->text() != bcstatus ) {
611 m_pBCDisplayZ->setText( QString (bcstatus) );
612 }
613
614 break;
615 default:
618 bcDisplaystatus = 1;
619 }
620 sprintf(bcstatus, "%02d ", beatstocountondisplay -1);
621 if ( m_pBCDisplayZ->text() != bcstatus ) {
622 m_pBCDisplayZ->setText( QString (bcstatus) );
623 }
624
625 }
626
627 // Rubberband
628 if ( m_pRubberBPMChange->isChecked() != pPref->getRubberBandBatchMode() ) {
629 m_pRubberBPMChange->setChecked( pPref->getRubberBandBatchMode());
630 }
631}
632
633
634
637 if ( m_pHydrogen->getAudioEngine()->getState() != H2Core::AudioEngine::State::Playing ) {
638 if ( m_pRecBtn->isChecked() ) {
640 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Record midi events = On" ) );
641 }
642 else {
644 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Record midi events = Off" ) );
645 }
646 }
647}
648
651 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
652
653 // Hint that something is wrong in case there is no proper audio
654 // driver set.
655 if ( m_pHydrogen->getAudioOutput() == nullptr ||
656 dynamic_cast<NullDriver*>(m_pHydrogen->getAudioOutput()) != nullptr ) {
657 QMessageBox::warning( this, "Hydrogen",
658 QString( "%1\n%2" )
659 .arg( pCommonStrings->getAudioDriverNotPresent() )
660 .arg( pCommonStrings->getAudioDriverErrorHint() ) );
661 return;
662 }
663
664 if ( m_pPlayBtn->isChecked() ) {
665 m_pHydrogen->sequencer_play();
666 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Playing.") );
667 }
668 else {
669 m_pHydrogen->sequencer_stop();
671 }
672}
673
676{
677 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
678
679 // Hint that something is wrong in case there is no proper audio
680 // driver set.
681 if ( m_pHydrogen->getAudioOutput() == nullptr ||
682 dynamic_cast<NullDriver*>(m_pHydrogen->getAudioOutput()) != nullptr ) {
683 QMessageBox::warning( this, "Hydrogen",
684 QString( "%1\n%2" )
685 .arg( pCommonStrings->getAudioDriverNotPresent() )
686 .arg( pCommonStrings->getAudioDriverErrorHint() ) );
687 return;
688 }
689
690 if ( ! m_pPlayBtn->isDown() ) {
691 m_pPlayBtn->setChecked(false);
692 }
693 m_pHydrogen->sequencer_stop();
694 m_pHydrogen->getCoreActionController()->locateToColumn( 0 );
695 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Stopped.") );
696}
697
699 m_pMidiActivityTimer->stop();
700 m_pMidiActivityLED->setActivated( true );
701 m_pMidiActivityTimer->start( std::chrono::duration_cast<std::chrono::milliseconds>( m_midiActivityTimeout )
702 .count() );
703}
704
706 m_pMidiActivityTimer->stop();
707 m_pMidiActivityLED->setActivated( false );
708}
709
711 // A new song got loaded
712 if ( nValue == 0 ) {
718 static_cast<int>(Hydrogen::get_instance()->getJackTimebaseState()) );
720 }
721}
722
724{
725 auto pHydrogen = Hydrogen::get_instance();
726 auto pHydrogenApp = HydrogenApp::get_instance();
727
728 if ( pHydrogen->getMode() == Song::Mode::Song ) {
729 // Song mode
730 m_pPatternModeLED->setActivated( false );
731 m_pSongModeLED->setActivated( true );
732 m_pSongModeBtn->setChecked( true );
733 m_pPatternModeBtn->setChecked( false );
734
735 m_pSongLoopBtn->setIsActive( true );
736
737 pHydrogenApp->showStatusBarMessage( tr("Song mode selected.") );
738 } else {
739 // Pattern mode
740 m_pPatternModeLED->setActivated( true );
741 m_pSongModeLED->setActivated( false );
742 m_pSongModeBtn->setChecked( false );
743 m_pPatternModeBtn->setChecked( true );
744
745 m_pSongLoopBtn->setIsActive( false );
746
747 pHydrogenApp->showStatusBarMessage( tr("Pattern mode selected.") );
748 }
749
752}
753
754void PlayerControl::activateSongMode( bool bActivate ) {
755 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
756 if ( bActivate ) {
757 pCoreActionController->activateSongMode( true );
758 m_pSongModeBtn->setChecked( true );
759 m_pPatternModeBtn->setChecked( false );
760 }
761 else {
762 pCoreActionController->activateSongMode( false );
763 m_pSongModeBtn->setChecked( false );
764 m_pPatternModeBtn->setChecked( true );
765 }
766}
767
768void PlayerControl::bpmChanged( double fNewBpmValue ) {
769 auto pAudioEngine = m_pHydrogen->getAudioEngine();
770 if ( m_pLCDBPMSpinbox->getIsActive() &&
772 // Store it's value in the .h2song file.
773 m_pHydrogen->getSong()->setBpm( static_cast<float>( fNewBpmValue ) );
774 // Use tempo in the next process cycle of the audio engine.
775 pAudioEngine->lock( RIGHT_HERE );
776 pAudioEngine->setNextBpm( static_cast<float>( fNewBpmValue ) );
777 pAudioEngine->unlock();
778 }
779}
780
781
782
783//beatcounter
785{
787 if ( bActivate ) {
788 pPref->m_bbc = Preferences::BC_ON;
789 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" BC Panel on") );
790 m_pControlsBCPanel->show();
791 m_pBCOnOffBtn->setChecked( true );
792 }
793 else {
794 pPref->m_bbc = Preferences::BC_OFF;
795 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" BC Panel off") );
796 m_pControlsBCPanel->hide();
797 m_pBCOnOffBtn->setChecked( false );
798 }
799}
800
802{
804 if ( m_pBCSetPlayBtn->text() == HydrogenApp::get_instance()->getCommonStrings()->getBeatCounterSetPlayButtonOff() ) {
806 m_pBCSetPlayBtn->setText( HydrogenApp::get_instance()->getCommonStrings()->getBeatCounterSetPlayButtonOn() );
807 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" Count BPM and start PLAY") );
808 }
809 else {
811 m_pBCSetPlayBtn->setText( HydrogenApp::get_instance()->getCommonStrings()->getBeatCounterSetPlayButtonOff() );
812 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" Count and set BPM") );
813 }
814}
815
817{
819 auto pHydrogen = H2Core::Hydrogen::get_instance();
820 if ( m_pRubberBPMChange->isChecked() ) {
821 // Recalculate all samples ones just to be safe since the
822 // recalculation is just triggered if there is a tempo change
823 // in the audio engine.
824 pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
825 pHydrogen->recalculateRubberband( pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
826 pHydrogen->getAudioEngine()->unlock();
827 pPref->setRubberBandBatchMode(true);
828 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Recalculate all samples using Rubberband ON") );
829 }
830 else {
831 pPref->setRubberBandBatchMode(false);
832 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Recalculate all samples using Rubberband OFF") );
833 }
834}
835
836
838{
839 int tmp = m_pHydrogen->getbeatsToCount();
840 char tmpb[3];
841
842 tmp ++;
843 if (tmp > 16) {
844 tmp = 2;
845 }
846
847 sprintf(tmpb, "%02d", tmp );
848 m_pBCDisplayB->setText( QString( tmpb ) );
849 m_pHydrogen->setbeatsToCount( tmp );
850}
851
853{
854 int tmp = m_pHydrogen->getbeatsToCount();
855 char tmpb[3];
856 tmp --;
857 if (tmp < 2 ) {
858 tmp = 16;
859 }
860 sprintf(tmpb, "%02d", tmp );
861 m_pBCDisplayB->setText( QString( tmpb ) );
862 m_pHydrogen->setbeatsToCount( tmp );
863}
864
866{
867 float tmp = m_pHydrogen->getNoteLength() * 4;
868
869 tmp = tmp / 2 ;
870 if (tmp < 1) {
871 tmp = 8;
872 }
873
874 m_pBCDisplayT->setText( QString::number( tmp ) );
875 m_pHydrogen->setNoteLength( (tmp) / 4 );
876}
877
879{
880 float tmp = m_pHydrogen->getNoteLength() * 4;
881
882 tmp = tmp * 2;
883 if (tmp > 8 ) {
884 tmp = 1;
885 }
886 m_pBCDisplayT->setText( QString::number(tmp) );
887 m_pHydrogen->setNoteLength( (tmp) / 4 );
888}
889// ~ beatcounter
890
891
892
894{
895 if ( !m_pHydrogen->hasJackAudioDriver() ) {
896 QMessageBox::warning( this, "Hydrogen", tr( "JACK-transport will work only with JACK driver." ) );
897 return;
898 }
899
900 auto pPref = Preferences::get_instance();
901 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
902
903 if ( pPref->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT ) {
904 pCoreActionController->activateJackTransport( false );
905 }
906 else {
907 pCoreActionController->activateJackTransport( true );
908 }
909}
910
911
913{
914#ifdef H2CORE_HAVE_JACK
915 if ( !m_pHydrogen->hasJackTransport() ) {
916 QMessageBox::warning( this, "Hydrogen", tr( "JACK transport will work only with JACK driver." ) );
917 return;
918 }
919
920 auto pPref = Preferences::get_instance();
921 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
922
923 if ( pPref->m_bJackTimebaseMode == Preferences::USE_JACK_TIMEBASE_CONTROL ) {
924 pCoreActionController->activateJackTimebaseControl( false );
925 }
926 else {
927 pCoreActionController->activateJackTimebaseControl( true );
928 }
929#endif
930}
931
933{
934 auto pHydrogen = Hydrogen::get_instance();
935 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() + 1 );
936}
937
938
939
941{
942 auto pHydrogen = Hydrogen::get_instance();
943 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() - 1 );
944}
945
947
948 auto pSong = Hydrogen::get_instance()->getSong();
949 if ( pSong == nullptr ) {
950 return;
951 }
952
953 if ( pSong->getLoopMode() == Song::LoopMode::Enabled ) {
954
955 m_pSongLoopBtn->setChecked( true );
956 HydrogenApp::get_instance()->showStatusBarMessage( tr("Loop song = On") );
957 }
958 else {
959 m_pSongLoopBtn->setChecked( false );
960 HydrogenApp::get_instance()->showStatusBarMessage( tr("Loop song = Off") );
961 }
962}
963
965{
966 Hydrogen* pHydrogen = Hydrogen::get_instance();
967 CoreActionController* pController = pHydrogen->getCoreActionController();
968
969 pController->setMetronomeIsActive( m_pMetronomeBtn->isChecked() );
970}
971
973{
975 bool isVisible = pH2App->getMixer()->isVisible();
976 pH2App->showMixer( !isVisible );
977}
978
980{
982 bool isVisible = pH2App->getInstrumentRack()->isVisible();
983 pH2App->showInstrumentPanel( isVisible );
984}
985
986
991
993 auto pHydrogen = Hydrogen::get_instance();
994
995 m_pLCDBPMSpinbox->setIsActive( pHydrogen->getTempoSource() ==
998}
999
1000void PlayerControl::showStatusBarMessage( const QString& sMessage, const QString& sCaller ) {
1001 m_pStatusLabel->showMessage( sMessage, sCaller );
1002}
1003
1005 auto pHydrogen = Hydrogen::get_instance();
1006 switch ( pHydrogen->getTempoSource() ) {
1009 break;
1012 break;
1013 default:
1015 }
1016}
1017
1019 auto pPref = Preferences::get_instance();
1020 auto pHydrogen = Hydrogen::get_instance();
1021
1022 if ( pHydrogen->getTempoSource() == H2Core::Hydrogen::Tempo::Song &&
1023 ! m_pBCOnOffBtn->getIsActive() ) {
1024 m_pBCOnOffBtn->setIsActive( true );
1025 if ( m_bLastBCOnOffBtnState ) {
1026 m_pBCOnOffBtn->setChecked( true );
1027 pPref->m_bbc = Preferences::BC_ON;
1028 m_pControlsBCPanel->show();
1029 }
1030
1031 } else if ( pHydrogen->getTempoSource() !=
1033 m_pBCOnOffBtn->getIsActive() ) {
1034 pPref->m_bbc = Preferences::BC_OFF;
1035 m_pControlsBCPanel->hide();
1037 m_pBCOnOffBtn->setChecked( false );
1038 m_pBCOnOffBtn->setIsActive( false );
1039 }
1040
1042}
1043
1045 auto pHydrogen = Hydrogen::get_instance();
1046 switch ( pHydrogen->getTempoSource() ) {
1049 break;
1052 break;
1053 default:
1054 m_pBCOnOffBtn->setToolTip( m_sBCOnOffBtnToolTip );
1055 }
1056}
1057
1059{
1060 // When updating the tempo of the BPM spin box it is crucial to
1061 // indicated that this was done due to a batch event and not due
1062 // to user input.
1064
1065 // Also update value if the BPM widget is disabled
1066 bool bIsReadOnly = m_pLCDBPMSpinbox->isReadOnly();
1067
1068 if ( ! bIsReadOnly ) {
1069 m_pLCDBPMSpinbox->setReadOnly( true );
1070 }
1071 /*
1072 * This is an external tempo change, triggered
1073 * via a midi or osc message.
1074 *
1075 * Just update the GUI using the current tempo
1076 * of the song.
1077 */
1078 m_pLCDBPMSpinbox->setValue( m_pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
1079
1080 if ( ! bIsReadOnly ) {
1081 m_pLCDBPMSpinbox->setReadOnly( false );
1082 }
1083
1084 // Re-enabling core Bpm alteration using BPM spinbox
1086
1087 if ( nValue == -1 ) {
1088 // Value was changed via API commands and not by the
1089 // AudioEngine.
1090 auto pHydrogen = H2Core::Hydrogen::get_instance();
1091 if ( pHydrogen->getTempoSource() == H2Core::Hydrogen::Tempo::Timeline ) {
1092 QMessageBox::warning( this, "Hydrogen", tr("A tempo change via MIDI, OSC, BeatCounter, or TapTempo was detected. It will only be used after deactivating the Timeline and left of the first Tempo Marker when activating it again.") );
1093 } else if ( pHydrogen->getTempoSource() ==
1095 QMessageBox::warning( this, "Hydrogen", tr("A tempo change via MIDI, OSC, BeatCounter, or TapTempo was detected. It will only take effect when deactivating JACK Timebase support or making Hydrogen take Timebase control.") );
1096 }
1097 }
1098}
1099
1101 if ( m_pHydrogen->hasJackAudioDriver() ) {
1102 m_pJackTransportBtn->show();
1103 m_pJackTimebaseBtn->show();
1104
1106 static_cast<int>(Hydrogen::get_instance()->getJackTimebaseState() ));
1108 }
1109 else {
1110 m_pJackTransportBtn->hide();
1111 m_pJackTimebaseBtn->hide();
1112 }
1113}
1114
1116{
1117 auto pPref = Preferences::get_instance();
1118
1119 if ( pPref->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT ) {
1120
1121 if ( ! m_pJackTransportBtn->isDown() ) {
1122 m_pJackTransportBtn->setChecked( true );
1123 }
1124
1125 HydrogenApp::get_instance()->showStatusBarMessage( tr("JACK transport mode = On") );
1126
1127 if ( pPref->m_bJackTimebaseEnabled ) {
1128 m_pJackTimebaseBtn->setIsActive( true );
1130 static_cast<int>(Hydrogen::get_instance()->getJackTimebaseState()) );
1131 }
1132 }
1133 else {
1134
1135 if ( ! m_pJackTransportBtn->isDown() ) {
1136 m_pJackTransportBtn->setChecked( false );
1137 }
1138 m_pJackTimebaseBtn->setChecked( false );
1139 m_pJackTimebaseBtn->setIsActive( false );
1140 HydrogenApp::get_instance()->showStatusBarMessage( tr("JACK transport mode = Off") );
1141 }
1142}
1143
1145{
1146 auto pPref = Preferences::get_instance();
1147 if ( ! pPref->m_bJackTimebaseEnabled ) {
1148 return;
1149 }
1150
1151 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1152
1153 QString sMessage = tr("JACK Timebase mode" ) + QString( " = " );
1154 const auto state = JackAudioDriver::TimebaseFromInt( nState );
1155
1156 switch( state ) {
1158
1159 if ( ! m_pJackTimebaseBtn->isDown() ) {
1160 m_pJackTimebaseBtn->setChecked( true );
1161 }
1162 m_pJackTimebaseBtn->setUseRedBackground( false );
1163 m_pJackTimebaseBtn->setToolTip( pCommonStrings->getJackTimebaseTooltip() );
1164
1165 sMessage.append( "Controller" );
1166 break;
1167
1169
1170 if ( ! m_pJackTimebaseBtn->isDown() ) {
1171 m_pJackTimebaseBtn->setChecked( true );
1172 }
1173 m_pJackTimebaseBtn->setUseRedBackground( true );
1174 m_pJackTimebaseBtn->setToolTip( pCommonStrings->getJackTimebaseListenerTooltip() );
1175
1176 sMessage.append( "Listener" );
1177 break;
1178
1179 default:
1180
1181 if ( ! m_pJackTimebaseBtn->isDown() ) {
1182 m_pJackTimebaseBtn->setChecked( false );
1183 }
1184 m_pJackTimebaseBtn->setUseRedBackground( false );
1185 m_pJackTimebaseBtn->setToolTip( pCommonStrings->getJackTimebaseTooltip() );
1186
1187 sMessage.append( pCommonStrings->getStatusOff() );
1188 }
1189
1193}
1194
1196{
1198 auto pPref = Preferences::get_instance();
1199 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1200 auto pHydrogen = Hydrogen::get_instance();
1201
1202 if ( pPref->m_bJackTimebaseEnabled ) {
1203 if ( pHydrogen->hasJackTransport() ) {
1204 m_pJackTimebaseBtn->setIsActive( true );
1206 static_cast<int>(pHydrogen->getJackTimebaseState()) );
1207 }
1208 else {
1209 m_pJackTimebaseBtn->setToolTip( pCommonStrings->getJackTimebaseTooltip() );
1210 }
1211 }
1212 else {
1213 m_pJackTimebaseBtn->setChecked( false );
1214 m_pJackTimebaseBtn->setIsActive( false );
1215 m_pJackTimebaseBtn->setBaseToolTip( pCommonStrings->getJackTimebaseDisabledTooltip() );
1216 }
1217 }
1218}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:61
int bcDisplaystatus
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
Custom QLabel that emits a signal when clicked.
Shows the current CPU load using a meter similar to the one used in Fader.
@ Playing
Transport is rolling.
Hydrogen Audio Engine.
Definition Hydrogen.h:54
@ Timeline
Only tempo markers on the Timeline are considered.
Definition Hydrogen.h:66
@ Jack
Hydrogen will disregard all internal tempo settings and uses the ones provided by the JACK server ins...
Definition Hydrogen.h:72
@ Song
BeatCounter, TapTempo, OSC and MIDI commands as well as the BPM widget in the PlayerControl are used ...
Definition Hydrogen.h:64
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:123
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:653
@ Listener
An external program is Timebase controller and Hydrogen will disregard all tempo markers on the Timel...
@ Controller
Hydrogen itself is Timebase controller and provides its current tempo to other Timebase listeners.
static Timebase TimebaseFromInt(int nState)
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 setRubberBandBatchMode(int val)
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ AudioTab
Any option in the Audio tab appeared.
bool m_bUseMetronome
If set to true, samples of the metronome will be added to H2Core::AudioEngine::m_songNoteQueue and th...
@ USE_JACK_TRANSPORT
Specifies whether or not to use JACK transport capabilities.
Definition Preferences.h:90
@ USE_JACK_TIMEBASE_CONTROL
Specifies that Hydrogen should attempt to acquire JACK Timebase control.
void setRecordEvents(bool value)
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
InstrumentRack * getInstrumentRack()
void showStatusBarMessage(const QString &sMessage, const QString &sCaller="")
void showMixer(bool bShow)
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
void showInstrumentPanel(bool)
Mixer * getMixer()
Non-interactive display used for both numerical values and the status display.
Definition LCDDisplay.h:40
Custom spin box.
Definition LCDSpinBox.h:50
LED identicating a user selection.
Definition LED.h:43
Custom LED that comes with its own timer.
Definition LED.h:72
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
void updateBeatCounterToolTip()
Button * m_pBCBDownBtn
Button * m_pRecBtn
void midiActivityEvent() override
void bcbDownButtonClicked()
LCDDisplay * m_pTimeDisplay
void showInstrumentRackButtonClicked()
virtual void timelineActivationEvent() override
Button * m_pBCTUpBtn
PixmapWidget * m_pControlsBCPanel
Button * m_pJackTimebaseBtn
virtual void driverChangedEvent() override
Button * m_pMetronomeBtn
void updateBPMSpinbox()
Store the tool tip of the beat counter since it gets overwritten during deactivation.
void activateBeatCounter(bool bActivate)
ClickableLabel * m_pTimeMinutesLbl
MetronomeLED * m_pMetronomeLED
Button * m_pSongLoopBtn
void bcbUpButtonClicked()
Button * m_pBCOnOffBtn
void updatePlayerControl()
void recBtnClicked()
Toggle record mode.
void bctDownButtonClicked()
Button * m_pRubberBPMChange
void metronomeButtonClicked()
ClickableLabel * m_pBPMLbl
LED * m_pPatternModeLED
Button * m_pShowInstrumentRackBtn
void playBtnClicked()
Start audio engine.
QLabel * m_pBCDisplayB
void bpmChanged(double)
void onPreferencesChanged(H2Core::Preferences::Changes changes)
ClickableLabel * m_pMidiInLbl
QTimer * m_pMidiActivityTimer
Used to turn off the LED m_pMidiActivityLED indicating an incoming MIDI event after m_midiActivityTim...
virtual void updateSongEvent(int nValue) override
virtual void songModeActivationEvent() override
Shared GUI update when activating Song or Pattern mode via button click or via OSC command.
void rubberbandButtonToggle()
QString m_sBCOnOffBtnToolTip
StatusMessageDisplay * m_pStatusLabel
Button * m_pPlayBtn
void jackTimebaseBtnClicked()
Button * m_pBCSetPlayBtn
virtual void jackTransportActivationEvent() override
ClickableLabel * m_pTimeHoursLbl
Button * m_pStopBtn
PlayerControl(QWidget *parent)
void jackTransportBtnClicked()
void showMixerButtonClicked()
QLabel * m_pBCDisplayT
void bcSetPlayBtnClicked()
virtual void tempoChangedEvent(int nValue) override
ClickableLabel * m_pCpuLbl
std::chrono::milliseconds m_midiActivityTimeout
ClickableLabel * m_pTimeSecondsLbl
QLabel * m_pBCDisplayZ
void fastForwardBtnClicked()
virtual void loopModeActivationEvent() override
void updateBPMSpinboxToolTip()
LED * m_pMidiActivityLED
CpuLoadWidget * m_pCpuLoadWidget
Button * m_pJackTransportBtn
Button * m_pBCBUpBtn
Button * m_pShowMixerBtn
void bctUpButtonClicked()
QString m_sBCOnOffBtnTimelineToolTip
bool m_bLastBCOnOffBtnState
void activateSongMode(bool bActivate)
static constexpr int m_nMinimumHeight
QString m_sBCOnOffBtnJackTimebaseToolTip
Button * m_pBCTDownBtn
void showStatusBarMessage(const QString &msg, const QString &sCaller="")
Button * m_pRwdBtn
ClickableLabel * m_pTimeMilliSecondsLbl
QString m_sLCDBPMSpinboxToolTip
Button * m_pSongModeBtn
QString m_sLCDBPMSpinboxJackTimebaseToolTip
Button * m_pPatternModeBtn
void deactivateMidiActivityLED()
virtual void jackTimebaseStateChangedEvent(int nState) override
void stopBtnClicked()
Stop audio engine.
bool m_bLCDBPMSpinboxIsArmed
When updating the tempo of the BPM spin box it is crucial to indicated that this was done due to a ba...
LCDSpinBox * m_pLCDBPMSpinbox
H2Core::Hydrogen * m_pHydrogen
QString m_sLCDBPMSpinboxTimelineToolTip
Button * m_pFfwdBtn
static QString getImagePath()
Definition Skin.h:36
Non-interactive display for status messages in the PlayerControl.
#define MAX_BPM
Definition Globals.h:36
#define MIN_BPM
Definition Globals.h:35