hydrogen 1.2.6
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-2025 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22#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 {
60 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
61
62 Hydrogen* pHydrogen = Hydrogen::get_instance();
63 std::shared_ptr<Song> pSong = pHydrogen->getSong();
64
65 assert( pSong );
66
67 setWindowTitle( tr( "Song Editor" ) );
68
69 // background
70 PixmapWidget *pBackPanel = new PixmapWidget( nullptr );
71 pBackPanel->setObjectName( "SongEditorBackPanel" );
72 pBackPanel->setFixedSize( 196, m_nMinimumHeight );
73 pBackPanel->setPixmap( "/songEditor/bg_topPanel.png" );
74
75 // time line toggle button
76 m_bLastIsTimelineActivated = pSong->getIsTimelineActivated();
77 m_pTimelineBtn = new Button( pBackPanel, QSize( 98, 17 ), Button::Type::Toggle, "",
78 pCommonStrings->getTimelineBigButton(), false, QSize(),
79 pCommonStrings->getTimelineEnabled() );
80 m_pTimelineBtn->move( 94, 4 );
81 m_pTimelineBtn->setObjectName( "TimelineBtn" );
83 connect( m_pTimelineBtn, SIGNAL( clicked() ), this, SLOT( timelineBtnClicked() ) );
85 m_pTimelineBtn->setToolTip(
86 pCommonStrings->getTimelineDisabledTimebaseListener() );
87 m_pTimelineBtn->setIsActive( false );
88 }
89 else if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
90 m_pTimelineBtn->setToolTip(
91 pCommonStrings->getTimelineDisabledPatternMode() );
92 m_pTimelineBtn->setIsActive( false );
93 }
94
95 // clear sequence button
96 m_pClearPatternSeqBtn = new Button( pBackPanel, QSize( 61, 21 ), Button::Type::Push, "", pCommonStrings->getClearButton(), false, QSize(), tr("Clear pattern sequence") );
97 m_pClearPatternSeqBtn->move( 2, 25 );
98 connect( m_pClearPatternSeqBtn, SIGNAL( clicked() ), this, SLOT( clearSequence() ) );
99
100 // new pattern button
101 Button *newPatBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Push, "plus.svg", "", false, QSize( 15, 15 ), tr("Create new pattern") );
102 newPatBtn->move( 64, 25 );
103 connect( newPatBtn, SIGNAL( clicked() ), this, SLOT( newPatBtnClicked() ) );
104
105 // down button
106 m_pDownBtn = new Button( pBackPanel, QSize( 25, 10 ), Button::Type::Push,
107 "down.svg", "", false, QSize( 7, 7 ),
108 tr("Move the selected pattern down"), false, true, 2 );
109 m_pDownBtn->move( 90, 36 );
110 connect( m_pDownBtn, SIGNAL( clicked() ), this, SLOT( downBtnClicked() ) );
111
112 // up button
113 m_pUpBtn = new Button( pBackPanel, QSize( 25, 10 ), Button::Type::Push,
114 "up.svg", "", false, QSize( 7, 7 ),
115 tr("Move the selected pattern up"), false, true, 2 );
116 m_pUpBtn->move( 90, 25 );
117 connect( m_pUpBtn, SIGNAL( clicked() ), this, SLOT( upBtnClicked() ) );
118
119 // Two buttons sharing the same position and either of them is
120 // shown unpressed.
121 m_pSelectionModeBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Toggle, "select.svg", "", false, QSize( 17, 16 ), tr( "Select mode" ) );
122 m_pSelectionModeBtn->move( 116, 25 );
123 connect( m_pSelectionModeBtn, &QPushButton::clicked,
124 [=](){ activateSelectMode( true ); } );
125
126 m_pDrawModeBtn = new Button( pBackPanel, QSize( 25, 21 ), Button::Type::Toggle, "draw.svg", "", false, QSize( 17, 16 ), tr( "Draw mode") );
127 m_pDrawModeBtn->move( 116, 25 );
128 connect( m_pDrawModeBtn, &QPushButton::clicked,
129 [=](){ activateSelectMode( false ); } );
130
132 m_pDrawModeBtn->hide();
133 } else {
134 m_pSelectionModeBtn->hide();
135 }
136
137 // Two buttons sharing the same position and either of them is
138 // shown unpressed
139 m_pPatternEditorLockedBtn = new Button( pBackPanel, QSize( 25, 21 ),
140 Button::Type::Toggle, "lock_closed.svg",
141 "", false, QSize( 21, 17 ),
142 pCommonStrings->getPatternEditorLocked(),
143 false, true );
144 m_pPatternEditorLockedBtn->move( 142, 25 );
145 connect( m_pPatternEditorLockedBtn, &QPushButton::clicked,
147
148 m_pPatternEditorUnlockedBtn = new Button( pBackPanel, QSize( 25, 21 ),
150 "lock_open.svg", "", false,
151 QSize( 21, 17 ),
152 pCommonStrings->getPatternEditorLocked(),
153 false, true );
154 m_pPatternEditorUnlockedBtn->move( 142, 25 );
155 connect( m_pPatternEditorUnlockedBtn, &QPushButton::clicked,
157
158 if ( pHydrogen->isPatternEditorLocked() ) {
160 } else {
162 }
163
164 if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
165 m_pPatternEditorLockedBtn->setIsActive( false );
166 m_pPatternEditorUnlockedBtn->setIsActive( false );
167 } else {
168 m_pPatternEditorLockedBtn->setIsActive( true );
169 m_pPatternEditorUnlockedBtn->setIsActive( true );
170 }
171
172 // Two buttons sharing the same position and either of them is
173 // shown unpressed.
174 m_pPlaySelectedSingleBtn = new Button( pBackPanel, QSize( 25, 21 ),
175 Button::Type::Push, "single_layer.svg",
176 "", false, QSize( 17, 13 ),
177 tr( "selected pattern mode"),
178 false, true );
179 m_pPlaySelectedSingleBtn->move( 168, 25 );
180 connect( m_pPlaySelectedSingleBtn, &QPushButton::clicked, [=]() {
181 activateStackedMode( true );
182 });
183
184 m_pPlaySelectedMultipleBtn = new Button( pBackPanel, QSize( 25, 21 ),
186 "multiple_layers.svg", "", false,
187 QSize( 21, 17 ),
188 tr( "stacked pattern mode"),
189 false, true );
190 m_pPlaySelectedMultipleBtn->move( 168, 25 );
192 connect( m_pPlaySelectedMultipleBtn, &QPushButton::clicked, [=]() {
193 activateStackedMode( false );
194 });
195
196 // We access the raw variable in the song class since we do not
197 // care whether Hydrogen is in song or pattern mode in here.
198 if ( pHydrogen->getSong() == nullptr ||
199 pHydrogen->getSong()->getPatternMode() == Song::PatternMode::Selected ) {
200 m_pPlaySelectedSingleBtn->setVisible( true );
201 m_pPlaySelectedMultipleBtn->setVisible( false );
202 }
203 else {
204 m_pPlaySelectedSingleBtn->setVisible( false );
205 m_pPlaySelectedMultipleBtn->setVisible( true );
206 }
207
208// ZOOM
209 m_pHScrollBar = new QScrollBar( Qt::Horizontal, nullptr );
210 m_pHScrollBar->setObjectName( "SongEditorPanel HScrollBar" );
211 connect( m_pHScrollBar, SIGNAL(valueChanged(int)), this, SLOT( hScrollTo(int) ) );
212
213 // zoom-in btn
214 Button* pZoomInBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "plus.svg", "", false, QSize( 9, 9 ) );
215 connect( pZoomInBtn, SIGNAL( clicked() ), this, SLOT( zoomOutBtnClicked() ) );
216
217
218
219 // zoom-out btn
220 Button* pZoomOutBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Push, "minus.svg", "", false, QSize( 9, 9 ) );
221 connect( pZoomOutBtn, SIGNAL( clicked() ), this, SLOT( zoomInBtnClicked() ) );
222
223 // view playback track toggle button
224 m_pViewPlaybackBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Toggle, "", pCommonStrings->getPlaybackTrackButton(), false, QSize(), tr( "View playback track" ) );
225 m_pViewPlaybackBtn->setObjectName( "ViewPlaybackBtn" );
226 connect( m_pViewPlaybackBtn, SIGNAL( clicked() ), this, SLOT( viewPlaybackTrackBtnClicked() ) );
227 m_pViewPlaybackBtn->setChecked( pPref->getShowPlaybackTrack() );
228
229 // Playback Fader
230 m_pPlaybackTrackFader = new Fader( pBackPanel, Fader::Type::Vertical, tr( "Playback track volume" ), false, false, 0.0, 1.5 );
231 m_pPlaybackTrackFader->setObjectName( "SongEditorPlaybackTrackFader" );
232 m_pPlaybackTrackFader->move( 6, 1 );
233 m_pPlaybackTrackFader->setValue( pSong->getPlaybackTrackVolume() );
234 m_pPlaybackTrackFader->hide();
235 connect( m_pPlaybackTrackFader, SIGNAL( valueChanged( WidgetWithInput* ) ), this, SLOT( faderChanged( WidgetWithInput* ) ) );
236
237 // mute playback track toggle button
238 m_pMutePlaybackBtn = new Button( pBackPanel, QSize( 34, 17 ),
240 pCommonStrings->getBigMuteButton(),
241 true, QSize(), tr( "Mute playback track" ),
242 false, true );
243 m_pMutePlaybackBtn->setObjectName( "SongEditorPlaybackTrackMuteButton" );
244 m_pMutePlaybackBtn->move( 158, 4 );
245 m_pMutePlaybackBtn->hide();
246 connect( m_pMutePlaybackBtn, &QPushButton::clicked, [=](bool bChecked){
248 });
249
251 m_pPlaybackTrackFader->setIsActive( false );
252 m_pMutePlaybackBtn->setChecked( true );
253 m_pMutePlaybackBtn->setIsActive( false );
254 } else {
255 m_pMutePlaybackBtn->setChecked( ! pSong->getPlaybackTrackEnabled() );
256 }
257
258 // edit playback track toggle button
259 m_pEditPlaybackBtn = new Button( pBackPanel, QSize( 34, 17 ), Button::Type::Push, "", pCommonStrings->getEditButton(), false, QSize(), tr( "Choose playback track") );
260 m_pEditPlaybackBtn->setObjectName( "SongEditorPlaybackTrackEditButton" );
261 m_pEditPlaybackBtn->move( 123, 4 );
262 m_pEditPlaybackBtn->hide();
263 connect( m_pEditPlaybackBtn, SIGNAL( clicked() ), this, SLOT( editPlaybackTrackBtnClicked() ) );
264 m_pEditPlaybackBtn->setChecked( false );
265
266 // timeline view toggle button
267 m_pViewTimelineBtn = new Button( nullptr, QSize( 19, 15 ), Button::Type::Toggle, "", pCommonStrings->getTimelineButton(), false, QSize(), tr( "View timeline" ) );
268 m_pViewTimelineBtn->setObjectName( "TimeLineToggleBtn" );
269 connect( m_pViewTimelineBtn, SIGNAL( clicked() ), this, SLOT( viewTimelineBtnClicked() ) );
270 m_pViewTimelineBtn->setChecked( ! pPref->getShowPlaybackTrack() );
271
272
273 QHBoxLayout *pHZoomLayout = new QHBoxLayout();
274 pHZoomLayout->setSpacing( 0 );
275 pHZoomLayout->setContentsMargins( 0, 0, 0, 0 );
276 pHZoomLayout->addWidget( m_pViewPlaybackBtn );
277 pHZoomLayout->addWidget( m_pViewTimelineBtn );
278 pHZoomLayout->addWidget( m_pHScrollBar );
279 pHZoomLayout->addWidget( pZoomInBtn );
280 pHZoomLayout->addWidget( pZoomOutBtn );
281
282 QWidget *pHScrollbarPanel = new QWidget();
283 pHScrollbarPanel->setLayout( pHZoomLayout );
284
286
287 // ~ ZOOM
288
289 // PATTERN LIST
291 m_pPatternListScrollView->setFrameShape( QFrame::NoFrame );
293 m_pPatternListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
294 m_pPatternListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
295 connect( m_pPatternListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( vScrollTo(int) ) );
296
298 m_pPatternList->setFocusPolicy( Qt::ClickFocus );
299 m_pPatternListScrollView->setFocusPolicy( Qt::ClickFocus );
302
303 // EDITOR
304 m_pEditorScrollView = new WidgetScrollArea( nullptr );
305 m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
306 m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
307 m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
310 m_pEditorScrollView->setFocusPolicy( Qt::ClickFocus );
311
312 m_pPatternList->setFocusProxy( m_pSongEditor );
313
314 connect( m_pEditorScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( hScrollTo(int) ) );
315 connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( vScrollTo(int) ) );
316
317
318 // POSITION RULER
319 m_pWidgetStack = new QStackedWidget( nullptr );
320 m_pWidgetStack->setFixedHeight( m_nMinimumHeight );
321
323 m_pPositionRulerScrollView->setFrameShape( QFrame::NoFrame );
324 m_pPositionRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
325 m_pPositionRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
326 m_pPositionRulerScrollView->setFocusPolicy( Qt::NoFocus );
328 m_pPositionRuler->setObjectName( "SongEditorPositionRuler" );
331 connect( m_pPositionRulerScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( hScrollTo(int) ) );
333
334 m_pPositionRuler->setFocusPolicy( Qt::ClickFocus );
335 m_pPositionRuler->setFocusProxy( m_pSongEditor );
336
338 m_pPlaybackTrackScrollView->setFrameShape( QFrame::NoFrame );
339 m_pPlaybackTrackScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
340 m_pPlaybackTrackScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
341
342 auto pCompo = Hydrogen::get_instance()->getAudioEngine()->getSampler()->getPlaybackTrackInstrument()->get_components()->front();
343 assert(pCompo);
344
346 m_pPlaybackTrackWaveDisplay->setSampleNameAlignment( Qt::AlignLeft );
348 m_pPlaybackTrackWaveDisplay->setAcceptDrops( true );
349
352
354 m_pAutomationPathScrollView->setFrameShape( QFrame::NoFrame );
355 m_pAutomationPathScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
356 m_pAutomationPathScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
358 m_pAutomationPathView->setObjectName( "SongEditorAutomationPathView" );
360 m_pAutomationPathScrollView->setFixedHeight(
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->setContentsMargins( 0, 0, 0, 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() *
454 m_pSongEditor->getGridWidth();
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 ) {
476 m_pPatternEditorLockedBtn->setUseRedBackground( 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
552 m_pPatternList->invalidateBackground();
553 m_pPatternList->update();
554
555 m_pSongEditor->invalidateBackground();
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
584 m_pPlaybackTrackFader->setIsActive( false );
585 m_pMutePlaybackBtn->setChecked( true );
586 m_pMutePlaybackBtn->setIsActive( false );
587
588 m_pPlaybackTrackWaveDisplay->updateDisplay( nullptr );
589 }
590 else {
591 // Playback track was selected by the user and is ready to
592 // use.
593 m_pPlaybackTrackFader->setIsActive( true );
594 m_pMutePlaybackBtn->setIsActive( true );
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
611{
612 m_pPositionRuler->invalidateBackground();
613}
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 if ( QMessageBox::information(
689 this, "Hydrogen",
690 tr( "Warning, this will erase your pattern sequence.\nAre you sure?"),
691 QMessageBox::Ok | QMessageBox::Cancel,
692 QMessageBox::Cancel ) == QMessageBox::Cancel ) {
693 return;
694 }
695
696 QString filename = Filesystem::tmp_file_path( "SEQ.xml" );
699
700 pH2App->m_pUndoStack->push( pAction );
701}
702
703
705{
706 auto pHydrogen = Hydrogen::get_instance();
707 auto pAudioEngine = pHydrogen->getAudioEngine();
708 //clear the old sequese
709 std::vector<PatternList*> *pPatternGroupsVect = pHydrogen->getSong()->getPatternGroupVector();
710 for (uint i = 0; i < pPatternGroupsVect->size(); i++) {
711 PatternList *pPatternList = (*pPatternGroupsVect)[i];
712 pPatternList->clear();
713 delete pPatternList;
714 }
715 pPatternGroupsVect->clear();
716
717 pAudioEngine->lock( RIGHT_HERE );
718 pHydrogen->getSong()->readTempPatternList( filename );
719 pHydrogen->updateSongSize();
720 pHydrogen->updateSelectedPattern( false );
721 pAudioEngine->unlock();
722
723 m_pSongEditor->updateEditorandSetTrue();
724 updateAll();
725}
726
727
729{
730 m_pHScrollBar->setMinimum( m_pEditorScrollView->horizontalScrollBar()->minimum() );
731 m_pHScrollBar->setMaximum( m_pEditorScrollView->horizontalScrollBar()->maximum() );
732 m_pHScrollBar->setSingleStep( m_pEditorScrollView->horizontalScrollBar()->singleStep() );
733 m_pHScrollBar->setPageStep( m_pEditorScrollView->horizontalScrollBar()->pageStep() );
734 m_pHScrollBar->setValue( m_pEditorScrollView->horizontalScrollBar()->value() );
735
736 m_pVScrollBar->setMinimum( m_pEditorScrollView->verticalScrollBar()->minimum() );
737 m_pVScrollBar->setMaximum( m_pEditorScrollView->verticalScrollBar()->maximum() );
738 m_pVScrollBar->setSingleStep( m_pEditorScrollView->verticalScrollBar()->singleStep() );
739 m_pVScrollBar->setPageStep( m_pEditorScrollView->verticalScrollBar()->pageStep() );
740 m_pVScrollBar->setValue( m_pEditorScrollView->verticalScrollBar()->value() );
741}
742
743
744void SongEditorPanel::resizeEvent( QResizeEvent *ev )
745{
746 UNUSED( ev );
748}
749
751
752 if ( nValue == 0 ) { // different song opened
756 static_cast<int>(Hydrogen::get_instance()->getJackTimebaseState()) );
757 // Calls patternEditorLockedEvent() internally.
762
764 }
765}
766
770
772
773 auto pHydrogen = Hydrogen::get_instance();
774 if ( pHydrogen->getMode() == Song::Mode::Song ) {
775 m_pPatternEditorLockedBtn->setIsActive( true );
776 m_pPatternEditorUnlockedBtn->setIsActive( true );
777 }
778
779 if ( pHydrogen->isPatternEditorLocked() ) {
782
783 if ( pHydrogen->getAudioEngine()->getState() ==
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 ) {
796 m_pPatternEditorLockedBtn->setIsActive( false );
797 m_pPatternEditorUnlockedBtn->setIsActive( false );
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
952{
953 unsigned width = m_pSongEditor->getGridWidth();
954 --width;
955 m_pSongEditor->setGridWidth( width );
956 m_pPositionRuler->setGridWidth( width );
957 m_pAutomationPathView->setGridWidth( width );
958
961
962 updateAll();
963}
964
965
967{
968 unsigned width = m_pSongEditor->getGridWidth();
969 ++width;
970 m_pSongEditor->setGridWidth( width );
971 m_pPositionRuler->setGridWidth( width );
972 m_pAutomationPathView->setGridWidth( width );
973
976
977 updateAll();
978}
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
1019{
1020 H2Core::AutomationPath *pPath = m_pAutomationPathView->getAutomationPath();
1022 HydrogenApp::get_instance()->m_pUndoStack->push( pUndoAction );
1023}
1024
1025
1027{
1028 H2Core::AutomationPath *pPath = m_pAutomationPathView->getAutomationPath();
1030 HydrogenApp::get_instance()->m_pUndoStack->push( pUndoAction );
1031}
1032
1033
1034void SongEditorPanel::automationPathPointMoved(float ox, float oy, float tx, float ty)
1035{
1036 H2Core::AutomationPath *pPath = m_pAutomationPathView->getAutomationPath();
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 const auto state = JackAudioDriver::TimebaseFromInt( nState );
1062 if ( state == JackAudioDriver::Timebase::Listener ) {
1063 setTimelineEnabled( false );
1064 m_pTimelineBtn->setToolTip(
1065 pCommonStrings->getTimelineDisabledTimebaseListener() );
1066 } else if ( pHydrogen->getMode() != Song::Mode::Pattern ) {
1067 setTimelineEnabled( true );
1068 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineEnabled() );
1069 }
1070}
1071
1073 auto pHydrogen = Hydrogen::get_instance();
1074 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1075 if ( pHydrogen->getMode() == Song::Mode::Pattern ) {
1076 setTimelineEnabled( false );
1077 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineDisabledPatternMode() );
1078
1079 } else if ( pHydrogen->getJackTimebaseState() != JackAudioDriver::Timebase::Listener ) {
1080 setTimelineEnabled( true );
1081 m_pTimelineBtn->setToolTip( pCommonStrings->getTimelineEnabled() );
1082
1083 }
1084
1086
1087 // Set disabled or enabled
1088 if ( Hydrogen::get_instance()->getMode() == Song::Mode::Song ) {
1089 m_pPlaySelectedMultipleBtn->setDisabled( true );
1090 m_pPlaySelectedSingleBtn->setDisabled( true );
1091 } else {
1092 m_pPlaySelectedMultipleBtn->setDisabled( false );
1093 m_pPlaySelectedSingleBtn->setDisabled( false );
1094 }
1095}
1096
1098 auto pHydrogen = Hydrogen::get_instance();
1099 if ( ! pHydrogen->isTimelineEnabled() && m_pTimelineBtn->isChecked() ) {
1100 setTimelineActive( false );
1101 } else if ( pHydrogen->isTimelineEnabled() && ! m_pTimelineBtn->isChecked() ) {
1102 setTimelineActive( true );
1103 }
1104}
1105
1107 return m_pTimelineBtn->isChecked();
1108}
1109
1111 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1112
1113 if ( ! m_pTimelineBtn->isDown() ) {
1114 m_pTimelineBtn->setChecked( bActive );
1115 }
1116
1118
1119 QString sMessage = QString( "%1 = %2" )
1120 .arg( pCommonStrings->getTimelineBigButton() )
1121 .arg( bActive ? pCommonStrings->getStatusOn() : pCommonStrings->getStatusOff() );
1123}
1124
1126 return m_pTimelineBtn->getIsActive();
1127}
1128
1130 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
1131
1132 if ( bEnabled ) {
1133 m_pTimelineBtn->setIsActive( true );
1134 // setTimelineActive( m_bLastIsTimelineActivated );
1135 } else {
1136 m_bLastIsTimelineActivated = Hydrogen::get_instance()->getSong()->getIsTimelineActivated();
1137 if ( m_pTimelineBtn->isChecked() ) {
1138 // setTimelineActive( false );
1139 }
1140 m_pTimelineBtn->setIsActive( false );
1141 }
1142
1143 QString sMessage = QString( "%1 = %2" )
1144 .arg( pCommonStrings->getTimelineBigButton() )
1145 .arg( bEnabled ? pCommonStrings->getStatusEnabled() :
1146 pCommonStrings->getStatusDisabled() );
1148}
1149
1153
1155 // Triggered every time the column of the SongEditor grid
1156 // changed. Either by rolling transport or by relocation.
1157 // In Song mode, we may scroll to change position in the Song Editor.
1158 auto pHydrogen = Hydrogen::get_instance();
1159 auto pPref = Preferences::get_instance();
1160 if ( pHydrogen->getMode() == Song::Mode::Song ) {
1161
1162 // Scroll vertically to keep currently playing patterns in view
1163 int nPatternInView = -1;
1164 int scroll = m_pSongEditor->yScrollTarget( m_pEditorScrollView, &nPatternInView );
1165 vScrollTo( scroll );
1166 }
1167}
1168
1170 auto pHydrogen = Hydrogen::get_instance();
1171 if ( bActive ) {
1172 pHydrogen->setPatternMode( Song::PatternMode::Stacked );
1173 }
1174 else {
1175 pHydrogen->setPatternMode( Song::PatternMode::Selected );
1176 }
1177}
1178
1180 auto pHydrogen = Hydrogen::get_instance();
1181
1182 // Already reset them in here in order to avoid visual glitches.
1183 m_pSelectionModeBtn->setChecked( false );
1184 m_pDrawModeBtn->setChecked( false );
1185
1186 if ( bActivate ) {
1187 pHydrogen->setActionMode( H2Core::Song::ActionMode::drawMode );
1188 }
1189 else {
1190 pHydrogen->setActionMode( H2Core::Song::ActionMode::selectMode );
1191 }
1192}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:61
This dialog is used to preview audiofiles.
QStringList getSelectedFiles()
static constexpr int m_nMinimumHeight
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 fader widget.
Definition Fader.h:44
@ Vertical
Only used for the playback track in the SongEditorPanel.
Definition Fader.h:51
@ 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:123
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:245
Song::Mode getMode() const
int getSelectedPatternNumber() const
Definition Hydrogen.h:674
void mutePlaybackTrack(const bool bMuted)
Wrapper around Song::setPlaybackTrackEnabled().
Definition Hydrogen.cpp:255
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
void setIsPatternEditorLocked(bool bValue)
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:663
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...
@ Listener
An external program is Timebase controller and Hydrogen will disregard all tempo markers on the Timel...
static Timebase TimebaseFromInt(int nState)
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:79
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:207
@ selectMode
Holding a pressed left mouse key will draw a rectangle to select a group of Notes.
Definition Song.h:77
@ drawMode
Holding a pressed left mouse key will draw/delete patterns in all grid cells encountered.
Definition Song.h:80
@ Unavailable
No proper playback track file set yet.
Definition Song.h:117
@ Muted
Valid file set but the playback track is muted via the GUI.
Definition Song.h:119
@ Stacked
An arbitrary number of pattern can be played.
Definition Song.h:103
@ Selected
Only one pattern - the one currently selected in the GUI - will be played back.
Definition Song.h:106
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.
Pattern Properties Dialog.
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
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
static constexpr int m_nMinimumHeight
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
virtual void jackTimebaseStateChangedEvent(int nState) override
void automationPathPointAdded(float x, float y)
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:270
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void onPreferencesChanged(H2Core::Preferences::Changes changes)
Song editor.
Definition SongEditor.h:72
Base class for active user input widget, which are not based on a high-level Qt widget.
float getValue() const
#define UNUSED(v)
Definition Globals.h:42