1 /*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23 #include <hydrogen/Preferences.h>
24 #include <hydrogen/hydrogen.h>
25 #include <hydrogen/basics/instrument.h>
26 #include <hydrogen/basics/instrument_list.h>
27 #include <hydrogen/basics/pattern.h>
28 #include <hydrogen/basics/pattern_list.h>
29 #include <hydrogen/audio_engine.h>
30 #include <hydrogen/event_queue.h>
31 using namespace H2Core;
32
33
34 #include "HydrogenApp.h"
35 #include "PatternEditorPanel.h"
36 #include "PatternEditorInstrumentList.h"
37 #include "PatternEditorRuler.h"
38 #include "NotePropertiesRuler.h"
39 #include "DrumPatternEditor.h"
40 #include "PianoRollEditor.h"
41
42 #include "../MainForm.h"
43 #include "../Widgets/Button.h"
44 #include "../Widgets/Fader.h"
45 #include "../Widgets/PixmapWidget.h"
46 #include "../Widgets/LCDCombo.h"
47
48 #include "../Skin.h"
49 #include "../SongEditor/SongEditorPanel.h"
50
51 #include <cmath>
52
53
updateSLnameLabel()54 void PatternEditorPanel::updateSLnameLabel( )
55 {
56 QFont font;
57 font.setBold( true );
58 pSLlabel->setFont( font );
59 pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit );
60 }
61
62 const char* PatternEditorPanel::__class_name = "PatternEditorPanel";
63
64
PatternEditorPanel(QWidget * pParent)65 PatternEditorPanel::PatternEditorPanel( QWidget *pParent )
66 : QWidget( pParent )
67 , Object( __class_name )
68 , m_pPattern( nullptr )
69 {
70 setAcceptDrops(true);
71
72 Preferences *pPref = Preferences::get_instance();
73
74
75 // Editor TOP
76 PixmapWidget *editor_top = new PixmapWidget(nullptr);
77 editor_top->setPixmap("/patternEditor/editor_top.png", true);
78 editor_top->setFixedHeight(24);
79
80 PixmapWidget *editor_top_2 = new PixmapWidget(nullptr);
81 editor_top_2->setPixmap("/patternEditor/editor_top.png", true);
82 editor_top_2->setFixedHeight(24);
83
84 QHBoxLayout *editor_top_hbox = new QHBoxLayout(editor_top);
85 editor_top_hbox->setSpacing(0);
86 editor_top_hbox->setMargin(0);
87 editor_top_hbox->setAlignment(Qt::AlignLeft);
88
89 QHBoxLayout *editor_top_hbox_2 = new QHBoxLayout(editor_top_2);
90 editor_top_hbox_2->setSpacing(0);
91 editor_top_hbox_2->setMargin(0);
92 editor_top_hbox_2->setAlignment(Qt::AlignLeft);
93
94
95 //soundlibrary name
96 pSLlabel = new QLabel( nullptr );
97 pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit );
98 pSLlabel->setFixedSize( 170, 20 );
99 pSLlabel->move( 10, 3 );
100 pSLlabel->setToolTip( tr("Loaded Soundlibrary") );
101 editor_top_hbox->addWidget( pSLlabel );
102
103 //wolke some background images back_size_res
104 PixmapWidget *pSizeResol = new PixmapWidget( nullptr );
105 pSizeResol->setFixedSize( 200, 20 );
106 pSizeResol->setPixmap( "/patternEditor/background_res-new.png" );
107 pSizeResol->move( 0, 3 );
108 editor_top_hbox_2->addWidget( pSizeResol );
109
110 // PATTERN size
111 __pattern_size_combo = new LCDCombo(pSizeResol, 4);
112 __pattern_size_combo->move( 34, 2 );
113 __pattern_size_combo->setToolTip( tr("Select pattern size") );
114 for ( int i = 1; i <= 32; i++) {
115 __pattern_size_combo->addItem( QString( "%1" ).arg( i ) );
116 }
117 // is triggered from inside selectedPatternChangedEvent()
118 connect(__pattern_size_combo, SIGNAL( valueChanged( int ) ), this, SLOT( patternSizeChanged( int ) ) );
119
120
121 // GRID resolution
122 __resolution_combo = new LCDCombo( pSizeResol , 7);
123 __resolution_combo->setToolTip(tr("Select grid resolution"));
124 __resolution_combo->addItem( "4" );
125 __resolution_combo->addItem( "8" );
126 __resolution_combo->addItem( "16" );
127 __resolution_combo->addItem( "32" );
128 __resolution_combo->addItem( "64" );
129 __resolution_combo->addSeparator();
130 __resolution_combo->addItem( "4T" );
131 __resolution_combo->addItem( "8T" );
132 __resolution_combo->addItem( "16T" );
133 __resolution_combo->addItem( "32T" );
134 __resolution_combo->addSeparator();
135 __resolution_combo->addItem( "off" );
136 __resolution_combo->move( 121, 2 );
137 // is triggered from inside PatternEditorPanel()
138 connect(__resolution_combo, SIGNAL(valueChanged( int )), this, SLOT(gridResolutionChanged( int )));
139
140
141 PixmapWidget *pRec = new PixmapWidget( nullptr );
142 pRec->setFixedSize( 158, 20 );
143 pRec->setPixmap( "/patternEditor/background_rec-new.png" );
144 pRec->move( 0, 3 );
145 editor_top_hbox_2->addWidget( pRec );
146
147
148 // Hear notes btn
149 ToggleButton *hearNotesBtn = new ToggleButton(
150 pRec,
151 "/patternEditor/btn_hear_on.png",
152 "/patternEditor/btn_hear_off.png",
153 "/patternEditor/btn_hear_off.png",
154 QSize(15, 13)
155 );
156 hearNotesBtn->move( 34, 3 );
157 hearNotesBtn->setToolTip( tr( "Hear new notes" ) );
158 connect( hearNotesBtn, SIGNAL(clicked(Button*)), this, SLOT( hearNotesBtnClick(Button*)));
159 hearNotesBtn->setPressed( pPref->getHearNewNotes() );
160
161
162 // quantize
163 ToggleButton* quantizeEventsBtn = new ToggleButton(
164 pRec,
165 "/patternEditor/btn_quant_on.png",
166 "/patternEditor/btn_quant_off.png",
167 "/patternEditor/btn_quant_off.png",
168 QSize(15, 13)
169 );
170 quantizeEventsBtn->move( 90, 3 );
171 quantizeEventsBtn->setPressed( pPref->getQuantizeEvents());
172 quantizeEventsBtn->setToolTip( tr( "Quantize keyboard/midi events to grid" ) );
173 connect( quantizeEventsBtn, SIGNAL(clicked(Button*)), this, SLOT( quantizeEventsBtnClick(Button*)));
174
175 // Editor mode
176 __show_drum_btn = new ToggleButton(
177 pRec,
178 "/patternEditor/btn_drum_piano_on.png",
179 "/patternEditor/btn_drum_piano_off.png",
180 "/patternEditor/btn_drum_piano_off.png",
181 QSize(17, 13)
182 );
183 __show_drum_btn->move( 137, 3 );
184 __show_drum_btn->setPressed( false );
185 __show_drum_btn->setToolTip( tr( "Show piano roll editor" ) );
186 connect(__show_drum_btn, SIGNAL(clicked(Button*)), this, SLOT( showDrumEditorBtnClick(Button*)));
187
188 __recpredelete = new QComboBox( nullptr );
189 __recpredelete->setFixedSize( 130, 20 );
190 __recpredelete->move( 2, 1 );
191 __recpredelete->addItem ( QString( "On play" ));
192 __recpredelete->addItem ( QString( "On rec: once fp" ));
193 __recpredelete->addItem ( QString( "On rec: 1/1 fp" ));
194 __recpredelete->addItem ( QString( "On rec: 1/2 fp" ));
195 __recpredelete->addItem ( QString( "On rec: 1/4 fp" ));
196 __recpredelete->addItem ( QString( "On rec: 1/8 fp" ));
197 __recpredelete->addItem ( QString( "On rec: 1/16 fp" ));
198 __recpredelete->addItem ( QString( "On rec: 1/32 fp" ));
199 __recpredelete->addItem ( QString( "On rec: 1/64 fp" ));
200 __recpredelete->addItem ( QString( "On rec: 1/64" ));
201 __recpredelete->addItem ( QString( "On rec: 1/32" ));
202 __recpredelete->addItem ( QString( "On rec: 1/16" ));
203 __recpredelete->addItem ( QString( "On rec: 1/8" ));
204 __recpredelete->addItem ( QString( "On rec: 1/4" ));
205 __recpredelete->addItem ( QString( "On rec: 1/2" ));
206 __recpredelete->addItem ( QString( "On rec: 1/1" ));
207 __recpredelete->addItem ( QString( "On rec: once" ));
208 __recpredelete->update();
209 __recpredelete->setToolTip( tr( "destructive mode pre delete settings" ) );
210 editor_top_hbox_2->addWidget( __recpredelete );
211 connect( __recpredelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPreDeleteSelect( int) ) );
212
213 __recpostdelete = new QComboBox( nullptr );
214 __recpostdelete->setFixedSize( 60, 20 );
215 __recpostdelete->move( 2, 1 );
216 __recpostdelete->addItem ( QString( "off" ));
217 __recpostdelete->addItem ( QString( "1/64" ));
218 __recpostdelete->addItem ( QString( "1/32" ));
219 __recpostdelete->addItem ( QString( "1/16" ));
220 __recpostdelete->addItem ( QString( "1/8" ));
221 __recpostdelete->addItem ( QString( "1/4" ));
222 __recpostdelete->addItem ( QString( "1/2" ));
223 __recpostdelete->addItem ( QString( "1/1" ));
224 __recpostdelete->update();
225 __recpostdelete->setToolTip( tr( "destructive mode post delete settings" ) );
226 editor_top_hbox_2->addWidget( __recpostdelete );
227 connect( __recpostdelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPostDeleteSelect( int) ) );
228
229
230 // zoom-in btn
231 Button *zoom_in_btn = new Button(
232 nullptr,
233 "/songEditor/btn_new_on.png",
234 "/songEditor/btn_new_off.png",
235 "/songEditor/btn_new_over.png",
236 QSize(19, 13)
237 );
238 zoom_in_btn->setToolTip( tr( "Zoom in" ) );
239 connect(zoom_in_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomInBtnClicked(Button*) ) );
240
241
242 // zoom-out btn
243 Button *zoom_out_btn = new Button(
244 nullptr,
245 "/songEditor/btn_minus_on.png",
246 "/songEditor/btn_minus_off.png",
247 "/songEditor/btn_minus_over.png",
248 QSize(19, 13)
249 );
250 zoom_out_btn->setToolTip( tr( "Zoom out" ) );
251 connect( zoom_out_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomOutBtnClicked(Button*) ) );
252
253
254 // End Editor TOP
255
256
257 // RULER____________________________________
258
259 // Ruler ScrollView
260 m_pRulerScrollView = new QScrollArea( nullptr );
261 m_pRulerScrollView->setFrameShape( QFrame::NoFrame );
262 m_pRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
263 m_pRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
264 m_pRulerScrollView->setFixedHeight( 25 );
265 // Ruler
266 m_pPatternEditorRuler = new PatternEditorRuler( m_pRulerScrollView->viewport() );
267
268 m_pRulerScrollView->setWidget( m_pPatternEditorRuler );
269 connect( m_pRulerScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
270
271 //~ RULER
272
273
274 // EDITOR _____________________________________
275 // Editor scrollview
276 m_pEditorScrollView = new QScrollArea( nullptr );
277 m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
278 m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
279 m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
280
281
282 // Editor
283 m_pDrumPatternEditor = new DrumPatternEditor( m_pEditorScrollView->viewport(), this );
284
285 m_pEditorScrollView->setWidget( m_pDrumPatternEditor );
286
287 connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorVScroll(int) ) );
288 connect( m_pEditorScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
289
290
291 //PianoRollEditor
292 m_pPianoRollScrollView = new QScrollArea( nullptr );
293 m_pPianoRollScrollView->setFrameShape( QFrame::NoFrame );
294 m_pPianoRollScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
295 m_pPianoRollScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
296 m_pPianoRollEditor = new PianoRollEditor( m_pPianoRollScrollView->viewport(), this );
297 m_pPianoRollScrollView->setWidget( m_pPianoRollEditor );
298 connect( m_pPianoRollScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
299
300 m_pPianoRollScrollView->hide();
301
302 //~ EDITOR
303
304
305
306
307
308
309 // INSTRUMENT LIST
310 // Instrument list scrollview
311 m_pInstrListScrollView = new QScrollArea( nullptr );
312 m_pInstrListScrollView->setFrameShape( QFrame::NoFrame );
313 m_pInstrListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
314 m_pInstrListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
315
316 // Instrument list
317 m_pInstrumentList = new PatternEditorInstrumentList( m_pInstrListScrollView->viewport(), this );
318 m_pInstrListScrollView->setWidget( m_pInstrumentList );
319 m_pInstrListScrollView->setFixedWidth( m_pInstrumentList->width() );
320
321 connect( m_pInstrListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorVScroll(int) ) );
322 //~ INSTRUMENT LIST
323
324
325
326
327 // NOTE_VELOCITY EDITOR
328 m_pNoteVelocityScrollView = new QScrollArea( nullptr );
329 m_pNoteVelocityScrollView->setFrameShape( QFrame::NoFrame );
330 m_pNoteVelocityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
331 m_pNoteVelocityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
332 m_pNoteVelocityEditor = new NotePropertiesRuler( m_pNoteVelocityScrollView->viewport(), this, NotePropertiesRuler::VELOCITY );
333 m_pNoteVelocityScrollView->setWidget( m_pNoteVelocityEditor );
334 m_pNoteVelocityScrollView->setFixedHeight( 100 );
335 connect( m_pNoteVelocityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
336
337 //~ NOTE_VELOCITY EDITOR
338
339
340 // NOTE_PAN EDITOR
341 m_pNotePanScrollView = new QScrollArea( nullptr );
342 m_pNotePanScrollView->setFrameShape( QFrame::NoFrame );
343 m_pNotePanScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
344 m_pNotePanScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
345 m_pNotePanEditor = new NotePropertiesRuler( m_pNotePanScrollView->viewport(), this, NotePropertiesRuler::PAN );
346 m_pNotePanScrollView->setWidget( m_pNotePanEditor );
347 m_pNotePanScrollView->setFixedHeight( 100 );
348 connect( m_pNotePanScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
349 //~ NOTE_PAN EDITOR
350
351
352 // NOTE_LEADLAG EDITOR
353 m_pNoteLeadLagScrollView = new QScrollArea( nullptr );
354 m_pNoteLeadLagScrollView->setFrameShape( QFrame::NoFrame );
355 m_pNoteLeadLagScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
356 m_pNoteLeadLagScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
357 m_pNoteLeadLagEditor = new NotePropertiesRuler( m_pNoteLeadLagScrollView->viewport(), this, NotePropertiesRuler::LEADLAG );
358 m_pNoteLeadLagScrollView->setWidget( m_pNoteLeadLagEditor );
359 m_pNoteLeadLagScrollView->setFixedHeight( 100 );
360 connect( m_pNoteLeadLagScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
361 //~ NOTE_LEADLAG EDITOR
362
363
364 // NOTE_NOTEKEY EDITOR
365
366
367 m_pNoteNoteKeyScrollView = new QScrollArea( nullptr );
368 m_pNoteNoteKeyScrollView->setFrameShape( QFrame::NoFrame );
369 m_pNoteNoteKeyScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
370 m_pNoteNoteKeyScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
371 m_pNoteNoteKeyEditor = new NotePropertiesRuler( m_pNoteNoteKeyScrollView->viewport(), this, NotePropertiesRuler::NOTEKEY );
372 m_pNoteNoteKeyScrollView->setWidget( m_pNoteNoteKeyEditor );
373 m_pNoteNoteKeyScrollView->setFixedHeight( 210 );
374 connect( m_pNoteNoteKeyScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
375
376
377 //~ NOTE_NOTEKEY EDITOR
378
379 // NOTE_PROBABILITY EDITOR
380 m_pNoteProbabilityScrollView = new QScrollArea( nullptr );
381 m_pNoteProbabilityScrollView->setFrameShape( QFrame::NoFrame );
382 m_pNoteProbabilityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
383 m_pNoteProbabilityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
384 m_pNoteProbabilityEditor = new NotePropertiesRuler( m_pNoteProbabilityScrollView->viewport(), this, NotePropertiesRuler::PROBABILITY );
385 m_pNoteProbabilityScrollView->setWidget( m_pNoteProbabilityEditor );
386 m_pNoteProbabilityScrollView->setFixedHeight( 100 );
387 connect( m_pNoteProbabilityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
388 //~ NOTE_PROBABILITY EDITOR
389
390
391
392 // external horizontal scrollbar
393 m_pPatternEditorHScrollBar = new QScrollBar( Qt::Horizontal , nullptr );
394 connect( m_pPatternEditorHScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
395
396 // external vertical scrollbar
397 m_pPatternEditorVScrollBar = new QScrollBar( Qt::Vertical, nullptr );
398 connect( m_pPatternEditorVScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
399
400 QHBoxLayout *pPatternEditorHScrollBarLayout = new QHBoxLayout();
401 pPatternEditorHScrollBarLayout->setSpacing( 0 );
402 pPatternEditorHScrollBarLayout->setMargin( 0 );
403 pPatternEditorHScrollBarLayout->addWidget( m_pPatternEditorHScrollBar );
404 pPatternEditorHScrollBarLayout->addWidget( zoom_in_btn );
405 pPatternEditorHScrollBarLayout->addWidget( zoom_out_btn );
406
407 QWidget *pPatternEditorHScrollBarContainer = new QWidget();
408 pPatternEditorHScrollBarContainer->setLayout( pPatternEditorHScrollBarLayout );
409
410
411 QPalette label_palette;
412 label_palette.setColor( QPalette::Foreground, QColor( 230, 230, 230 ) );
413
414 QFont boldFont;
415 boldFont.setBold( true );
416 m_pPatternNameLbl = new QLabel( nullptr );
417 m_pPatternNameLbl->setFont( boldFont );
418 m_pPatternNameLbl->setText( "pattern name label" );
419 m_pPatternNameLbl->setPalette(label_palette);
420
421
422
423
424
425
426 // NOTE_PROPERTIES BUTTONS
427 PixmapWidget *pPropertiesPanel = new PixmapWidget( nullptr );
428 pPropertiesPanel->setColor( QColor( 58, 62, 72 ) );
429
430 pPropertiesPanel->setFixedSize( 181, 100 );
431
432 QVBoxLayout *pPropertiesVBox = new QVBoxLayout( pPropertiesPanel );
433 pPropertiesVBox->setSpacing( 0 );
434 pPropertiesVBox->setMargin( 0 );
435
436
437 __pPropertiesCombo = new LCDCombo( nullptr, 20);
438 __pPropertiesCombo->setToolTip(tr("Select note properties"));
439 __pPropertiesCombo->addItem( tr("Velocity") );
440 __pPropertiesCombo->addItem( tr("Pan") );
441 __pPropertiesCombo->addItem( tr("Lead and Lag") );
442 __pPropertiesCombo->addItem( tr("NoteKey") );
443 __pPropertiesCombo->addItem( tr("Probability") );
444 /* __pPropertiesCombo->addItem( tr("Cutoff") ); */
445 /* __pPropertiesCombo->addItem( tr("Resonance") ); */
446 // is triggered here below
447 connect( __pPropertiesCombo, SIGNAL(valueChanged( int )), this, SLOT(propertiesComboChanged( int )));
448
449 pPropertiesVBox->addWidget( __pPropertiesCombo );
450
451 //~ NOTE_PROPERTIES BUTTONS
452
453
454 // LAYOUT
455 QWidget *pMainPanel = new QWidget();
456
457 QGridLayout *pGrid = new QGridLayout();
458 pGrid->setSpacing( 0 );
459 pGrid->setMargin( 0 );
460
461 pGrid->addWidget( editor_top, 0, 0);
462 pGrid->addWidget( editor_top_2, 0, 1, 1, 3);
463 pGrid->addWidget( m_pPatternNameLbl, 1, 0 );
464 pGrid->addWidget( m_pRulerScrollView, 1, 1 );
465
466 pGrid->addWidget( m_pInstrListScrollView, 2, 0 );
467
468 pGrid->addWidget( m_pEditorScrollView, 2, 1 );
469 pGrid->addWidget( m_pPianoRollScrollView, 2, 1 );
470
471 pGrid->addWidget( m_pPatternEditorVScrollBar, 2, 2 );
472 pGrid->addWidget( pPatternEditorHScrollBarContainer, 10, 1 );
473 pGrid->addWidget( m_pNoteVelocityScrollView, 4, 1 );
474 pGrid->addWidget( m_pNotePanScrollView, 4, 1 );
475 pGrid->addWidget( m_pNoteLeadLagScrollView, 4, 1 );
476 pGrid->addWidget( m_pNoteNoteKeyScrollView, 4, 1 );
477 pGrid->addWidget( m_pNoteProbabilityScrollView, 4, 1 );
478
479 pGrid->addWidget( pPropertiesPanel, 4, 0 );
480 pGrid->setRowStretch( 2, 100 );
481 pMainPanel->setLayout( pGrid );
482
483
484 // restore grid resolution
485 int nIndex;
486 int nRes = pPref->getPatternEditorGridResolution();
487 if (nRes == MAX_NOTES) {
488 nIndex = 11;
489 } else if ( pPref->isPatternEditorUsingTriplets() == false ) {
490 switch ( nRes ) {
491 case 4: nIndex = 0; break;
492 case 8: nIndex = 1; break;
493 case 16: nIndex = 2; break;
494 case 32: nIndex = 3; break;
495 case 64: nIndex = 4; break;
496 default:
497 nIndex = 0;
498 ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
499 }
500 } else {
501 switch ( nRes ) {
502 case 8: nIndex = 6; break;
503 case 16: nIndex = 7; break;
504 case 32: nIndex = 8; break;
505 case 64: nIndex = 9; break;
506 default:
507 nIndex = 6;
508 ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
509 }
510 }
511 __resolution_combo->select( nIndex );
512
513 //set pre delete
514 __recpredelete->setCurrentIndex(pPref->m_nRecPreDelete);
515 __recpostdelete->setCurrentIndex(pPref->m_nRecPostDelete);
516 displayorHidePrePostCB();
517
518 // LAYOUT
519 QVBoxLayout *pVBox = new QVBoxLayout();
520 pVBox->setSpacing( 0 );
521 pVBox->setMargin( 0 );
522 this->setLayout( pVBox );
523
524 pVBox->addWidget( pMainPanel );
525
526 HydrogenApp::get_instance()->addEventListener( this );
527
528 // update
529 __pPropertiesCombo->select( 0 );
530 selectedPatternChangedEvent();
531 }
532
533
534
535
~PatternEditorPanel()536 PatternEditorPanel::~PatternEditorPanel()
537 {
538 }
539
540
541
syncToExternalHorizontalScrollbar(int)542 void PatternEditorPanel::syncToExternalHorizontalScrollbar(int)
543 {
544 //INFOLOG( "[syncToExternalHorizontalScrollbar]" );
545
546 // drum Editor
547 m_pEditorScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
548 m_pEditorScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
549
550 // piano roll Editor
551 m_pPianoRollScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
552
553 // Ruler
554 m_pRulerScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
555
556 // Instrument list
557 m_pInstrListScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
558
559 // Velocity ruler
560 m_pNoteVelocityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
561
562 // pan ruler
563 m_pNotePanScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
564
565 // leadlag ruler
566 m_pNoteLeadLagScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
567
568 // notekey ruler
569 m_pNoteNoteKeyScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
570
571 // Probability ruler
572 m_pNoteProbabilityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
573 }
574
575
on_patternEditorVScroll(int nValue)576 void PatternEditorPanel::on_patternEditorVScroll(int nValue)
577 {
578 //INFOLOG( "[on_patternEditorVScroll] " + QString::number(nValue) );
579 m_pPatternEditorVScrollBar->setValue( nValue );
580 resizeEvent(nullptr);
581 }
582
on_patternEditorHScroll(int nValue)583 void PatternEditorPanel::on_patternEditorHScroll(int nValue)
584 {
585 //INFOLOG( "[on_patternEditorHScroll] " + QString::number(nValue) );
586 m_pPatternEditorHScrollBar->setValue( nValue );
587 resizeEvent(nullptr);
588 }
589
590
591
592
gridResolutionChanged(int nSelected)593 void PatternEditorPanel::gridResolutionChanged( int nSelected )
594 {
595 int nResolution;
596 bool bUseTriplets = false;
597
598 if ( nSelected == 11 ) {
599 nResolution = MAX_NOTES;
600 }
601 else if ( nSelected > 4 ) {
602 bUseTriplets = true;
603 nResolution = 0x1 << (nSelected - 3);
604 }
605 else {
606 nResolution = 0x1 << (nSelected + 2);
607 }
608
609 // INFOLOG( QString("idx %1 -> %2 resolution").arg( nSelected ).arg( nResolution ) );
610 m_pDrumPatternEditor->setResolution( nResolution, bUseTriplets );
611 m_pPianoRollEditor->setResolution( nResolution, bUseTriplets );
612
613 Preferences::get_instance()->setPatternEditorGridResolution( nResolution );
614 Preferences::get_instance()->setPatternEditorUsingTriplets( bUseTriplets );
615 }
616
617
618
selectedPatternChangedEvent()619 void PatternEditorPanel::selectedPatternChangedEvent()
620 {
621 PatternList *pPatternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
622 int nSelectedPatternNumber = Hydrogen::get_instance()->getSelectedPatternNumber();
623
624 if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->size() ) ) {
625 // update pattern name text
626 m_pPattern = pPatternList->get( nSelectedPatternNumber );
627 QString sCurrentPatternName = m_pPattern->get_name();
628 this->setWindowTitle( ( tr( "Pattern editor - %1").arg( sCurrentPatternName ) ) );
629 m_pPatternNameLbl->setText( sCurrentPatternName );
630
631 // update pattern size combobox
632 int nPatternSize = m_pPattern->get_length();
633 int nEighth = MAX_NOTES / 8;
634
635 // do no emit the changed value, otherwise patternSizeChanged() would be triggered,
636 // which handles a manual pattern size change
637 __pattern_size_combo->select( (nPatternSize / nEighth) - 1 , false);
638 }
639 else {
640 m_pPattern = nullptr;
641
642 this->setWindowTitle( ( tr( "Pattern editor - %1").arg(QString("No pattern selected.")) ) );
643 m_pPatternNameLbl->setText( tr( "No pattern selected" ) );
644 }
645
646 resizeEvent( nullptr ); // force an update of the scrollbars
647 }
648
649
650
hearNotesBtnClick(Button * ref)651 void PatternEditorPanel::hearNotesBtnClick(Button *ref)
652 {
653 Preferences *pref = ( Preferences::get_instance() );
654 pref->setHearNewNotes( ref->isPressed() );
655
656 if (ref->isPressed() ) {
657 ( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Hear new notes = On" ), 2000 );
658 }
659 else {
660 ( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Hear new notes = Off" ), 2000 );
661 }
662
663 }
664
quantizeEventsBtnClick(Button * ref)665 void PatternEditorPanel::quantizeEventsBtnClick(Button *ref)
666 {
667 Preferences *pref = ( Preferences::get_instance() );
668 pref->setQuantizeEvents( ref->isPressed() );
669
670 if (ref->isPressed() ) {
671 ( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Quantize incoming keyboard/midi events = On" ), 2000 );
672 }
673 else {
674 ( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Quantize incoming keyboard/midi events = Off" ), 2000 );
675 }
676 }
677
syncScrollBarSize(QScrollBar * pDest,QScrollBar * pSrc)678 static void syncScrollBarSize(QScrollBar *pDest, QScrollBar *pSrc)
679 {
680 pDest->setMinimum( pSrc->minimum() );
681 pDest->setMaximum( pSrc->maximum() );
682 pDest->setSingleStep( pSrc->singleStep() );
683 pDest->setPageStep( pSrc->pageStep() );
684 }
685
resizeEvent(QResizeEvent * ev)686 void PatternEditorPanel::resizeEvent( QResizeEvent *ev )
687 {
688 UNUSED( ev );
689 QScrollArea *pScrollArea = m_pEditorScrollView;
690
691 syncScrollBarSize( m_pPatternEditorHScrollBar, pScrollArea->horizontalScrollBar() );
692 syncScrollBarSize( m_pPatternEditorVScrollBar, pScrollArea->verticalScrollBar() );
693
694 syncScrollBarSize( m_pRulerScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
695 syncScrollBarSize( m_pNoteVelocityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
696 syncScrollBarSize( m_pNotePanScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
697 syncScrollBarSize( m_pNoteLeadLagScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar()) ;
698 syncScrollBarSize( m_pNoteNoteKeyScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
699 syncScrollBarSize( m_pNoteProbabilityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
700 }
701
showEvent(QShowEvent * ev)702 void PatternEditorPanel::showEvent ( QShowEvent *ev )
703 {
704 UNUSED( ev );
705 }
706
707
708 /// richiamato dall'uso dello scroll del mouse
contentsMoving(int dummy)709 void PatternEditorPanel::contentsMoving(int dummy)
710 {
711 UNUSED( dummy );
712 //INFOLOG( "contentsMoving" );
713 syncToExternalHorizontalScrollbar(0);
714 }
715
716
717
selectedInstrumentChangedEvent()718 void PatternEditorPanel::selectedInstrumentChangedEvent()
719 {
720 //m_pNoteVelocityEditor->updateEditor();
721 //m_pNotePanEditor->updateEditor();
722 //m_pNoteLeadLagEditor->updateEditor();
723
724 resizeEvent(nullptr); // force a scrollbar update
725 }
726
727
showDrumEditorBtnClick(Button * ref)728 void PatternEditorPanel::showDrumEditorBtnClick(Button *ref)
729 {
730 UNUSED( ref );
731 if ( !__show_drum_btn->isPressed() ){
732 __show_drum_btn->setToolTip( tr( "Show piano roll editor" ) );
733 m_pPianoRollScrollView->hide();
734 m_pEditorScrollView->show();
735 m_pInstrListScrollView->show();
736
737 m_pDrumPatternEditor->selectedInstrumentChangedEvent(); // force an update
738
739 // force a re-sync of extern scrollbars
740 resizeEvent( nullptr );
741
742 }
743 else
744 {
745 __show_drum_btn->setToolTip( tr( "Show drum editor" ) );
746 m_pPianoRollScrollView->show();
747 m_pPianoRollScrollView->verticalScrollBar()->setValue( 250 );
748 m_pEditorScrollView->show();
749 m_pInstrListScrollView->show();
750
751 m_pPianoRollEditor->selectedPatternChangedEvent();
752 m_pPianoRollEditor->updateEditor(); // force an update
753 // force a re-sync of extern scrollbars
754 resizeEvent( nullptr );
755 }
756 }
757
758
zoomInBtnClicked(Button * ref)759 void PatternEditorPanel::zoomInBtnClicked(Button *ref)
760 {
761 if(m_pPatternEditorRuler->getGridWidth() >=24){
762 return;
763 }
764 UNUSED( ref );
765 m_pPatternEditorRuler->zoomIn();
766 m_pDrumPatternEditor->zoom_in();
767 m_pNoteVelocityEditor->zoomIn();
768 m_pNoteLeadLagEditor->zoomIn();
769 m_pNoteNoteKeyEditor->zoomIn();
770 m_pNoteProbabilityEditor->zoomIn();
771 m_pNotePanEditor->zoomIn();
772 m_pPianoRollEditor->zoom_in();
773
774 resizeEvent( nullptr );
775 }
776
777
778
zoomOutBtnClicked(Button * ref)779 void PatternEditorPanel::zoomOutBtnClicked(Button *ref)
780 {
781 UNUSED( ref );
782 m_pPatternEditorRuler->zoomOut();
783 m_pDrumPatternEditor->zoom_out();
784 m_pNoteVelocityEditor->zoomOut();
785 m_pNoteLeadLagEditor->zoomOut();
786 m_pNoteNoteKeyEditor->zoomOut();
787 m_pNoteProbabilityEditor->zoomOut();
788 m_pNotePanEditor->zoomOut();
789 m_pPianoRollEditor->zoom_out();
790
791 resizeEvent( nullptr );
792 }
793
794
795
patternSizeChanged(int nSelected)796 void PatternEditorPanel::patternSizeChanged( int nSelected )
797 {
798 // INFOLOG( QString("idx %1 -> %2 eighth").arg( nSelected ).arg( ( MAX_NOTES / 8 ) * ( nSelected + 1 ) ) );
799
800 if ( !m_pPattern ) {
801 return;
802 }
803
804 int nEighth = MAX_NOTES / 8;
805
806 Hydrogen *pEngine = Hydrogen::get_instance();
807
808 if ( pEngine->getState() != STATE_READY ) {
809 __pattern_size_combo->select( ((m_pPattern->get_length() / nEighth) - 1), false );
810 QMessageBox::information( this, "Hydrogen", tr( "Is not possible to change the pattern size when playing." ) );
811 return;
812 }
813
814 m_pPattern->set_length( nEighth * ( nSelected + 1 ) );
815
816 m_pPatternEditorRuler->updateEditor( true ); // redraw all
817 m_pNoteVelocityEditor->updateEditor();
818 m_pNotePanEditor->updateEditor();
819 m_pNoteLeadLagEditor->updateEditor();
820 m_pNoteNoteKeyEditor->updateEditor();
821 m_pNoteProbabilityEditor->updateEditor();
822 m_pPianoRollEditor->updateEditor();
823
824 resizeEvent( nullptr );
825
826 EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
827 }
828
829
830
moveUpBtnClicked(Button *)831 void PatternEditorPanel::moveUpBtnClicked(Button *)
832 {
833 Hydrogen *engine = Hydrogen::get_instance();
834 int nSelectedInstrument = engine->getSelectedInstrumentNumber();
835
836 AudioEngine::get_instance()->lock( RIGHT_HERE );
837
838 Song *pSong = engine->getSong();
839 InstrumentList *pInstrumentList = pSong->get_instrument_list();
840
841 if ( ( nSelectedInstrument - 1 ) >= 0 ) {
842 pInstrumentList->swap( nSelectedInstrument -1, nSelectedInstrument );
843
844 AudioEngine::get_instance()->unlock();
845 engine->setSelectedInstrumentNumber( nSelectedInstrument - 1 );
846
847 pSong->set_is_modified( true );
848 }
849 else {
850 AudioEngine::get_instance()->unlock();
851 }
852 }
853
854
855
moveDownBtnClicked(Button *)856 void PatternEditorPanel::moveDownBtnClicked(Button *)
857 {
858 Hydrogen *engine = Hydrogen::get_instance();
859 int nSelectedInstrument = engine->getSelectedInstrumentNumber();
860
861 AudioEngine::get_instance()->lock( RIGHT_HERE );
862
863 Song *pSong = engine->getSong();
864 InstrumentList *pInstrumentList = pSong->get_instrument_list();
865
866 if ( ( nSelectedInstrument + 1 ) < (int)pInstrumentList->size() ) {
867 pInstrumentList->swap( nSelectedInstrument, nSelectedInstrument + 1 );
868
869 AudioEngine::get_instance()->unlock();
870 engine->setSelectedInstrumentNumber( nSelectedInstrument + 1 );
871
872 pSong->set_is_modified( true );
873 }
874 else {
875 AudioEngine::get_instance()->unlock();
876 }
877
878 }
879
880
881
882
dragEnterEvent(QDragEnterEvent * event)883 void PatternEditorPanel::dragEnterEvent(QDragEnterEvent *event)
884 {
885 m_pInstrumentList->dragEnterEvent( event );
886 }
887
888
889
dropEvent(QDropEvent * event)890 void PatternEditorPanel::dropEvent(QDropEvent *event)
891 {
892 m_pInstrumentList->dropEvent( event );
893 }
894
895
896
propertiesComboChanged(int nSelected)897 void PatternEditorPanel::propertiesComboChanged( int nSelected )
898 {
899 if ( nSelected == 0 ) { // Velocity
900 m_pNotePanScrollView->hide();
901 m_pNoteLeadLagScrollView->hide();
902 m_pNoteNoteKeyScrollView->hide();
903 m_pNoteVelocityScrollView->show();
904 m_pNoteProbabilityScrollView->hide();
905
906 m_pNoteVelocityEditor->updateEditor();
907 }
908 else if ( nSelected == 1 ) { // Pan
909 m_pNoteVelocityScrollView->hide();
910 m_pNoteLeadLagScrollView->hide();
911 m_pNoteNoteKeyScrollView->hide();
912 m_pNotePanScrollView->show();
913 m_pNoteProbabilityScrollView->hide();
914
915 m_pNotePanEditor->updateEditor();
916 }
917 else if ( nSelected == 2 ) { // Lead and Lag
918 m_pNoteVelocityScrollView->hide();
919 m_pNotePanScrollView->hide();
920 m_pNoteNoteKeyScrollView->hide();
921 m_pNoteLeadLagScrollView->show();
922 m_pNoteProbabilityScrollView->hide();
923
924 m_pNoteLeadLagEditor->updateEditor();
925 }
926 else if ( nSelected == 3 ) { // NoteKey
927 m_pNoteVelocityScrollView->hide();
928 m_pNotePanScrollView->hide();
929 m_pNoteLeadLagScrollView->hide();
930 m_pNoteNoteKeyScrollView->show();
931 m_pNoteProbabilityScrollView->hide();
932
933 m_pNoteNoteKeyEditor->updateEditor();
934 }
935 else if ( nSelected == 4 ) { // Probability
936 m_pNotePanScrollView->hide();
937 m_pNoteLeadLagScrollView->hide();
938 m_pNoteNoteKeyScrollView->hide();
939 m_pNoteVelocityScrollView->hide();
940 m_pNoteProbabilityScrollView->show();
941
942 m_pNoteProbabilityEditor->updateEditor();
943 }
944 /*
945 else if ( nSelected == 5 ) { // Cutoff
946 }
947 else if ( nSelected == 6 ) { // Resonance
948 }
949 */
950 else {
951 ERRORLOG( QString("unhandled value : %1").arg(nSelected) );
952 }
953 }
954
955
recPreDeleteSelect(int index)956 void PatternEditorPanel::recPreDeleteSelect( int index )
957 {
958 Preferences::get_instance()->m_nRecPreDelete = index;
959 if( index>=9 && index <=15 ){
960 __recpostdelete->show();
961 }else{
962 __recpostdelete->hide();
963 }
964 }
965
966
recPostDeleteSelect(int index)967 void PatternEditorPanel::recPostDeleteSelect( int index )
968 {
969 Preferences::get_instance()->m_nRecPostDelete = index;
970 }
971
972
displayorHidePrePostCB()973 void PatternEditorPanel::displayorHidePrePostCB()
974 {
975 int index = __recpredelete->currentIndex();
976 if( Preferences::get_instance()->getDestructiveRecord() ){
977 __recpostdelete->show();
978 if( index>=8 && index <=14 ){
979 __recpostdelete->show();
980 }else{
981 __recpostdelete->hide();
982 }
983 __recpredelete->show();
984 }else{
985 __recpostdelete->hide();
986 __recpredelete->hide();
987 }
988 }
989
updatePianorollEditor()990 void PatternEditorPanel::updatePianorollEditor()
991 {
992 m_pDrumPatternEditor->updateEditor(); // force an update
993 }
994