hydrogen 1.2.3
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-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
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)
60 , m_midiActivityTimeout( 125 )
61 , m_bLCDBPMSpinboxIsArmed( true )
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->setMargin( 0 );
80 setLayout( hbox );
81
82// CONTROLS
83 PixmapWidget *pControlsPanel = new PixmapWidget( nullptr );
84 pControlsPanel->setFixedSize( 344, 43 );
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 );
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 );
205 } else {
206 m_pSongModeBtn->setChecked( false );
207 m_pPatternModeBtn->setChecked( 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 master 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 }
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 master 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
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( 113, 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
411 //jack time master
412 /*: Using the JACK Timebase Master functionality one of the
413 connected programs can broadcast both speed and measure information to
414 all other connected applications in order to have a more fine-grained
415 transport control.*/
416 m_pJackMasterBtn = new Button( pJackPanel, QSize( 53, 16 ),
418 pCommonStrings->getJackMasterButton(), false,
419 QSize(), pCommonStrings->getJackTBMMasterTooltip(),
420 false, true );
421 m_pJackMasterBtn->setObjectName( "PlayerControlJackMasterButton" );
422 if ( ! m_pHydrogen->hasJackAudioDriver() ) {
423 m_pJackMasterBtn->hide();
424 }
425
426 if ( pPref->m_bJackTimebaseEnabled ) {
427 if ( m_pHydrogen->hasJackTransport() ) {
429 JackAudioDriver::Timebase::Master ) {
430 m_pJackMasterBtn->setChecked( true );
431 }
432 else if ( m_pHydrogen->getJackTimebaseState() ==
433 JackAudioDriver::Timebase::Slave ) {
434 m_pJackMasterBtn->setChecked( true );
436 m_pJackMasterBtn->setToolTip( pCommonStrings->getJackTBMSlaveTooltip() );
437 }
438 else {
439 m_pJackMasterBtn->setChecked( false );
440 }
441 }
442 else {
444 }
445 }
446 else {
448 m_pJackMasterBtn->setBaseToolTip( pCommonStrings->getJackMasterDisabledTooltip() );
449 }
450
451 connect(m_pJackMasterBtn, SIGNAL( clicked() ), this, SLOT( jackMasterBtnClicked() ));
452 m_pJackMasterBtn->move( 56, 24 );
453 // ~ jack time master
454
455 // CPU load widget
456 m_pCpuLoadWidget = new CpuLoadWidget( pJackPanel );
457 m_pCpuLoadWidget->setObjectName( "CpuLoadWidget" );
458
459 // Midi Activity widget
460 m_pMidiActivityLED = new LED( pJackPanel, QSize( 11, 9 ) );
461 m_pMidiActivityLED->setObjectName( "MidiActivityLED" );
462 m_pMidiActivityTimer = new QTimer( this );
463 connect( m_pMidiActivityTimer, SIGNAL( timeout() ),
464 this, SLOT( deactivateMidiActivityLED() ) );
465 m_pMidiInLbl = new ClickableLabel( pJackPanel, QSize( 45, 9 ),
466 pCommonStrings->getMidiInLabel() );
467 m_pMidiInLbl->move( 22, 14 );
468 m_pCpuLbl = new ClickableLabel( pJackPanel, QSize( 30, 9 ),
469 pCommonStrings->getCpuLabel() );
470 m_pCpuLbl->move( 71, 14 );
471
472 m_pMidiActivityLED->move( 11, 14 );
473 m_pCpuLoadWidget->move( 10, 3 );
474// ~ JACK
475
476
477 QWidget *pLcdBackGround = new QWidget( nullptr );
478 pLcdBackGround->setFixedSize( 256, 43 );
479 pLcdBackGround->setObjectName( "LcdBackground" );
480 hbox->addWidget( pLcdBackGround );
481
482 m_pShowMixerBtn = new Button( pLcdBackGround, QSize( 88, 23 ), Button::Type::Toggle,
483 "", pCommonStrings->getMixerButton(), false, QSize(),
484 tr( "Show mixer" ) );
485 m_pShowMixerBtn->move( 0, 0 );
486 connect(m_pShowMixerBtn, SIGNAL( clicked() ), this, SLOT( showMixerButtonClicked() ));
487
488 m_pShowInstrumentRackBtn = new Button( pLcdBackGround, QSize( 168, 23 ), Button::Type::Toggle,
489 "", pCommonStrings->getInstrumentRackButton(), false, QSize(),
490 tr( "Show Instrument Rack" ) );
491 m_pShowInstrumentRackBtn->move( 88, 0 );
492 connect( m_pShowInstrumentRackBtn, SIGNAL( clicked() ),
493 this, SLOT( showInstrumentRackButtonClicked() ) );
494
495 m_pStatusLabel = new StatusMessageDisplay( pLcdBackGround, QSize( 255, 18 ) );
496 m_pStatusLabel->move( 0, 24 );
497
498 hbox->addStretch( 1000 ); // this must be the last widget in the HBOX!!
499
500 QTimer *timer = new QTimer( this );
501 connect(timer, SIGNAL(timeout()), this, SLOT(updatePlayerControl()));
502 timer->start(100); // update player control at 10 fps
503
506}
507
508
509
510
513
514
515
516
517
519{
522
523 if ( ! m_pShowMixerBtn->isDown() ) {
524 m_pShowMixerBtn->setChecked( pH2App->getMixer()->isVisible() );
525 }
526 if ( ! m_pShowInstrumentRackBtn->isDown() ) {
527 m_pShowInstrumentRackBtn->setChecked( pH2App->getInstrumentRack()->isVisible() );
528 }
529
530 auto state = m_pHydrogen->getAudioEngine()->getState();
531 if ( ! m_pPlayBtn->isDown() && ! m_pStopBtn->isDown() &&
532 ! m_pFfwdBtn->isDown() && ! m_pRwdBtn->isDown() ) {
534 m_pPlayBtn->setChecked(true);
535 } else {
536 m_pPlayBtn->setChecked(false);
537 }
538 }
539
540 if ( ! m_pRecBtn->isDown() ) {
541 if (pPref->getRecordEvents()) {
542 m_pRecBtn->setChecked(true);
543 } else {
544 m_pRecBtn->setChecked(false);
545 }
546 }
547
548 std::shared_ptr<Song> song = m_pHydrogen->getSong();
549
550 if ( ! m_pLCDBPMSpinbox->hasFocus() &&
555 }
556
557 //beatcounter
558 if ( pPref->m_bbc == Preferences::BC_OFF ) {
559 m_pControlsBCPanel->hide();
560 if ( ! m_pBCOnOffBtn->isDown() ) {
561 m_pBCOnOffBtn->setChecked(false);
562 }
563 } else {
564 m_pControlsBCPanel->show();
565 if ( ! m_pBCOnOffBtn->isDown() ) {
566 m_pBCOnOffBtn->setChecked(true);
567 }
568 }
569
570 if ( ! m_pBCSetPlayBtn->isDown() ) {
572 m_pBCSetPlayBtn->setChecked(false);
573 } else {
574 m_pBCSetPlayBtn->setChecked(true);
575 }
576 }
577 // ~ beatcounter
578
579 // time
580 float fSeconds = m_pHydrogen->getAudioEngine()->getElapsedTime();
581
582 int nMSec = (int)( (fSeconds - (int)fSeconds) * 1000.0 );
583 int nSeconds = ( (int)fSeconds ) % 60;
584 int nMins = (int)( fSeconds / 60.0 ) % 60;
585 int nHours = (int)( fSeconds / 3600.0 );
586
587 QString sTime = QString( "%1:%2:%3.%4" )
588 .arg( nHours, 2, 10, QLatin1Char( '0' ) )
589 .arg( nMins, 2, 10, QLatin1Char( '0' ) )
590 .arg( nSeconds, 2, 10, QLatin1Char( '0' ) )
591 .arg( nMSec, 3, 10, QLatin1Char( '0' ) );
592
593 if ( m_pTimeDisplay->text() != sTime ) {
594 m_pTimeDisplay->setText( sTime );
595 }
596
597 if ( ! m_pMetronomeBtn->isDown() ) {
598 m_pMetronomeBtn->setChecked(pPref->m_bUseMetronome);
599 }
600
601
602 //beatcounter get BC message
603 char bcstatus[4];
604 int beatstocountondisplay = 1;
605 beatstocountondisplay = m_pHydrogen->getBcStatus();
606
607 switch (beatstocountondisplay){
608 case 1 :
609 if (bcDisplaystatus == 1){
611 bcDisplaystatus = 0;
612 }
613 sprintf(bcstatus, "R");
614 if ( m_pBCDisplayZ->text() != bcstatus ) {
615 m_pBCDisplayZ->setText( QString (bcstatus) );
616 }
617
618 break;
619 default:
622 bcDisplaystatus = 1;
623 }
624 sprintf(bcstatus, "%02d ", beatstocountondisplay -1);
625 if ( m_pBCDisplayZ->text() != bcstatus ) {
626 m_pBCDisplayZ->setText( QString (bcstatus) );
627 }
628
629 }
630
631 // Rubberband
632 if ( m_pRubberBPMChange->isChecked() != pPref->getRubberBandBatchMode() ) {
633 m_pRubberBPMChange->setChecked( pPref->getRubberBandBatchMode());
634 }
635}
636
637
638
642 if ( m_pRecBtn->isChecked() ) {
644 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Record midi events = On" ) );
645 }
646 else {
648 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Record midi events = Off" ) );
649 }
650 }
651}
652
655 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
656
657 // Hint that something is wrong in case there is no proper audio
658 // driver set.
659 if ( m_pHydrogen->getAudioOutput() == nullptr ||
660 dynamic_cast<NullDriver*>(m_pHydrogen->getAudioOutput()) != nullptr ) {
661 QMessageBox::warning( this, "Hydrogen",
662 QString( "%1\n%2" )
663 .arg( pCommonStrings->getAudioDriverNotPresent() )
664 .arg( pCommonStrings->getAudioDriverErrorHint() ) );
665 return;
666 }
667
668 if ( m_pPlayBtn->isChecked() ) {
670 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Playing.") );
671 }
672 else {
675 }
676}
677
680{
681 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
682
683 // Hint that something is wrong in case there is no proper audio
684 // driver set.
685 if ( m_pHydrogen->getAudioOutput() == nullptr ||
686 dynamic_cast<NullDriver*>(m_pHydrogen->getAudioOutput()) != nullptr ) {
687 QMessageBox::warning( this, "Hydrogen",
688 QString( "%1\n%2" )
689 .arg( pCommonStrings->getAudioDriverNotPresent() )
690 .arg( pCommonStrings->getAudioDriverErrorHint() ) );
691 return;
692 }
693
694 if ( ! m_pPlayBtn->isDown() ) {
695 m_pPlayBtn->setChecked(false);
696 }
699 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Stopped.") );
700}
701
703 m_pMidiActivityTimer->stop();
705 m_pMidiActivityTimer->start( std::chrono::duration_cast<std::chrono::milliseconds>( m_midiActivityTimeout )
706 .count() );
707}
708
713
715 // A new song got loaded
716 if ( nValue == 0 ) {
723 }
724}
725
727{
728 auto pHydrogen = Hydrogen::get_instance();
729 auto pHydrogenApp = HydrogenApp::get_instance();
730
731 if ( pHydrogen->getMode() == Song::Mode::Song ) {
732 // Song mode
735 m_pSongModeBtn->setChecked( true );
736 m_pPatternModeBtn->setChecked( false );
737
739
740 pHydrogenApp->showStatusBarMessage( tr("Song mode selected.") );
741 } else {
742 // Pattern mode
745 m_pSongModeBtn->setChecked( false );
746 m_pPatternModeBtn->setChecked( true );
747
748 m_pSongLoopBtn->setIsActive( false );
749
750 pHydrogenApp->showStatusBarMessage( tr("Pattern mode selected.") );
751 }
752
755}
756
757void PlayerControl::activateSongMode( bool bActivate ) {
758 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
759 if ( bActivate ) {
760 pCoreActionController->activateSongMode( true );
761 m_pSongModeBtn->setChecked( true );
762 m_pPatternModeBtn->setChecked( false );
763 }
764 else {
765 pCoreActionController->activateSongMode( false );
766 m_pSongModeBtn->setChecked( false );
767 m_pPatternModeBtn->setChecked( true );
768 }
769}
770
771void PlayerControl::bpmChanged( double fNewBpmValue ) {
772 auto pAudioEngine = m_pHydrogen->getAudioEngine();
775 // Store it's value in the .h2song file.
776 m_pHydrogen->getSong()->setBpm( static_cast<float>( fNewBpmValue ) );
777 // Use tempo in the next process cycle of the audio engine.
778 pAudioEngine->lock( RIGHT_HERE );
779 pAudioEngine->setNextBpm( static_cast<float>( fNewBpmValue ) );
780 pAudioEngine->unlock();
781 }
782}
783
784
785
786//beatcounter
788{
790 if ( bActivate ) {
791 pPref->m_bbc = Preferences::BC_ON;
792 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" BC Panel on") );
793 m_pControlsBCPanel->show();
794 m_pBCOnOffBtn->setChecked( true );
795 }
796 else {
797 pPref->m_bbc = Preferences::BC_OFF;
798 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" BC Panel off") );
799 m_pControlsBCPanel->hide();
800 m_pBCOnOffBtn->setChecked( false );
801 }
802}
803
805{
809 m_pBCSetPlayBtn->setText( HydrogenApp::get_instance()->getCommonStrings()->getBeatCounterSetPlayButtonOn() );
810 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" Count BPM and start PLAY") );
811 }
812 else {
815 (HydrogenApp::get_instance())->showStatusBarMessage( tr(" Count and set BPM") );
816 }
817}
818
820{
822 auto pHydrogen = H2Core::Hydrogen::get_instance();
823 if ( m_pRubberBPMChange->isChecked() ) {
824 // Recalculate all samples ones just to be safe since the
825 // recalculation is just triggered if there is a tempo change
826 // in the audio engine.
827 pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
828 pHydrogen->recalculateRubberband( pHydrogen->getAudioEngine()->getTransportPosition()->getBpm() );
829 pHydrogen->getAudioEngine()->unlock();
830 pPref->setRubberBandBatchMode(true);
831 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Recalculate all samples using Rubberband ON") );
832 }
833 else {
834 pPref->setRubberBandBatchMode(false);
835 (HydrogenApp::get_instance())->showStatusBarMessage( tr("Recalculate all samples using Rubberband OFF") );
836 }
837}
838
839
841{
842 int tmp = m_pHydrogen->getbeatsToCount();
843 char tmpb[3];
844
845 tmp ++;
846 if (tmp > 16) {
847 tmp = 2;
848 }
849
850 sprintf(tmpb, "%02d", tmp );
851 m_pBCDisplayB->setText( QString( tmpb ) );
853}
854
856{
857 int tmp = m_pHydrogen->getbeatsToCount();
858 char tmpb[3];
859 tmp --;
860 if (tmp < 2 ) {
861 tmp = 16;
862 }
863 sprintf(tmpb, "%02d", tmp );
864 m_pBCDisplayB->setText( QString( tmpb ) );
866}
867
869{
870 float tmp = m_pHydrogen->getNoteLength() * 4;
871
872 tmp = tmp / 2 ;
873 if (tmp < 1) {
874 tmp = 8;
875 }
876
877 m_pBCDisplayT->setText( QString::number( tmp ) );
878 m_pHydrogen->setNoteLength( (tmp) / 4 );
879}
880
882{
883 float tmp = m_pHydrogen->getNoteLength() * 4;
884
885 tmp = tmp * 2;
886 if (tmp > 8 ) {
887 tmp = 1;
888 }
889 m_pBCDisplayT->setText( QString::number(tmp) );
890 m_pHydrogen->setNoteLength( (tmp) / 4 );
891}
892// ~ beatcounter
893
894
895
897{
899 QMessageBox::warning( this, "Hydrogen", tr( "JACK-transport will work only with JACK driver." ) );
900 return;
901 }
902
903 auto pPref = Preferences::get_instance();
904 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
905
906 if ( pPref->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT ) {
907 pCoreActionController->activateJackTransport( false );
908 }
909 else {
910 pCoreActionController->activateJackTransport( true );
911 }
912}
913
914
915//jack time master
917{
918#ifdef H2CORE_HAVE_JACK
919 if ( !m_pHydrogen->hasJackTransport() ) {
920 QMessageBox::warning( this, "Hydrogen", tr( "JACK transport will work only with JACK driver." ) );
921 return;
922 }
923
924 auto pPref = Preferences::get_instance();
925 auto pCoreActionController = Hydrogen::get_instance()->getCoreActionController();
926
927 if ( pPref->m_bJackMasterMode == Preferences::USE_JACK_TIME_MASTER ) {
928 pCoreActionController->activateJackTimebaseMaster( false );
929 }
930 else {
931 pCoreActionController->activateJackTimebaseMaster( true );
932 }
933#endif
934}
935// ~ jack time master
936
938{
939 auto pHydrogen = Hydrogen::get_instance();
940 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() + 1 );
941}
942
943
944
946{
947 auto pHydrogen = Hydrogen::get_instance();
948 pHydrogen->getCoreActionController()->locateToColumn( pHydrogen->getAudioEngine()->getTransportPosition()->getColumn() - 1 );
949}
950
952
953 auto pSong = Hydrogen::get_instance()->getSong();
954 if ( pSong == nullptr ) {
955 return;
956 }
957
958 if ( pSong->getLoopMode() == Song::LoopMode::Enabled ) {
959
960 m_pSongLoopBtn->setChecked( true );
961 HydrogenApp::get_instance()->showStatusBarMessage( tr("Loop song = On") );
962 }
963 else {
964 m_pSongLoopBtn->setChecked( false );
965 HydrogenApp::get_instance()->showStatusBarMessage( tr("Loop song = Off") );
966 }
967}
968
970{
971 Hydrogen* pHydrogen = Hydrogen::get_instance();
972 CoreActionController* pController = pHydrogen->getCoreActionController();
973
974 pController->setMetronomeIsActive( m_pMetronomeBtn->isChecked() );
975}
976
978{
980 bool isVisible = pH2App->getMixer()->isVisible();
981 pH2App->showMixer( !isVisible );
982}
983
985{
987 bool isVisible = pH2App->getInstrumentRack()->isVisible();
988 pH2App->showInstrumentPanel( isVisible );
989}
990
991
996
998 auto pHydrogen = Hydrogen::get_instance();
999
1000 m_pLCDBPMSpinbox->setIsActive( pHydrogen->getTempoSource() ==
1003}
1004
1005void PlayerControl::showStatusBarMessage( const QString& sMessage, const QString& sCaller ) {
1006 m_pStatusLabel->showMessage( sMessage, sCaller );
1007}
1008
1010 auto pHydrogen = Hydrogen::get_instance();
1011 switch ( pHydrogen->getTempoSource() ) {
1014 break;
1017 break;
1018 default:
1020 }
1021}
1022
1024 auto pPref = Preferences::get_instance();
1025 auto pHydrogen = Hydrogen::get_instance();
1026
1027 if ( pHydrogen->getTempoSource() == H2Core::Hydrogen::Tempo::Song &&
1028 ! m_pBCOnOffBtn->getIsActive() ) {
1029 m_pBCOnOffBtn->setIsActive( true );
1030 if ( m_bLastBCOnOffBtnState ) {
1031 m_pBCOnOffBtn->setChecked( true );
1032 pPref->m_bbc = Preferences::BC_ON;
1033 m_pControlsBCPanel->show();
1034 }
1035
1036 } else if ( pHydrogen->getTempoSource() !=
1039 pPref->m_bbc = Preferences::BC_OFF;
1040 m_pControlsBCPanel->hide();
1042 m_pBCOnOffBtn->setChecked( false );
1043 m_pBCOnOffBtn->setIsActive( false );
1044 }
1045
1047}
1048
1050 auto pHydrogen = Hydrogen::get_instance();
1051 switch ( pHydrogen->getTempoSource() ) {
1054 break;
1057 break;
1058 default:
1059 m_pBCOnOffBtn->setToolTip( m_sBCOnOffBtnToolTip );
1060 }
1061}
1062
1064{
1065 // When updating the tempo of the BPM spin box it is crucial to
1066 // indicated that this was done due to a batch event and not due
1067 // to user input.
1069
1070 // Also update value if the BPM widget is disabled
1071 bool bIsReadOnly = m_pLCDBPMSpinbox->isReadOnly();
1072
1073 if ( ! bIsReadOnly ) {
1074 m_pLCDBPMSpinbox->setReadOnly( true );
1075 }
1076 /*
1077 * This is an external tempo change, triggered
1078 * via a midi or osc message.
1079 *
1080 * Just update the GUI using the current tempo
1081 * of the song.
1082 */
1084
1085 if ( ! bIsReadOnly ) {
1086 m_pLCDBPMSpinbox->setReadOnly( false );
1087 }
1088
1089 // Re-enabling core Bpm alteration using BPM spinbox
1091
1092 if ( nValue == -1 ) {
1093 // Value was changed via API commands and not by the
1094 // AudioEngine.
1095 auto pHydrogen = H2Core::Hydrogen::get_instance();
1096 if ( pHydrogen->getTempoSource() == H2Core::Hydrogen::Tempo::Timeline ) {
1097 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.") );
1098 } else if ( pHydrogen->getTempoSource() ==
1100 QMessageBox::warning( this, "Hydrogen", tr("A tempo change via MIDI, OSC, BeatCounter, or TapTempo was detected. It will only take effect when deactivating JACK BBT transport or making Hydrogen the Timebase master.") );
1101 }
1102 }
1103}
1104
1107 m_pJackTransportBtn->show();
1108 m_pJackMasterBtn->show();
1109
1112 }
1113 else {
1114 m_pJackTransportBtn->hide();
1115 m_pJackMasterBtn->hide();
1116 }
1117}
1118
1120{
1121 auto pPref = Preferences::get_instance();
1122
1123 if ( pPref->m_bJackTransportMode == Preferences::USE_JACK_TRANSPORT ) {
1124
1125 if ( ! m_pJackTransportBtn->isDown() ) {
1126 m_pJackTransportBtn->setChecked( true );
1127 }
1128
1129 HydrogenApp::get_instance()->showStatusBarMessage( tr("JACK transport mode = On") );
1130
1131 if ( pPref->m_bJackTimebaseEnabled ) {
1134 }
1135 }
1136 else {
1137
1138 if ( ! m_pJackTransportBtn->isDown() ) {
1139 m_pJackTransportBtn->setChecked( false );
1140 }
1141 m_pJackMasterBtn->setChecked( false );
1142 m_pJackMasterBtn->setIsActive( false );
1143 HydrogenApp::get_instance()->showStatusBarMessage( tr("JACK transport mode = Off") );
1144 }
1145}
1146
1148{
1149 auto pPref = Preferences::get_instance();
1150 if ( ! pPref->m_bJackTimebaseEnabled ) {
1151 return;
1152 }
1153
1154 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1155 auto pHydrogen = Hydrogen::get_instance();
1156
1157 QString sMessage = tr("JACK Timebase mode" ) + QString( " = " );
1158
1159 switch( pHydrogen->getJackTimebaseState() ) {
1160 case JackAudioDriver::Timebase::Master:
1161
1162 if ( ! m_pJackMasterBtn->isDown() ) {
1163 m_pJackMasterBtn->setChecked( true );
1164 }
1166 m_pJackMasterBtn->setToolTip( pCommonStrings->getJackTBMMasterTooltip() );
1167
1168 sMessage.append( "master" );
1169 break;
1170
1171 case JackAudioDriver::Timebase::Slave:
1172
1173 if ( ! m_pJackMasterBtn->isDown() ) {
1174 m_pJackMasterBtn->setChecked( true );
1175 }
1177 m_pJackMasterBtn->setToolTip( pCommonStrings->getJackTBMSlaveTooltip() );
1178
1179 sMessage.append( "slave" );
1180 break;
1181
1182 default:
1183
1184 if ( ! m_pJackMasterBtn->isDown() ) {
1185 m_pJackMasterBtn->setChecked( false );
1186 }
1188 m_pJackMasterBtn->setToolTip( pCommonStrings->getJackTBMMasterTooltip() );
1189
1190 sMessage.append( pCommonStrings->getStatusOff() );
1191 }
1192
1196}
1197
1199{
1201 auto pPref = Preferences::get_instance();
1202 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1203
1204 if ( pPref->m_bJackTimebaseEnabled ) {
1205 if ( Hydrogen::get_instance()->hasJackTransport() ) {
1208 }
1209 else {
1210 m_pJackMasterBtn->setToolTip( pCommonStrings->getJackTBMMasterTooltip() );
1211 }
1212 }
1213 else {
1214 m_pJackMasterBtn->setChecked( false );
1215 m_pJackMasterBtn->setIsActive( false );
1216 m_pJackMasterBtn->setBaseToolTip( pCommonStrings->getJackMasterDisabledTooltip() );
1217 }
1218 }
1219}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:59
int bcDisplaystatus
Generic Button with SVG icons or text.
Definition Button.h:60
@ Push
Button is not set checkable.
@ Toggle
Button is set checkable.
void setUseRedBackground(bool bUseRedBackground)
Definition Button.cpp:122
void setBaseToolTip(const QString &sNewTip)
Definition Button.cpp:306
bool getIsActive() const
Definition Button.h:178
void setIsActive(bool bIsActive)
Definition Button.cpp:99
Custom QLabel that emits a signal when clicked.
const QString & getBeatCounterSetPlayButtonOff() const
Shows the current CPU load using a meter similar to the one used in Fader.
@ Playing
Transport is rolling.
float getElapsedTime() const
State getState() const
const std::shared_ptr< TransportPosition > getTransportPosition() const
bool locateToColumn(int nPatternGroup)
Relocates transport to the beginning of a particular column/Pattern group.
bool activateSongMode(bool bActivate)
Switches between Song and Pattern mode of playback.
bool activateJackTransport(bool bActivate)
(De)activates the usage of Jack transport.
bool activateJackTimebaseMaster(bool bActivate)
(De)activates the usage of Jack timebase master.
Hydrogen Audio Engine.
Definition Hydrogen.h:54
JackAudioDriver::Timebase getJackTimebaseState() const
@ Timeline
Only tempo markers on the Timeline are considered.
@ Jack
Hydrogen will disregard all internal tempo settings and uses the ones provided by the JACK server ins...
@ Song
BeatCounter, TapTempo, OSC and MIDI commands as well as the BPM widget in the PlayerControl are used ...
bool hasJackAudioDriver() const
void sequencer_stop()
Stop the internal sequencer.
Definition Hydrogen.cpp:226
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
void setbeatsToCount(int beatstocount)
Updates m_nbeatsToCount.
Definition Hydrogen.cpp:958
Tempo getTempoSource() const
Song::Mode getMode() const
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
void setNoteLength(float notelength)
Definition Hydrogen.cpp:968
AudioOutput * getAudioOutput() const
Used to display audio driver info.
Definition Hydrogen.cpp:719
bool hasJackTransport() const
float getNoteLength()
Definition Hydrogen.cpp:973
CoreActionController * getCoreActionController() const
Definition Hydrogen.h:639
void sequencer_play()
Start the internal sequencer.
Definition Hydrogen.cpp:218
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 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_TIME_MASTER
Specifies that Hydrogen is using in the time master mode and will thus control specific aspects of th...
Definition Preferences.h:96
@ USE_JACK_TRANSPORT
Specifies whether or not to use JACK transport capabilities.
Definition Preferences.h:89
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
bool getIsHovered() const
Definition LCDSpinBox.h:141
void setValue(double fValue)
bool getIsActive() const
Definition LCDSpinBox.h:138
void setIsActive(bool bIsActive)
LED identicating a user selection.
Definition LED.h:43
void setActivated(bool bActivated)
Definition LED.cpp:63
Custom LED that comes with its own timer.
Definition LED.h:72
void setAction(std::shared_ptr< Action > pAction)
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
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
void jackMasterBtnClicked()
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
Button * m_pBCSetPlayBtn
virtual void jackTransportActivationEvent() override
Button * m_pJackMasterBtn
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)
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()
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...
virtual void jackTimebaseStateChangedEvent() override
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.
void showMessage(const QString &sMessage, const QString &sCaller="")
#define MAX_BPM
Definition Globals.h:36
#define MIN_BPM
Definition Globals.h:35