hydrogen 1.2.3
SongEditorPanel.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22#include "SongEditorPanel.h"
24
26#include "../HydrogenApp.h"
29#include "../Skin.h"
31#include "../Widgets/Button.h"
32#include "../Widgets/Fader.h"
33#include "../Widgets/LCDCombo.h"
35#include "../WidgetScrollArea.h"
36
37#include "SongEditor.h"
38#include "UndoActions.h"
39#include "CommonStrings.h"
40
41#include <core/Hydrogen.h>
48#include <core/EventQueue.h>
49
50#ifdef WIN32
51#include <time.h>
52#endif
53using namespace H2Core;
54
55
57 : QWidget( pParent )
58 {
59 m_nInitialWidth = 600;
60 m_nInitialHeight = 250;
61
63 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
64
65 Hydrogen* pHydrogen = Hydrogen::get_instance();
66 std::shared_ptr<Song> pSong = pHydrogen->getSong();
67
68 assert( pSong );
69
70 setWindowTitle( tr( "Song Editor" ) );
71
72 // background
73 PixmapWidget *pBackPanel = new PixmapWidget( nullptr );
74 pBackPanel->setObjectName( "SongEditorBackPanel" );
75 pBackPanel->setFixedSize( 196, 49 );
76 pBackPanel->setPixmap( "/songEditor/bg_topPanel.png" );
77
78 // time line toggle button
79 m_pTimelineBtn = new Button( pBackPanel, QSize( 98, 17 ), Button::Type::Toggle, "",
80 pCommonStrings->getTimelineBigButton(), false, QSize(),
81 pCommonStrings->getTimelineEnabled() );
82 m_pTimelineBtn->move( 94, 4 );
83 m_pTimelineBtn->setObjectName( "TimelineBtn" );
84 connect( m_pTimelineBtn, SIGNAL( clicked() ), this, SLOT( timelineBtnClicked() ) );
85 if ( pHydrogen->getJackTimebaseState() == JackAudioDriver::Timebase::Slave ) {
86 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineDisabledTimebaseSlave() );
88 } else if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
89 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineDisabledPatternMode() );
91 } else {
93 }
94 m_bLastIsTimelineActivated = pSong->getIsTimelineActivated();
95
96 // clear sequence button
97 m_pClearPatternSeqBtn = new Button( pBackPanel, QSize( 61, 21 ), Button::Type::Push, "", pCommonStrings->getClearButton(), false, QSize(), tr("Clear pattern sequence") );
98 m_pClearPatternSeqBtn->move( 2, 25 );
99 connect( m_pClearPatternSeqBtn, SIGNAL( clicked() ), this, SLOT( clearSequence() ) );
100
101 // new pattern button
102 Button *newPatBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Push, "plus.svg", "", false, QSize( 15, 15 ), tr("Create new pattern") );
103 newPatBtn->move( 64, 25 );
104 connect( newPatBtn, SIGNAL( clicked() ), this, SLOT( newPatBtnClicked() ) );
105
106 // down button
107 m_pDownBtn = new Button( pBackPanel, QSize( 25, 10 ), Button::Type::Push,
108 "down.svg", "", false, QSize( 7, 7 ),
109 tr("Move the selected pattern down"), false, true, 2 );
110 m_pDownBtn->move( 90, 36 );
111 connect( m_pDownBtn, SIGNAL( clicked() ), this, SLOT( downBtnClicked() ) );
112
113 // up button
114 m_pUpBtn = new Button( pBackPanel, QSize( 25, 10 ), Button::Type::Push,
115 "up.svg", "", false, QSize( 7, 7 ),
116 tr("Move the selected pattern up"), false, true, 2 );
117 m_pUpBtn->move( 90, 25 );
118 connect( m_pUpBtn, SIGNAL( clicked() ), this, SLOT( upBtnClicked() ) );
119
120 // Two buttons sharing the same position and either of them is
121 // shown unpressed.
122 m_pSelectionModeBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Toggle, "select.svg", "", false, QSize( 17, 16 ), tr( "Select mode" ) );
123 m_pSelectionModeBtn->move( 116, 25 );
124 connect( m_pSelectionModeBtn, &QPushButton::clicked,
125 [=](){ activateSelectMode( true ); } );
126
127 m_pDrawModeBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Toggle, "draw.svg", "", false, QSize( 17, 16 ), tr( "Draw mode") );
128 m_pDrawModeBtn->move( 116, 25 );
129 connect( m_pDrawModeBtn, &QPushButton::clicked,
130 [=](){ activateSelectMode( false ); } );
131
133 m_pDrawModeBtn->hide();
134 } else {
135 m_pSelectionModeBtn->hide();
136 }
137
138 // Two buttons sharing the same position and either of them is
139 // shown unpressed
140 m_pPatternEditorLockedBtn = new Button( pBackPanel, QSize( 25, 21 ),
141 Button::Type::Toggle, "lock_closed.svg",
142 "", false, QSize( 21, 17 ),
143 pCommonStrings->getPatternEditorLocked(),
144 false, true );
145 m_pPatternEditorLockedBtn->move( 142, 25 );
146 connect( m_pPatternEditorLockedBtn, &QPushButton::clicked,
148
149 m_pPatternEditorUnlockedBtn = new Button( pBackPanel, QSize( 25, 21 ),
151 "lock_open.svg", "", false,
152 QSize( 21, 17 ),
153 pCommonStrings->getPatternEditorLocked(),
154 false, true );
155 m_pPatternEditorUnlockedBtn->move( 142, 25 );
156 connect( m_pPatternEditorUnlockedBtn, &QPushButton::clicked,
158
159 if ( pHydrogen->isPatternEditorLocked() ) {
161 } else {
163 }
164
165 if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
168 } else {
171 }
172
173 // Two buttons sharing the same position and either of them is
174 // shown unpressed.
175 m_pPlaySelectedSingleBtn = new Button( pBackPanel, QSize( 25, 21 ),
176 Button::Type::Push, "single_layer.svg",
177 "", false, QSize( 17, 13 ),
178 tr( "selected pattern mode"),
179 false, true );
180 m_pPlaySelectedSingleBtn->move( 168, 25 );
181 connect( m_pPlaySelectedSingleBtn, &QPushButton::clicked, [=]() {
182 activateStackedMode( true );
183 });
184
185 m_pPlaySelectedMultipleBtn = new Button( pBackPanel, QSize( 25, 21 ),
187 "multiple_layers.svg", "", false,
188 QSize( 21, 17 ),
189 tr( "stacked pattern mode"),
190 false, true );
191 m_pPlaySelectedMultipleBtn->move( 168, 25 );
193 connect( m_pPlaySelectedMultipleBtn, &QPushButton::clicked, [=]() {
194 activateStackedMode( false );
195 });
196
197 // We access the raw variable in the song class since we do not
198 // care whether Hydrogen is in song or pattern mode in here.
199 if ( pHydrogen->getSong() == nullptr ||
200 pHydrogen->getSong()->getPatternMode() == Song::PatternMode::Selected ) {
201 m_pPlaySelectedSingleBtn->setVisible( true );
202 m_pPlaySelectedMultipleBtn->setVisible( false );
203 }
204 else {
205 m_pPlaySelectedSingleBtn->setVisible( false );
206 m_pPlaySelectedMultipleBtn->setVisible( true );
207 }
208
209// ZOOM
210 m_pHScrollBar = new QScrollBar( Qt::Horizontal, nullptr );
211 m_pHScrollBar->setObjectName( "SongEditorPanel HScrollBar" );
212 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), this, SLOT( hScrollTo(int) ) );
213
214 // zoom-in btn
215 Button* pZoomInBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "plus.svg", "", false, QSize( 9, 9 ) );
216 connect( pZoomInBtn, SIGNAL( clicked() ), this, SLOT( zoomOutBtnClicked() ) );
217
218
219
220 // zoom-out btn
221 Button* pZoomOutBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "minus.svg", "", false, QSize( 9, 9 ) );
222 connect( pZoomOutBtn, SIGNAL( clicked() ), this, SLOT( zoomInBtnClicked() ) );
223
224 // view playback track toggle button
225 m_pViewPlaybackBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Toggle, "", pCommonStrings->getPlaybackTrackButton(), false, QSize(), tr( "View playback track" ) );
226 m_pViewPlaybackBtn->setObjectName( "ViewPlaybackBtn" );
227 connect( m_pViewPlaybackBtn, SIGNAL( clicked() ), this, SLOT( viewPlaybackTrackBtnClicked() ) );
228 m_pViewPlaybackBtn->setChecked( pPref->getShowPlaybackTrack() );
229
230 // Playback Fader
231 m_pPlaybackTrackFader = new Fader( pBackPanel, Fader::Type::Vertical, tr( "Playback track volume" ), false, false, 0.0, 1.5 );
232 m_pPlaybackTrackFader->setObjectName( "SongEditorPlaybackTrackFader" );
233 m_pPlaybackTrackFader->move( 6, 1 );
234 m_pPlaybackTrackFader->setValue( pSong->getPlaybackTrackVolume() );
235 m_pPlaybackTrackFader->hide();
236 connect( m_pPlaybackTrackFader, SIGNAL( valueChanged( WidgetWithInput* ) ), this, SLOT( faderChanged( WidgetWithInput* ) ) );
237
238 // mute playback track toggle button
239 m_pMutePlaybackBtn = new Button( pBackPanel, QSize( 34, 17 ),
241 pCommonStrings->getBigMuteButton(),
242 true, QSize(), tr( "Mute playback track" ),
243 false, true );
244 m_pMutePlaybackBtn->setObjectName( "SongEditorPlaybackTrackMuteButton" );
245 m_pMutePlaybackBtn->move( 158, 4 );
246 m_pMutePlaybackBtn->hide();
247 connect( m_pMutePlaybackBtn, &QPushButton::clicked, [=](bool bChecked){
249 });
250
251 if ( pHydrogen->getPlaybackTrackState() == Song::PlaybackTrack::Unavailable ) {
253 m_pMutePlaybackBtn->setChecked( true );
255 } else {
256 m_pMutePlaybackBtn->setChecked( ! pSong->getPlaybackTrackEnabled() );
257 }
258
259 // edit playback track toggle button
260 m_pEditPlaybackBtn = new Button( pBackPanel, QSize( 34, 17 ), Button::Type::Push, "", pCommonStrings->getEditButton(), false, QSize(), tr( "Choose playback track") );
261 m_pEditPlaybackBtn->setObjectName( "SongEditorPlaybackTrackEditButton" );
262 m_pEditPlaybackBtn->move( 123, 4 );
263 m_pEditPlaybackBtn->hide();
264 connect( m_pEditPlaybackBtn, SIGNAL( clicked() ), this, SLOT( editPlaybackTrackBtnClicked() ) );
265 m_pEditPlaybackBtn->setChecked( false );
266
267 // timeline view toggle button
268 m_pViewTimelineBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Toggle, "", pCommonStrings->getTimelineButton(), false, QSize(), tr( "View timeline" ) );
269 m_pViewTimelineBtn->setObjectName( "TimeLineToggleBtn" );
270 connect( m_pViewTimelineBtn, SIGNAL( clicked() ), this, SLOT( viewTimelineBtnClicked() ) );
271 m_pViewTimelineBtn->setChecked( ! pPref->getShowPlaybackTrack() );
272
273
274 QHBoxLayout *pHZoomLayout = new QHBoxLayout();
275 pHZoomLayout->setSpacing( 0 );
276 pHZoomLayout->setMargin( 0 );
277 pHZoomLayout->addWidget( m_pViewPlaybackBtn );
278 pHZoomLayout->addWidget( m_pViewTimelineBtn );
279 pHZoomLayout->addWidget( m_pHScrollBar );
280 pHZoomLayout->addWidget( pZoomInBtn );
281 pHZoomLayout->addWidget( pZoomOutBtn );
282
283 QWidget *pHScrollbarPanel = new QWidget();
284 pHScrollbarPanel->setLayout( pHZoomLayout );
285
287
288 // ~ ZOOM
289
290 // PATTERN LIST
292 m_pPatternListScrollView->setFrameShape( QFrame::NoFrame );
294 m_pPatternListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
295 m_pPatternListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
296 connect( m_pPatternListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( vScrollTo(int) ) );
297
299 m_pPatternList->setFocusPolicy( Qt::ClickFocus );
300 m_pPatternListScrollView->setFocusPolicy( Qt::ClickFocus );
303
304 // EDITOR
305 m_pEditorScrollView = new WidgetScrollArea( nullptr );
306 m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
307 m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
308 m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
311 m_pEditorScrollView->setFocusPolicy( Qt::ClickFocus );
312
313 m_pPatternList->setFocusProxy( m_pSongEditor );
314
315 connect( m_pEditorScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( hScrollTo(int) ) );
316 connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( vScrollTo(int) ) );
317
318
319 // POSITION RULER
320 m_pWidgetStack = new QStackedWidget( nullptr );
321 m_pWidgetStack->setFixedHeight( 50 );
322
324 m_pPositionRulerScrollView->setFrameShape( QFrame::NoFrame );
325 m_pPositionRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
326 m_pPositionRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
327 m_pPositionRulerScrollView->setFocusPolicy( Qt::NoFocus );
329 m_pPositionRuler->setObjectName( "SongEditorPositionRuler" );
331 m_pPositionRulerScrollView->setFixedHeight( 50 );
332 connect( m_pPositionRulerScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( hScrollTo(int) ) );
334
335 m_pPositionRuler->setFocusPolicy( Qt::ClickFocus );
336 m_pPositionRuler->setFocusProxy( m_pSongEditor );
337
339 m_pPlaybackTrackScrollView->setFrameShape( QFrame::NoFrame );
340 m_pPlaybackTrackScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
341 m_pPlaybackTrackScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
342
343 auto pCompo = Hydrogen::get_instance()->getAudioEngine()->getSampler()->getPlaybackTrackInstrument()->get_components()->front();
344 assert(pCompo);
345
348 m_pPlaybackTrackWaveDisplay->resize( m_pPositionRuler->width() , 50);
349 m_pPlaybackTrackWaveDisplay->setAcceptDrops( true );
350
352 m_pPlaybackTrackScrollView->setFixedHeight( 50 );
353
355 m_pAutomationPathScrollView->setFrameShape( QFrame::NoFrame );
356 m_pAutomationPathScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
357 m_pAutomationPathScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
359 m_pAutomationPathView->setObjectName( "SongEditorAutomationPathView" );
361 m_pAutomationPathScrollView->setFixedHeight( 64 );
362 connect( m_pAutomationPathView, SIGNAL( pointAdded(float, float) ), this, SLOT( automationPathPointAdded(float,float) ) );
363 connect( m_pAutomationPathView, SIGNAL( pointRemoved(float, float) ), this, SLOT( automationPathPointRemoved(float,float) ) );
364 connect( m_pAutomationPathView, SIGNAL( pointMoved(float, float, float, float) ), this, SLOT( automationPathPointMoved(float,float, float, float) ) );
365
366 m_pAutomationCombo = new LCDCombo( nullptr, QSize( m_nPatternListWidth, 18 ), true );
367 m_pAutomationCombo->setToolTip( tr("Adjust parameter values in time") );
368 m_pAutomationCombo->addItem( tr("Velocity") );
369 m_pAutomationCombo->setCurrentIndex( 0 );
370
371 m_pVScrollBar = new QScrollBar( Qt::Vertical, nullptr );
372 m_pVScrollBar->setObjectName( "SongEditorPanel VScrollBar" );
373 connect( m_pVScrollBar, SIGNAL(valueChanged(int)), this, SLOT( vScrollTo(int) ) );
374
377
378 if( Preferences::get_instance()->getShowPlaybackTrack() ) {
380 } else {
381 showTimeline();
382 }
383
384 // ok...let's build the layout
385 QGridLayout *pGridLayout = new QGridLayout();
386 pGridLayout->setSpacing( 0 );
387 pGridLayout->setMargin( 0 );
388
389 pGridLayout->addWidget( pBackPanel, 0, 0 );
390 pGridLayout->addWidget( m_pWidgetStack, 0, 1 );
391 pGridLayout->addWidget( m_pPatternListScrollView, 1, 0 );
392 pGridLayout->addWidget( m_pEditorScrollView, 1, 1 );
393 pGridLayout->addWidget( m_pVScrollBar, 1, 2, 2, 1 );
394 pGridLayout->addWidget( m_pAutomationPathScrollView, 2, 1);
395 pGridLayout->addWidget( m_pAutomationCombo, 2, 0,
396 Qt::AlignVCenter | Qt::AlignRight );
397 pGridLayout->addWidget( pHScrollbarPanel, 3, 1 );
398 if( !pPref->getShowAutomationArea() ){
400 m_pAutomationCombo->hide();
401 }
402
403 this->setLayout( pGridLayout );
404 QPalette defaultPalette;
405 defaultPalette.setColor( QPalette::Window, QColor( 58, 62, 72 ) );
406 this->setPalette( defaultPalette );
407
408 show();
409
410 updateAll();
411
413
414 m_pTimer = new QTimer(this);
415
416 connect(m_pTimer, SIGNAL(timeout()), this, SLOT( updatePlayHeadPosition() ) );
417 connect(m_pTimer, SIGNAL(timeout()), this, SLOT( updatePlaybackFaderPeaks() ) );
418
419 m_pTimer->start(100);
420}
421
422
423
428
429
430
432{
433 auto pHydrogen = H2Core::Hydrogen::get_instance();
434 auto pAudioEngine = pHydrogen->getAudioEngine();
435 std::shared_ptr<Song> pSong = pHydrogen->getSong();
436
437 if ( Preferences::get_instance()->m_bFollowPlayhead &&
438 pHydrogen->getMode() == Song::Mode::Song ) {
439 if ( pAudioEngine->getState() != H2Core::AudioEngine::State::Playing ) {
440 return;
441 }
442
443 int nWidth;
444 if ( m_pViewPlaybackBtn->isChecked() ) {
445 nWidth = m_pPlaybackTrackScrollView->viewport()->width();
446 } else {
447 nWidth = m_pPositionRulerScrollView->viewport()->width();
448 }
449
450 QPoint pos = m_pPositionRuler->pos();
451 int x = -pos.x();
452
453 int nPlayHeadPosition = pAudioEngine->getTransportPosition()->getColumn() *
455
456 int value = m_pEditorScrollView->horizontalScrollBar()->value();
457
458 // Distance the grid will be moved left or right.
459 int nIncrement = 100;
460 if ( nIncrement > std::round( static_cast<float>(nWidth) / 3 ) ) {
461 nIncrement = std::round( static_cast<float>(nWidth) / 3 );
462 } else if ( nIncrement < 2 * Skin::nPlayheadWidth ) {
463 nIncrement = 2 * Skin::nPlayheadWidth;
464 }
465
466 if ( nPlayHeadPosition > ( x + nWidth - std::floor( static_cast<float>( nIncrement ) / 2 ) ) ) {
467 hScrollTo( value + nIncrement );
468 }
469 else if ( nPlayHeadPosition < x ) {
470 hScrollTo( value - nIncrement );
471 }
472 }
473}
474
475void SongEditorPanel::highlightPatternEditorLocked( bool bUseRedBackground ) {
477}
478
480{
483 auto pInstrument = pSampler->getPlaybackTrackInstrument();
484
485
486 bool bShowPeaks = pPref->showInstrumentPeaks();
487 float fallOff = pPref->getMixerFalloffSpeed();
488
489 // fader
490 float fOldPeak_L = m_pPlaybackTrackFader->getPeak_L();
491 float fOldPeak_R = m_pPlaybackTrackFader->getPeak_R();
492
493 float fNewPeak_L = pInstrument->get_peak_l();
494 pInstrument->set_peak_l( 0.0f ); // reset instrument peak
495
496 float fNewPeak_R = pInstrument->get_peak_r();
497 pInstrument->set_peak_r( 0.0f ); // reset instrument peak
498
499 if (!bShowPeaks) {
500 fNewPeak_L = 0.0f;
501 fNewPeak_R = 0.0f;
502 }
503
504 if ( fNewPeak_L >= fOldPeak_L) { // LEFT peak
505 m_pPlaybackTrackFader->setPeak_L( fNewPeak_L );
506 }
507 else {
508 m_pPlaybackTrackFader->setPeak_L( fOldPeak_L / fallOff );
509 }
510 if ( fNewPeak_R >= fOldPeak_R) { // Right peak
511 m_pPlaybackTrackFader->setPeak_R( fNewPeak_R );
512 }
513 else {
514 m_pPlaybackTrackFader->setPeak_R( fOldPeak_R / fallOff );
515 }
516}
517
519{
520 static bool inside = false;
521 if ( !inside ) {
522 inside = true;
523 m_pVScrollBar->setValue( value );
524 m_pPatternListScrollView->verticalScrollBar()->setValue( value );
525 m_pEditorScrollView->verticalScrollBar()->setValue( value );
526 inside = false;
527 }
528}
529
531{
532 static bool inside = false;
533 if ( !inside ) {
534 inside = true;
535 m_pHScrollBar->setValue( value );
536 m_pEditorScrollView->horizontalScrollBar()->setValue( value );
537 m_pPlaybackTrackScrollView->horizontalScrollBar()->setValue( value );
538 m_pPositionRulerScrollView->horizontalScrollBar()->setValue( value );
539 m_pAutomationPathScrollView->horizontalScrollBar()->setValue( value );
540 inside = false;
541 }
542}
543
548{
549 auto pHydrogen = Hydrogen::get_instance();
550 auto pSong = pHydrogen->getSong();
551
553 m_pPatternList->update();
554
556 m_pSongEditor->update();
557
559
561}
562
564 auto pHydrogen = Hydrogen::get_instance();
565 auto pSong = pHydrogen->getSong();
566
568
569 m_pAutomationPathView->setAutomationPath( pSong->getVelocityAutomationPath() );
570
572}
573
575{
576 auto pHydrogen = Hydrogen::get_instance();
577 auto pSong = pHydrogen->getSong();
578
579 if ( Preferences::get_instance()->getShowPlaybackTrack() &&
580 pSong != nullptr ) {
581
582 if ( pHydrogen->getPlaybackTrackState() == Song::PlaybackTrack::Unavailable ) {
583 // No playback track chosen
585 m_pMutePlaybackBtn->setChecked( true );
587
589 }
590 else {
591 // Playback track was selected by the user and is ready to
592 // use.
595 if ( pHydrogen->getPlaybackTrackState() == Song::PlaybackTrack::Muted ) {
596 m_pMutePlaybackBtn->setChecked( true );
597 } else {
598 m_pMutePlaybackBtn->setChecked( false );
599 }
600
601 auto pPlaybackCompo = pHydrogen->getAudioEngine()->getSampler()->
602 getPlaybackTrackInstrument()->get_components()->front();
603
604 m_pPlaybackTrackWaveDisplay->updateDisplay( pPlaybackCompo->get_layer(0) );
605 }
606 }
607}
608
609
614
619{
620 Hydrogen *pHydrogen = Hydrogen::get_instance();
621 std::shared_ptr<Song> pSong = pHydrogen->getSong();
622 PatternList *pPatternList = pSong->getPatternList();
623 Pattern *pNewPattern = new Pattern( tr("Pattern %1").arg(pPatternList->size()+1));
624 PatternPropertiesDialog *pDialog = new PatternPropertiesDialog( this, pNewPattern, 0, true );
625
626 if ( pDialog->exec() == QDialog::Accepted ) {
627 int nRow;
628 if ( pHydrogen->getSelectedPatternNumber() == -1 ) {
629 nRow = pPatternList->size();
630 } else {
631 nRow = pHydrogen->getSelectedPatternNumber() + 1;
632 }
633 SE_insertPatternAction* pAction =
634 new SE_insertPatternAction( nRow, new Pattern( pNewPattern->get_name(),
635 pNewPattern->get_info(),
636 pNewPattern->get_category() ) );
637 HydrogenApp::get_instance()->m_pUndoStack->push( pAction );
638 }
639
640 delete pNewPattern;
641 delete pDialog;
642}
643
648{
649 Hydrogen *pHydrogen = Hydrogen::get_instance();
650
651 if( pHydrogen->getSelectedPatternNumber() < 0 || !pHydrogen->getSelectedPatternNumber() ) {
652 return;
653 }
654 int nSelectedPatternPos = pHydrogen->getSelectedPatternNumber();
655
656 SE_movePatternListItemAction *pAction = new SE_movePatternListItemAction( nSelectedPatternPos, nSelectedPatternPos -1 ) ;
657 HydrogenApp::get_instance()->m_pUndoStack->push( pAction );
658}
659
660
661
666{
667 Hydrogen *pHydrogen = Hydrogen::get_instance();
668 std::shared_ptr<Song> pSong = pHydrogen->getSong();
669 PatternList *pPatternList = pSong->getPatternList();
670
671 if( pHydrogen->getSelectedPatternNumber() < 0 ||
672 pHydrogen->getSelectedPatternNumber() + 1 >= pPatternList->size() ) {
673 return;
674 }
675
676 int nSelectedPatternPos = pHydrogen->getSelectedPatternNumber();
677
678 SE_movePatternListItemAction *pAction = new SE_movePatternListItemAction( nSelectedPatternPos, nSelectedPatternPos +1 ) ;
679 HydrogenApp::get_instance()->m_pUndoStack->push( pAction );
680}
681
682
683
684
686{
687 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
688 int res = QMessageBox::information( this, "Hydrogen",
689 tr( "Warning, this will erase your pattern sequence.\nAre you sure?"),
690 pCommonStrings->getButtonOk(),
691 pCommonStrings->getButtonCancel(),
692 nullptr, 1 );
693 if ( res == 1 ) {
694 return;
695 }
696
697 QString filename = Filesystem::tmp_file_path( "SEQ.xml" );
700
701 pH2App->m_pUndoStack->push( pAction );
702}
703
704
706{
707 auto pHydrogen = Hydrogen::get_instance();
708 auto pAudioEngine = pHydrogen->getAudioEngine();
709 //clear the old sequese
710 std::vector<PatternList*> *pPatternGroupsVect = pHydrogen->getSong()->getPatternGroupVector();
711 for (uint i = 0; i < pPatternGroupsVect->size(); i++) {
712 PatternList *pPatternList = (*pPatternGroupsVect)[i];
713 pPatternList->clear();
714 delete pPatternList;
715 }
716 pPatternGroupsVect->clear();
717
718 pAudioEngine->lock( RIGHT_HERE );
719 pHydrogen->getSong()->readTempPatternList( filename );
720 pHydrogen->updateSongSize();
721 pHydrogen->updateSelectedPattern( false );
722 pAudioEngine->unlock();
723
725 updateAll();
726}
727
728
730{
731 m_pHScrollBar->setMinimum( m_pEditorScrollView->horizontalScrollBar()->minimum() );
732 m_pHScrollBar->setMaximum( m_pEditorScrollView->horizontalScrollBar()->maximum() );
733 m_pHScrollBar->setSingleStep( m_pEditorScrollView->horizontalScrollBar()->singleStep() );
734 m_pHScrollBar->setPageStep( m_pEditorScrollView->horizontalScrollBar()->pageStep() );
735 m_pHScrollBar->setValue( m_pEditorScrollView->horizontalScrollBar()->value() );
736
737 m_pVScrollBar->setMinimum( m_pEditorScrollView->verticalScrollBar()->minimum() );
738 m_pVScrollBar->setMaximum( m_pEditorScrollView->verticalScrollBar()->maximum() );
739 m_pVScrollBar->setSingleStep( m_pEditorScrollView->verticalScrollBar()->singleStep() );
740 m_pVScrollBar->setPageStep( m_pEditorScrollView->verticalScrollBar()->pageStep() );
741 m_pVScrollBar->setValue( m_pEditorScrollView->verticalScrollBar()->value() );
742}
743
744
745void SongEditorPanel::resizeEvent( QResizeEvent *ev )
746{
747 UNUSED( ev );
749}
750
752
753 if ( nValue == 0 ) { // different song opened
757 // Calls patternEditorLockedEvent() internally.
762
764 }
765}
766
770
772
773 auto pHydrogen = Hydrogen::get_instance();
774 if ( pHydrogen->getMode() == Song::Mode::Song ) {
777 }
778
779 if ( pHydrogen->isPatternEditorLocked() ) {
782
783 if ( pHydrogen->getAudioEngine()->getState() ==
784 AudioEngine::State::Playing ) {
785 m_pPatternEditorLockedBtn->setChecked( true );
786 } else {
787 m_pPatternEditorLockedBtn->setChecked( false );
788 }
789 } else {
792 m_pPatternEditorUnlockedBtn->setChecked( false );
793 }
794
795 if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
798 }
799}
800
802 // The lock button is highlighted when transport is rolling.
804}
805
807
808 m_pSelectionModeBtn->setChecked( false );
809 m_pDrawModeBtn->setChecked( false );
810
811 if ( Hydrogen::get_instance()->getActionMode() ==
813 m_pDrawModeBtn->show();
814 m_pSelectionModeBtn->hide();
815 } else {
816 m_pDrawModeBtn->hide();
817 m_pSelectionModeBtn->show();
818 }
819}
820
825
827{
828 m_pWidgetStack->setCurrentWidget( m_pPositionRulerScrollView );
829 m_pTimelineBtn->show();
830 m_pMutePlaybackBtn->hide();
831 m_pEditPlaybackBtn->hide();
832 m_pPlaybackTrackFader->hide();
833 if ( ! m_pViewPlaybackBtn->isDown() ) {
834 m_pViewPlaybackBtn->setChecked( false );
835 }
836 if ( ! m_pViewTimelineBtn->isDown() ) {
837 m_pViewTimelineBtn->setChecked( true );
838 }
840}
841
842
844{
845 m_pWidgetStack->setCurrentWidget( m_pPlaybackTrackScrollView );
846 m_pTimelineBtn->hide();
847 m_pMutePlaybackBtn->show();
848 m_pEditPlaybackBtn->show();
849 m_pPlaybackTrackFader->show();
850 if ( ! m_pViewTimelineBtn->isDown() ) {
851 m_pViewTimelineBtn->setChecked( false );
852 }
853 if ( ! m_pViewPlaybackBtn->isDown() ) {
854 m_pViewPlaybackBtn->setChecked( true );
855 }
857
859}
860
862{
863 if ( m_pViewTimelineBtn->isChecked() ){
864 showTimeline();
865 } else {
867 }
868}
869
871{
872 if ( m_pViewPlaybackBtn->isChecked() ){
874 } else {
875 showTimeline();
876 }
877}
878
880{
881 auto pHydrogen = Hydrogen::get_instance();
882 auto pSong = pHydrogen->getSong();
883 if ( pHydrogen->getAudioEngine()->getState() ==
885 pHydrogen->sequencer_stop();
886 }
887
888 QString sPath, sFilename;
889
890 if ( ! pSong->getPlaybackTrackFilename().isEmpty() ) {
891 QFileInfo fileInfo( pSong->getPlaybackTrackFilename() );
892 sFilename = pSong->getPlaybackTrackFilename();
893 sPath = fileInfo.absoluteDir().absolutePath();
894 } else {
895 sFilename = "";
897 }
898
899 if ( ! Filesystem::dir_readable( sPath, false ) ){
900 sPath = QDir::homePath();
901 }
902
903 //use AudioFileBrowser, but don't allow multi-select. Also, hide all no necessary controls.
904 AudioFileBrowser *pFileBrowser =
905 new AudioFileBrowser( nullptr, false, false, sPath, sFilename );
906
907 QStringList filenameList;
908
909 if ( pFileBrowser->exec() == QDialog::Accepted ) {
910
911 // Only overwrite the default directory if we didn't start
912 // from an existing file or the final directory differs from
913 // the starting one.
914 if ( sFilename.isEmpty() ||
915 sPath != pFileBrowser->getSelectedDirectory() ) {
917 }
918 filenameList = pFileBrowser->getSelectedFiles();
919 }
920
921 delete pFileBrowser;
922
923 if( filenameList.size() != 3 ) {
924 return;
925 }
926
927 if ( filenameList[2].isEmpty() ) {
928 return;
929 }
930
931 pHydrogen->loadPlaybackTrack( filenameList[2] );
932}
933
935{
936 auto pHydrogen = Hydrogen::get_instance();
937
938 // We access the raw variable in the song class since we do not
939 // care whether Hydrogen is in song or pattern mode in here.
940 if ( pHydrogen->getSong() == nullptr ||
941 pHydrogen->getSong()->getPatternMode() == Song::PatternMode::Selected ) {
942 m_pPlaySelectedSingleBtn->setVisible( true );
943 m_pPlaySelectedMultipleBtn->setVisible( false );
944 }
945 else {
946 m_pPlaySelectedSingleBtn->setVisible( false );
947 m_pPlaySelectedMultipleBtn->setVisible( true );
948 }
949}
950
964
965
979
981{
982 auto pHydrogen = Hydrogen::get_instance();
983 auto pSong = pHydrogen->getSong();
984
985 if ( pSong == nullptr ) {
986 return;
987 }
988
989 Fader* pFader = dynamic_cast<Fader*>( pRef );
990 const float fNewValue = std::round( pFader->getValue() * 100 ) / 100;
991
992 if ( pSong->getPlaybackTrackVolume() != fNewValue ) {
993 pSong->setPlaybackTrackVolume( fNewValue );
995 tr( "Playback volume set to" )
996 .append( QString( " [%1]" ).arg( fNewValue ) ),
997 "SongEditorPanel:PlaybackTrackVolume" );
998 }
999}
1000
1001
1003{
1004 updateAll();
1005
1006 auto pHydrogen = Hydrogen::get_instance();
1007 if ( pHydrogen->getSelectedPatternNumber() == -1 ) {
1008 return;
1009 }
1010
1011 // Make sure currently selected pattern is visible.
1012 int nGridHeight = m_pPatternList->getGridHeight();
1013 m_pPatternListScrollView->ensureVisible( 0, (pHydrogen->getSelectedPatternNumber()
1014 * nGridHeight + nGridHeight/2 ),
1015 0, nGridHeight );
1016}
1017
1024
1025
1032
1033
1034void SongEditorPanel::automationPathPointMoved(float ox, float oy, float tx, float ty)
1035{
1037 SE_automationPathMovePointAction *pUndoAction = new SE_automationPathMovePointAction(pPath, ox, oy, tx, ty);
1038 HydrogenApp::get_instance()->m_pUndoStack->push( pUndoAction );
1039}
1040
1042{
1044
1045 if(!pPref->getShowAutomationArea())
1046 {
1048 m_pAutomationCombo->show();
1049 pPref->setShowAutomationArea( true );
1050 } else {
1052 m_pAutomationCombo->hide();
1053 pPref->setShowAutomationArea( false );
1054 }
1055}
1056
1057
1059 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1060 auto pHydrogen = Hydrogen::get_instance();
1061 if ( pHydrogen->getJackTimebaseState() == JackAudioDriver::Timebase::Slave ) {
1062 setTimelineEnabled( false );
1063 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineDisabledTimebaseSlave() );
1064 } else if ( pHydrogen->getMode() != Song::Mode::Pattern ) {
1065 setTimelineEnabled( true );
1066 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineEnabled() );
1067 }
1068}
1069
1071 auto pHydrogen = Hydrogen::get_instance();
1072 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1073 if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
1074 setTimelineEnabled( false );
1075 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineDisabledPatternMode() );
1076
1077 } else if ( pHydrogen->getJackTimebaseState() != JackAudioDriver::Timebase::Slave ) {
1078 setTimelineEnabled( true );
1079 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineEnabled() );
1080
1081 }
1082
1084
1085 // Set disabled or enabled
1086 if ( Hydrogen::get_instance()->getMode() == Song::Mode::Song ) {
1087 m_pPlaySelectedMultipleBtn->setDisabled( true );
1088 m_pPlaySelectedSingleBtn->setDisabled( true );
1089 } else {
1090 m_pPlaySelectedMultipleBtn->setDisabled( false );
1091 m_pPlaySelectedSingleBtn->setDisabled( false );
1092 }
1093}
1094
1096 auto pHydrogen = Hydrogen::get_instance();
1097 if ( ! pHydrogen->isTimelineEnabled() && m_pTimelineBtn->isChecked() ) {
1098 setTimelineActive( false );
1099 } else if ( pHydrogen->isTimelineEnabled() && ! m_pTimelineBtn->isChecked() ) {
1100 setTimelineActive( true );
1101 }
1102}
1103
1105 return m_pTimelineBtn->isChecked();
1106}
1107
1109 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1110
1111 if ( ! m_pTimelineBtn->isDown() ) {
1112 m_pTimelineBtn->setChecked( bActive );
1113 }
1114
1116
1117 QString sMessage = QString( "%1 = %2" )
1118 .arg( pCommonStrings->getTimelineBigButton() )
1119 .arg( bActive ? pCommonStrings->getStatusOn() : pCommonStrings->getStatusOff() );
1121}
1122
1126
1128 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1129
1130 if ( bEnabled ) {
1131 m_pTimelineBtn->setIsActive( true );
1132 // setTimelineActive( m_bLastIsTimelineActivated );
1133 } else {
1134 m_bLastIsTimelineActivated = Hydrogen::get_instance()->getSong()->getIsTimelineActivated();
1135 if ( m_pTimelineBtn->isChecked() ) {
1136 // setTimelineActive( false );
1137 }
1138 m_pTimelineBtn->setIsActive( false );
1139 }
1140
1141 QString sMessage = QString( "%1 = %2" )
1142 .arg( pCommonStrings->getTimelineBigButton() )
1143 .arg( bEnabled ? pCommonStrings->getStatusEnabled() :
1144 pCommonStrings->getStatusDisabled() );
1146}
1147
1151
1153 // Triggered every time the column of the SongEditor grid
1154 // changed. Either by rolling transport or by relocation.
1155 // In Song mode, we may scroll to change position in the Song Editor.
1156 auto pHydrogen = Hydrogen::get_instance();
1157 auto pPref = Preferences::get_instance();
1158 if ( pHydrogen->getMode() == Song::Mode::Song ) {
1159
1160 // Scroll vertically to keep currently playing patterns in view
1161 int nPatternInView = -1;
1162 int scroll = m_pSongEditor->yScrollTarget( m_pEditorScrollView, &nPatternInView );
1163 vScrollTo( scroll );
1164 }
1165}
1166
1168 auto pHydrogen = Hydrogen::get_instance();
1169 if ( bActive ) {
1170 pHydrogen->setPatternMode( Song::PatternMode::Stacked );
1171 }
1172 else {
1173 pHydrogen->setPatternMode( Song::PatternMode::Selected );
1174 }
1175}
1176
1178 auto pHydrogen = Hydrogen::get_instance();
1179
1180 // Already reset them in here in order to avoid visual glitches.
1181 m_pSelectionModeBtn->setChecked( false );
1182 m_pDrawModeBtn->setChecked( false );
1183
1184 if ( bActivate ) {
1185 pHydrogen->setActionMode( H2Core::Song::ActionMode::drawMode );
1186 }
1187 else {
1188 pHydrogen->setActionMode( H2Core::Song::ActionMode::selectMode );
1189 }
1190}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:59
This dialog is used to preview audiofiles.
QStringList getSelectedFiles()
H2Core::AutomationPath * getAutomationPath() const noexcept
void setGridWidth(int width)
void setAutomationPath(H2Core::AutomationPath *path, bool bUpdate=true)
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
bool getIsActive() const
Definition Button.h:178
void setIsActive(bool bIsActive)
Definition Button.cpp:99
Custom fader widget.
Definition Fader.h:44
@ Vertical
Only used for the playback track in the SongEditorPanel.
float getPeak_L() const
Definition Fader.h:62
float getPeak_R() const
Definition Fader.h:65
void setPeak_R(float peak)
Definition Fader.cpp:338
void setPeak_L(float peak)
Definition Fader.cpp:313
@ Playing
Transport is rolling.
Sampler * getSampler() const
static bool dir_readable(const QString &path, bool silent=false)
returns true if the given path is a readable regular directory
static QString tmp_file_path(const QString &base)
touch a temporary file under tmp_dir() and return it's path.
Hydrogen Audio Engine.
Definition Hydrogen.h:54
JackAudioDriver::Timebase getJackTimebaseState() const
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
void setIsTimelineActivated(bool bEnabled)
Wrapper around both Song::setIsTimelineActivated (recent) and Preferences::setUseTimelinebpm() (forme...
Song::ActionMode getActionMode() const
Song::PlaybackTrack getPlaybackTrackState() const
Wrapper around Song::getPlaybackTrackState().
Definition Hydrogen.cpp:240
Song::Mode getMode() const
int getSelectedPatternNumber() const
Definition Hydrogen.h:660
void mutePlaybackTrack(const bool bMuted)
Wrapper around Song::setPlaybackTrackEnabled().
Definition Hydrogen.cpp:250
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
void setIsPatternEditorLocked(bool bValue)
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
bool isPatternEditorLocked() const
Convenience function checking whether using the Pattern Editor is locked in the song settings and the...
PatternList is a collection of patterns.
Definition PatternList.h:43
void clear()
empty the pattern list
int size() const
returns the numbers of patterns
Pattern class is a Note container.
Definition Pattern.h:46
const QString & get_info() const
get the category of the pattern
Definition Pattern.h:320
const QString & get_name() const
set the category of the pattern
Definition Pattern.h:310
const QString & get_category() const
set the length of the pattern
Definition Pattern.h:330
Manager for User Preferences File (singleton)
Definition Preferences.h:78
void setShowAutomationArea(bool value)
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setShowPlaybackTrack(bool val)
void setSongEditorGridWidth(unsigned value)
void setSongEditorGridHeight(unsigned value)
bool getShowPlaybackTrack() const
void setLastOpenPlaybackTrackDirectory(QString sPath)
QString getLastOpenPlaybackTrackDirectory() const
Waveform based sampler.
Definition Sampler.h:51
std::shared_ptr< Instrument > getPlaybackTrackInstrument() const
Definition Sampler.h:208
@ selectMode
Holding a pressed left mouse key will draw a rectangle to select a group of Notes.
@ drawMode
Holding a pressed left mouse key will draw/delete patterns in all grid cells encountered.
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
QUndoStack * m_pUndoStack
void showStatusBarMessage(const QString &sMessage, const QString &sCaller="")
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
void addItem(const QString &text, const QVariant &userData=QVariant())
Definition LCDCombo.cpp:63
Pattern Properties Dialog.
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
void updateDisplay(std::shared_ptr< H2Core::InstrumentLayer > pLayer) override
static constexpr int nPlayheadWidth
Definition Skin.h:77
void updateAll()
Update and redraw all...
Button * m_pPlaySelectedMultipleBtn
virtual void playbackTrackChangedEvent() override
QScrollArea * m_pPlaybackTrackScrollView
virtual void timelineActivationEvent() override
QScrollArea * m_pPositionRulerScrollView
Button * m_pViewTimelineBtn
void setTimelineEnabled(bool bEnabled)
SongEditorPanel(QWidget *parent)
static const int m_nPatternListWidth
QScrollArea * m_pEditorScrollView
void faderChanged(WidgetWithInput *pRef)
QStackedWidget * m_pWidgetStack
void newPatBtnClicked()
Create a new pattern.
void hScrollTo(int value)
void restoreGroupVector(QString filename)
virtual void stateChangedEvent(H2Core::AudioEngine::State) override
void editPlaybackTrackBtnClicked()
void toggleAutomationAreaVisibility()
void downBtnClicked()
Move down a pattern in the patternList.
QScrollBar * m_pHScrollBar
void highlightPatternEditorLocked(bool bUseRedBackground)
Turns the background color of m_pPatternEditorLockedBtn red to signal the user her last action was no...
SongEditorPositionRuler * m_pPositionRuler
virtual void resizeEvent(QResizeEvent *ev) override
bool getTimelineActive() const
void upBtnClicked()
Move up a pattern in the patternList.
virtual void patternModifiedEvent() override
void automationPathPointRemoved(float x, float y)
void activateSelectMode(bool bActivate)
QScrollBar * m_pVScrollBar
bool getTimelineEnabled() const
virtual void stackedModeActivationEvent(int) override
virtual void songModeActivationEvent() override
Button * m_pPatternEditorLockedBtn
void activateStackedMode(bool bActivate)
Used by the shotlist during automated generation of images for the manual.
void setTimelineActive(bool bActive)
Button * m_pPlaySelectedSingleBtn
Fader * m_pPlaybackTrackFader
Button * m_pViewPlaybackBtn
SongEditor * m_pSongEditor
QScrollArea * m_pAutomationPathScrollView
void updatePlaybackTrackIfNecessary()
virtual void playingPatternsChangedEvent() override
virtual void updateSongEvent(int) override
LCDCombo * m_pAutomationCombo
Button * m_pClearPatternSeqBtn
void vScrollTo(int value)
QScrollArea * m_pPatternListScrollView
Button * m_pSelectionModeBtn
Button * m_pMutePlaybackBtn
AutomationPathView * m_pAutomationPathView
SongEditorPatternList * m_pPatternList
void viewPlaybackTrackBtnClicked()
Button * m_pEditPlaybackBtn
virtual void selectedPatternChangedEvent() override
virtual void gridCellToggledEvent() override
void automationPathPointMoved(float ox, float oy, float tx, float ty)
virtual void patternEditorLockedEvent() override
void automationPathPointAdded(float x, float y)
virtual void jackTimebaseStateChangedEvent() override
Button * m_pPatternEditorUnlockedBtn
PlaybackTrackWaveDisplay * m_pPlaybackTrackWaveDisplay
virtual void actionModeChangeEvent(int nValue) override
Updates the associated buttons if the action mode was changed within the core.
Song editor pattern list.
Definition SongEditor.h:263
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void setGridWidth(uint width)
Song editor.
Definition SongEditor.h:72
int getGridHeight()
Definition SongEditor.h:92
void setGridWidth(uint width)
int yScrollTarget(QScrollArea *pScrollArea, int *pnPatternInView)
Calculate a target Y scroll value for tracking a playing song.
int getGridWidth()
void invalidateBackground()
void updateEditorandSetTrue()
void setSampleNameAlignment(Qt::AlignmentFlag flag)
Definition WaveDisplay.h:81
Base class for active user input widget, which are not based on a high-level Qt widget.
virtual void setValue(float fValue, bool bTriggeredByUserInteraction=false)
void setIsActive(bool bIsActive)
float getValue() const
#define UNUSED(v)
Definition Globals.h:42