hydrogen 1.2.3
InstrumentEditor.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
23#include <QtGui>
24#include <QtWidgets>
25
26
27#include <math.h>
28#include <assert.h>
29#include <vector>
30
31#include <core/Basics/Song.h>
32#include <core/Hydrogen.h>
33#include <core/Globals.h>
34#include <core/Basics/Adsr.h>
35#include <core/Basics/Sample.h>
42#include <core/EventQueue.h>
43using namespace H2Core;
44
45#include "../HydrogenApp.h"
46#include "../CommonStrings.h"
47#include "../Widgets/Rotary.h"
50#include "../Widgets/Button.h"
53#include "../Widgets/LCDCombo.h"
54#include "../Widgets/Fader.h"
55#include "InstrumentEditor.h"
57#include "WaveDisplay.h"
58#include "LayerPreview.h"
60
62 : QWidget( pParent )
63 , m_pInstrument( nullptr )
64 , m_nSelectedLayer( 0 )
65 , m_fPreviousMidiOutChannel( -1.0 )
66 , m_nSelectedComponent( -1 )
67{
68 setFixedWidth( 290 );
69
70 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
71
72 // Instrument properties top
74 m_pInstrumentPropTop->setPixmap( "/instrumentEditor/instrumentTab_top.png" );
75
77 pCommonStrings->getGeneralButton(), false, QSize(),
78 tr( "Show instrument properties" ) );
79 m_pShowInstrumentBtn->move( 4, 4 );
80
81 connect( m_pShowInstrumentBtn, &QPushButton::clicked,
82 [=]() { showLayers( false ); } );
83
85 pCommonStrings->getLayersButton(), false, QSize(),
86 tr( "Show layers properties" ) );
87 m_pShowLayersBtn->move( 145, 4 );
88
89 connect( m_pShowLayersBtn, &QPushButton::clicked,
90 [=]() { showLayers( true ); } );
91
92
93 // Instrument properties
94 m_pInstrumentProp = new PixmapWidget( this );
95 m_pInstrumentProp->move(0, 31);
96 m_pInstrumentProp->setPixmap( "/instrumentEditor/instrumentTab.png" );
97
98 m_pNameLbl = new ClickableLabel( m_pInstrumentProp, QSize( 279, 27 ), "",
100 m_pNameLbl->move( 5, 4 );
101 m_pNameLbl->setScaledContents( true );
102
104 //Midi Out
105
106 ClickableLabel* pMidiOutLbl = new ClickableLabel( m_pInstrumentProp, QSize( 61, 10 ),
107 pCommonStrings->getMidiOutLabel() );
108 pMidiOutLbl->move( 22, 281 );
109
110 m_pMidiOutChannelLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
111 LCDSpinBox::Type::Int, -1, 16,
112 true, true );
113 m_pMidiOutChannelLCD->move( 98, 257 );
114 m_pMidiOutChannelLCD->setToolTip(QString(tr("Midi out channel")));
115 connect( m_pMidiOutChannelLCD, SIGNAL( valueChanged( double ) ),
116 this, SLOT( midiOutChannelChanged( double ) ) );
118 pCommonStrings->getMidiOutChannelLabel() );
119 m_pMidiOutChannelLbl->move( 96, 281 );
120
122 m_pMidiOutNoteLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
123 LCDSpinBox::Type::Int, 0, 127, true );
124 m_pMidiOutNoteLCD->move( 161, 257 );
125 m_pMidiOutNoteLCD->setToolTip(QString(tr("Midi out note")));
126 connect( m_pMidiOutNoteLCD, SIGNAL( valueChanged( double ) ),
127 this, SLOT( midiOutNoteChanged( double ) ) );
128 m_pMidiOutNoteLbl = new ClickableLabel( m_pInstrumentProp, QSize( 61, 10 ),
129 pCommonStrings->getMidiOutNoteLabel() );
130 m_pMidiOutNoteLbl->move( 159, 281 );
131
133
134 connect( m_pNameLbl, SIGNAL( labelClicked(ClickableLabel*) ),
135 this, SLOT( labelClicked(ClickableLabel*) ) );
136
137 m_pPitchLCD = new LCDDisplay( m_pInstrumentProp, QSize( 56, 20 ), false, false );
138 m_pPitchLCD->move( 24, 213 );
139 m_pPitchLbl = new ClickableLabel( m_pInstrumentProp, QSize( 54, 10 ),
140 pCommonStrings->getPitchLabel() );
141 m_pPitchLbl->move( 25, 235 );
142
143
145 tr( "Pitch offset (Coarse)" ), true, -24, 24 );
146 m_pPitchCoarseRotary->move( 84, 210 );
147
148 connect( m_pPitchCoarseRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
149 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
150 m_pPitchCoarseLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
151 pCommonStrings->getPitchCoarseLabel() );
152 m_pPitchCoarseLbl->move( 82, 235 );
153
155 tr( "Pitch offset (Fine)" ), false, -0.5, 0.5 );
156 //it will have resolution of 100 steps between Min and Max => quantum delta = 0.01
157 m_pPitchFineRotary->move( 138, 210 );
158 connect( m_pPitchFineRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
159 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
160 m_pPitchFineLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
161 pCommonStrings->getPitchFineLabel() );
162 m_pPitchFineLbl->move( 136, 235 );
163
164
165
167 tr( "Random pitch factor" ), false );
168 m_pRandomPitchRotary->move( 194, 210 );
169 connect( m_pRandomPitchRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
170 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
171 m_pPitchRandomLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
172 pCommonStrings->getPitchRandomLabel() );
173 m_pPitchRandomLbl->move( 192, 235 );
174
175 // Filter
177 "", pCommonStrings->getBypassButton(), true,
178 QSize( 0, 0 ), "", false, true );
179 connect( m_pFilterBypassBtn, SIGNAL( clicked() ),
180 this, SLOT( filterActiveBtnClicked() ) );
181 m_pFilterBypassBtn->move( 67, 169 );
182
184 tr( "Filter Cutoff" ), false );
186 connect( m_pCutoffRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
187 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
188 m_pCutoffLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
189 pCommonStrings->getCutoffLabel() );
190 m_pCutoffLbl->move( 107, 189 );
191
193 tr( "Filter resonance" ), false );
194 connect( m_pResonanceRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
195 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
196 m_pResonanceLbl = new ClickableLabel( m_pInstrumentProp, QSize( 56, 10 ),
197 pCommonStrings->getResonanceLabel() );
198 m_pResonanceLbl->move( 157, 189 );
199
200 m_pCutoffRotary->move( 109, 164 );
201 m_pResonanceRotary->move( 163, 164 );
202 // ~ Filter
203
204 // ADSR
206 tr( "Length of Attack phase.\n\nValue" ), false );
208 tr( "Length of Decay phase.\n\nValue" ), false );
210 tr( "Sample volume in Sustain phase.\n\nValue" ), false );
213 tr( "Length of Release phase.\n\nValue" ), false );
215 connect( m_pAttackRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
216 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
217 connect( m_pDecayRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
218 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
219 connect( m_pSustainRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
220 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
221 connect( m_pReleaseRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
222 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
223 m_pAttackRotary->move( 45, 52 );
224 m_pDecayRotary->move( 97, 52 );
225 m_pSustainRotary->move( 149, 52 );
226 m_pReleaseRotary->move( 201, 52 );
227
228 m_pAttackLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
229 pCommonStrings->getAttackLabel() );
230 m_pAttackLbl->move( 43, 78 );
231 m_pDecayLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
232 pCommonStrings->getDecayLabel() );
233 m_pDecayLbl->move( 95, 78 );
234 m_pSustainLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
235 pCommonStrings->getSustainLabel() );
236 m_pSustainLbl->move( 147, 78 );
237 m_pReleaseLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
238 pCommonStrings->getReleaseLabel() );
239 m_pReleaseLbl->move( 199, 78 );
240 // ~ ADSR
241
242 // instrument gain
243 m_pInstrumentGainLCD = new LCDDisplay( m_pInstrumentProp, QSize( 43, 20 ), false, false );
245 tr( "Instrument gain" ), false, 0.0, 5.0 );
247 connect( m_pInstrumentGain, SIGNAL( valueChanged( WidgetWithInput* ) ),
248 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
249 m_pInstrumentGainLCD->move( 62, 103 );
250 m_pInstrumentGain->move( 109, 100 );
251 m_pGainLbl = new ClickableLabel( m_pInstrumentProp, QSize( 48, 10 ),
252 pCommonStrings->getGainLabel() );
253 m_pGainLbl->move( 107, 125 );
254
255
256 m_pMuteGroupLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
257 LCDSpinBox::Type::Int, -1, 100,
258 true, true );
259 m_pMuteGroupLCD->move( 160, 101 );
260 connect( m_pMuteGroupLCD, SIGNAL( valueChanged( double ) ),
261 this, SLOT( muteGroupChanged( double ) ) );
262 m_pMuteGroupLbl = new ClickableLabel( m_pInstrumentProp, QSize( 61, 10 ),
263 pCommonStrings->getMuteGroupLabel() );
264 m_pMuteGroupLbl->move( 159, 125 );
265
266 m_pIsStopNoteCheckBox = new QCheckBox ( tr( "" ), m_pInstrumentProp );
267 m_pIsStopNoteCheckBox->move( 42, 139 );
268 m_pIsStopNoteCheckBox->adjustSize();
269 m_pIsStopNoteCheckBox->setFixedSize( 14, 14 );
270 m_pIsStopNoteCheckBox->setToolTip( tr( "Stop the current playing instrument-note before trigger the next note sample" ) );
271 m_pIsStopNoteCheckBox->setFocusPolicy ( Qt::NoFocus );
272 connect( m_pIsStopNoteCheckBox, SIGNAL( toggled( bool ) ),
273 this, SLOT( onIsStopNoteCheckBoxClicked( bool ) ) );
274 m_pIsStopNoteLbl = new ClickableLabel( m_pInstrumentProp, QSize( 87, 10 ),
275 pCommonStrings->getIsStopNoteLabel() );
276 m_pIsStopNoteLbl->move( 59, 144 );
277
278 m_pApplyVelocity = new QCheckBox ( "", m_pInstrumentProp );
279 m_pApplyVelocity->move( 153, 139 );
280 m_pApplyVelocity->adjustSize();
281 m_pApplyVelocity->setFixedSize( 14, 14 );
282 m_pApplyVelocity->setToolTip( tr( "Don't change the layers' gain based on velocity" ) );
283 m_pApplyVelocity->setFocusPolicy( Qt::NoFocus );
284 connect( m_pApplyVelocity, SIGNAL( toggled( bool ) ),
285 this, SLOT( onIsApplyVelocityCheckBoxClicked( bool ) ) );
287 pCommonStrings->getApplyVelocityLabel() );
288 m_pApplyVelocityLbl->move( 170, 144 );
289
291 // HiHat setup
292
293 m_pHihatGroupLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
294 LCDSpinBox::Type::Int, -1, 32,
295 true, true );
296 m_pHihatGroupLCD->move( 28, 303 );
297 connect( m_pHihatGroupLCD, SIGNAL( valueChanged( double ) ),
298 this, SLOT( hihatGroupChanged( double ) ) );
299 m_pHihatGroupLbl = new ClickableLabel( m_pInstrumentProp, QSize( 69, 10 ),
300 pCommonStrings->getHihatGroupLabel() );
301 m_pHihatGroupLbl->move( 22, 327 );
302
303 m_pHihatMinRangeLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
304 LCDSpinBox::Type::Int, 0, 127, true );
305 m_pHihatMinRangeLCD->move( 138, 303 );
306 connect( m_pHihatMinRangeLCD, SIGNAL( valueChanged( double ) ),
307 this, SLOT( hihatMinRangeChanged( double ) ) );
309 pCommonStrings->getHihatMinRangeLabel() );
310 m_pHihatMinRangeLbl->move( 136, 327 );
311
312 m_pHihatMaxRangeLCD = new LCDSpinBox( m_pInstrumentProp, QSize( 59, 24 ),
313 LCDSpinBox::Type::Int, 0, 127, true );
314 m_pHihatMaxRangeLCD->move( 203, 303 );
315 connect( m_pHihatMaxRangeLCD, SIGNAL( valueChanged( double ) ),
316 this, SLOT( hihatMaxRangeChanged( double ) ) );
318 pCommonStrings->getHihatMaxRangeLabel() );
319 m_pHihatMaxRangeLbl->move( 201, 327 );
320 // ~ Instrument properties
321
322 // LAYER properties
323 m_pLayerProp = new PixmapWidget( this );
324 m_pLayerProp->setObjectName( "LayerProperties" );
325 m_pLayerProp->move( 0, 31 );
326 m_pLayerProp->hide();
327 m_pLayerProp->setPixmap( "/instrumentEditor/layerTabsupernew.png" );
328
329 // Component
330 m_pCompoNameLbl = new ClickableLabel( m_pLayerProp, QSize( 279, 27 ), "",
332 m_pCompoNameLbl->move( 5, 4 );
333 connect( m_pCompoNameLbl, SIGNAL( labelClicked(ClickableLabel*) ),
334 this, SLOT( labelCompoClicked(ClickableLabel*) ) );
335
336 m_buttonDropDownCompo = new Button( m_pLayerProp, QSize( 18, 18 ),
337 Button::Type::Push, "dropdown.svg", "",
338 false, QSize( 12, 12 ) );
339 m_buttonDropDownCompo->setObjectName( "InstrumentEditorComponentNameDropDown" );
340 m_buttonDropDownCompo->move( 263, 8 );
341 connect( m_buttonDropDownCompo, SIGNAL( clicked() ),
342 this, SLOT( onDropDownCompoClicked() ) );
343
344 // Layer preview
345 m_pLayerPreview = new LayerPreview( nullptr );
346
347 m_pLayerScrollArea = new QScrollArea( m_pLayerProp);
348 m_pLayerScrollArea->setFrameShape( QFrame::NoFrame );
349 m_pLayerScrollArea->move( 6, 44 );
350 m_pLayerScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
352 m_pLayerScrollArea->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn );
353 }
354 m_pLayerScrollArea->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
355 m_pLayerScrollArea->setMaximumHeight( 182 );
357
358
359 // Waveform display
361 m_pWaveDisplay->resize( 277, 58 );
362 m_pWaveDisplay->updateDisplay( nullptr );
363 m_pWaveDisplay->move( 5, 241 );
364 connect( m_pWaveDisplay, SIGNAL( doubleClicked(QWidget*) ),
365 this, SLOT( waveDisplayDoubleClicked(QWidget*) ) );
366
367 m_pLoadLayerBtn = new Button( m_pLayerProp, QSize( 92, 18 ), Button::Type::Push,
368 "", pCommonStrings->getLoadLayerButton() );
369 m_pLoadLayerBtn->setObjectName( "LoadLayerButton" );
370 m_pLoadLayerBtn->move( 5, 304 );
371
373 "", pCommonStrings->getDeleteLayerButton() );
374 m_pRemoveLayerBtn->setObjectName( "RemoveLayerButton" );
375 m_pRemoveLayerBtn->move( 97, 304 );
376
378 "", pCommonStrings->getEditLayerButton() );
379 m_pSampleEditorBtn->setObjectName( "SampleEditorButton" );
380 m_pSampleEditorBtn->move( 191, 304 );
381
382 connect( m_pLoadLayerBtn, SIGNAL( clicked() ),
383 this, SLOT( loadLayerBtnClicked() ) );
384 connect( m_pRemoveLayerBtn, SIGNAL( clicked() ),
385 this, SLOT( removeLayerButtonClicked() ) );
386 connect( m_pSampleEditorBtn, SIGNAL( clicked() ),
387 this, SLOT( showSampleEditor() ) );
388 // Layer gain
389 m_pLayerGainLCD = new LCDDisplay( m_pLayerProp, QSize( 36, 16 ), false, false );
391 tr( "Layer gain" ), false , 0.0, 5.0);
393 connect( m_pLayerGainRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
394 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
395 m_pLayerGainLbl = new ClickableLabel( m_pLayerProp, QSize( 44, 10 ),
396 pCommonStrings->getLayerGainLabel() );
397 m_pLayerGainLbl->move( 50, 360 );
398
399 m_pCompoGainLCD = new LCDDisplay( m_pLayerProp, QSize( 36, 16 ), false, false );
401 tr( "Component volume" ), false, 0.0, 5.0 );
403 connect( m_pCompoGainRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
404 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
405 m_pCompoGainLbl = new ClickableLabel( m_pLayerProp, QSize( 44, 10 ),
406 pCommonStrings->getComponentGainLabel() );
407 m_pCompoGainLbl->move( 147, 360 );
408
409 m_pLayerPitchCoarseLCD = new LCDDisplay( m_pLayerProp, QSize( 28, 16 ), false, false );
410 m_pLayerPitchFineLCD = new LCDDisplay( m_pLayerProp, QSize( 28, 16 ), false, false );
411 m_pLayerPitchLbl = new ClickableLabel( m_pLayerProp, QSize( 45, 10 ),
412 pCommonStrings->getPitchLabel() );
413 m_pLayerPitchLbl->move( 17, 412 );
414
416 tr( "Layer pitch (Coarse)" ), true, -24.0, 24.0 );
417 connect( m_pLayerPitchCoarseRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
418 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
419 m_pLayerPitchCoarseLbl = new ClickableLabel( m_pLayerProp, QSize( 44, 10 ),
420 pCommonStrings->getPitchCoarseLabel() );
421 m_pLayerPitchCoarseLbl->move( 61, 412 );
422
424 tr( "Layer pitch (Fine)" ), true, -50.0, 50.0 );
425 connect( m_pLayerPitchFineRotary, SIGNAL( valueChanged( WidgetWithInput* ) ),
426 this, SLOT( rotaryChanged( WidgetWithInput* ) ) );
427 m_pLayerPitchFineLbl = new ClickableLabel( m_pLayerProp, QSize( 44, 10 ),
428 pCommonStrings->getPitchFineLabel() );
429 m_pLayerPitchFineLbl->move( 147, 412 );
430
431 m_pLayerGainLCD->move( 53, 343 );
432 m_pLayerGainRotary->move( 94, 341 );
433
434 m_pCompoGainLCD->move( 151, 343 );
435 m_pCompoGainRotary->move( 191, 341 );
436
437 m_pLayerPitchCoarseLCD->move( 70, 393 );
438 m_pLayerPitchCoarseRotary->move( 105, 391 );
439
440 m_pLayerPitchFineLCD->move( 155, 393 );
441 m_pLayerPitchFineRotary->move( 191, 391 );
442
443 m_sampleSelectionAlg = new LCDCombo(m_pLayerProp, QSize( width() - 76 - 7, 18 ), true );
444 m_sampleSelectionAlg->move( 76, 432 );
445 m_sampleSelectionAlg->setToolTip( tr( "Select selection algorithm" ) );
446 m_sampleSelectionAlg->addItem( QString( "First in Velocity" ) );
447 m_sampleSelectionAlg->addItem( QString( "Round Robin" ) );
448 m_sampleSelectionAlg->addItem( QString( "Random" ) );
449 connect( m_sampleSelectionAlg, SIGNAL( currentIndexChanged( int ) ),
450 this, SLOT( sampleSelectionChanged( int ) ) );
451 m_pSampleSelectionLbl = new ClickableLabel( m_pLayerProp, QSize( 70, 10 ),
452 pCommonStrings->getSampleSelectionLabel() );
453 m_pSampleSelectionLbl->move( 7, 436 );
454
455 // ~ Layer properties
456
457 //component handling
458 QStringList itemsCompo;
459 popCompo = new QMenu( this );
460
461 connect( popCompo, SIGNAL( triggered(QAction*) ),
462 this, SLOT( compoChangeAddDelete(QAction*) ) );
463 update();
464 // ~ component handling
465
466 showLayers( false );
467
469
470 selectedInstrumentChangedEvent(); // force an update
471
474}
475
476
477
479{
480 //INFOLOG( "DESTROY" );
481}
482
484 // A new song got loaded
485 if ( nValue == 0 ) {
487
488 // The function call above sets some spurious isModified when
489 // updating the states of the widgets. This has to be reset
490 // for a freshly loaded song.
492 }
493}
494
498
500{
501 Hydrogen *pHydrogen = Hydrogen::get_instance();
502 std::shared_ptr<Song> pSong = pHydrogen->getSong();
503 auto pCompoList = pSong->getComponents();
504
506
507 // update layer list
508 if ( pSong != nullptr && m_pInstrument != nullptr &&
509 pCompoList != nullptr && pCompoList->size() > 0 ) {
511
512 // ADSR
513 m_pAttackRotary->setValue( sqrtf(m_pInstrument->get_adsr()->getAttack() / 100000.0) );
514 m_pDecayRotary->setValue( sqrtf(m_pInstrument->get_adsr()->getDecay() / 100000.0) );
515 m_pSustainRotary->setValue( m_pInstrument->get_adsr()->getSustain() );
516 float fTmp = m_pInstrument->get_adsr()->getRelease() - 256.0;
517 if( fTmp < 0.0 ) {
518 fTmp = 0.0;
519 }
520 m_pReleaseRotary->setValue( sqrtf(fTmp / 100000.0) );
521 // ~ ADSR
522
523 // filter
527 // ~ filter
528
529 // pitch offset
530 char tmp[7];
531 sprintf( tmp, "%#.2f", m_pInstrument->get_pitch_offset() );
532 m_pPitchLCD->setText( tmp );
533
534 /* fCoarsePitch is the closest integer to pitch_offset (represents the pitch shift interval in half steps)
535 while it is an integer number, it's defined float to be used in next lines */
536 float fCoarsePitch = round( m_pInstrument->get_pitch_offset() );
537
538 //fFinePitch represents the fine adjustment (between -0.5 and +0.5) if pitch_offset has decimal part
539 float fFinePitch = m_pInstrument->get_pitch_offset() - fCoarsePitch;
540
541 m_pPitchCoarseRotary->setValue( fCoarsePitch );
542 m_pPitchFineRotary->setValue( fFinePitch );
543
544 // pitch random
546
547 //Stop Note
549
550 //Ignore Velocity
552
553 // instr gain
554 sprintf( tmp, "%#.2f", m_pInstrument->get_gain() );
555 m_pInstrumentGainLCD->setText( tmp );
557
558 // instr mute group
560
561 // midi out channel
562 if ( m_pInstrument->get_midi_out_channel() == -1 ) {
563 m_pMidiOutChannelLCD->setValue( -1 ); // turn off
564 } else {
565 // The MIDI channels start at 1 instead of zero.
567 }
568
569 //midi out note
571
572 // hihat
576
577 // see instrument.h
579
580 itemsCompo.clear();
581 for ( const auto& pComponent : *pSong->getComponents() ) {
582 if ( ! itemsCompo.contains( pComponent->get_name() ) ) {
583 itemsCompo.append( pComponent->get_name() );
584 }
585 }
586 itemsCompo.append("--sep--");
587 itemsCompo.append("add");
588 itemsCompo.append("delete");
589 itemsCompo.append("rename");
590
591 update();
592
593 bool bFound = false;
594 for ( const auto& ppComponent : *pCompoList ) {
595 if ( ppComponent->get_id() == m_nSelectedComponent ) {
596 bFound = true;
597 break;
598 }
599 }
600 if ( !bFound ){
601 m_nSelectedComponent = pCompoList->front()->get_id();
602 }
603
604 auto pTmpComponent = pSong->getComponent( m_nSelectedComponent );
605
606 assert(pTmpComponent);
607
608 m_pCompoNameLbl->setText( pTmpComponent->get_name() );
609
610 if ( m_nSelectedLayer >= 0 ) {
611
613 if ( pComponent != nullptr ) {
614
615 char tmp[20];
616 sprintf( tmp, "%#.2f", pComponent->get_gain());
617 m_pCompoGainLCD->setText( tmp );
618
619 m_pCompoGainRotary->setValue( pComponent->get_gain() );
620
621 auto pLayer = pComponent->get_layer( m_nSelectedLayer );
622 if ( pLayer != nullptr ) {
623 m_pWaveDisplay->updateDisplay( pLayer );
624 }
625 else {
626 m_pWaveDisplay->updateDisplay( nullptr );
627 }
628 }
629 else {
630 m_pWaveDisplay->updateDisplay( nullptr );
631 }
632 }
633 else {
634 m_pWaveDisplay->updateDisplay( nullptr );
635 }
636 }
637 else {
638 m_pNameLbl->setText( QString( "NULL Instrument..." ) );
639 m_pWaveDisplay->updateDisplay( nullptr );
641 }
642
644}
645
646// In here we just check those parameters that can be altered by MIDI
647// or OSC messages or other parts of Hydrogen.
649{
650 auto pInstrumentList = Hydrogen::get_instance()->getSong()->getInstrumentList();
651
652 // Check if either this particular line or all lines should be updated.
653 if ( m_pInstrument != nullptr ) {
654 if ( m_pInstrument == pInstrumentList->get( nInstrumentNumber ) ||
655 nInstrumentNumber == -1 ) {
656
657 if ( m_pNameLbl->text() != m_pInstrument->get_name() ) {
659 }
660
661 // filter
665 // ~ filter
666 }
667 // In case nInstrumentNumber does not belong to the currently
668 // selected instrument we don't have to do anything.
669 }
670 else {
671 m_pNameLbl->setText( QString( "NULL Instrument..." ) );
672 m_pWaveDisplay->updateDisplay( nullptr );
674 }
675
677}
678
680{
681 assert( ref );
682 Rotary* pRotary = static_cast<Rotary*>( ref );
683
684 float fVal = pRotary->getValue();
685
686 if ( m_pInstrument ) {
687 if ( pRotary == m_pRandomPitchRotary ){
689 }
690 else if ( pRotary == m_pPitchCoarseRotary ) {
691 //round fVal, since Coarse is the integer number of half steps
692 float newPitch = round( fVal ) + m_pPitchFineRotary->getValue();
693 m_pInstrument->set_pitch_offset( newPitch );
694 char tmp[7];
695 sprintf( tmp, "%#.2f", newPitch);
696 m_pPitchLCD->setText( tmp );
697 }
698 else if ( pRotary == m_pPitchFineRotary ) {
699 float newPitch = round( m_pPitchCoarseRotary->getValue() ) + fVal;
700 m_pInstrument->set_pitch_offset( newPitch );
701 char tmp[7];
702 sprintf( tmp, "%#.2f", newPitch);
703 m_pPitchLCD->setText( tmp );
704 }
705 else if ( pRotary == m_pCutoffRotary ) {
707 }
708 else if ( pRotary == m_pResonanceRotary ) {
709 if ( fVal > 0.95f ) {
710 fVal = 0.95f;
711 }
713 }
714 else if ( pRotary == m_pAttackRotary ) {
715 m_pInstrument->get_adsr()->setAttack( fVal * fVal * 100000 );
716 }
717 else if ( pRotary == m_pDecayRotary ) {
718 m_pInstrument->get_adsr()->setDecay( fVal * fVal * 100000 );
719 }
720 else if ( pRotary == m_pSustainRotary ) {
721 m_pInstrument->get_adsr()->setSustain( fVal );
722 }
723 else if ( pRotary == m_pReleaseRotary ) {
724 m_pInstrument->get_adsr()->setRelease( 256.0 + fVal * fVal * 100000 );
725 }
726 else if ( pRotary == m_pLayerGainRotary ) {
727 char tmp[20];
728 sprintf( tmp, "%#.2f", fVal );
729 m_pLayerGainLCD->setText( tmp );
730
732 if( pCompo ) {
733 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
734 if ( pLayer ) {
735 pLayer->set_gain( fVal );
736 m_pWaveDisplay->updateDisplay( pLayer );
737 }
738 }
739 }
740 else if ( pRotary == m_pCompoGainRotary ) {
741 char tmp[20];
742 sprintf( tmp, "%#.2f", fVal );
743 m_pCompoGainLCD->setText( tmp );
744
746 pCompo->set_gain( fVal );
747 }
748 else if ( pRotary == m_pLayerPitchCoarseRotary ) {
749 m_pLayerPitchCoarseLCD->setText( QString( "%1" ).arg( (int) round( fVal ) ) );
750
752 if( pCompo ) {
753 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
754 if ( pLayer ) {
755 float fCoarse = round( m_pLayerPitchCoarseRotary->getValue() );
756 float fFine = m_pLayerPitchFineRotary->getValue() / 100.0;
757 pLayer->set_pitch( fCoarse + fFine );
758 }
759 }
760 }
761 else if ( pRotary == m_pLayerPitchFineRotary ) {
762 m_pLayerPitchFineLCD->setText( QString( "%1" ).arg( fVal, 0, 'f', 0 ) );
764 if( pCompo ) {
765 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
766 if ( pLayer ) {
767 float fCoarse = round( m_pLayerPitchCoarseRotary->getValue() );
768 float fFine = m_pLayerPitchFineRotary->getValue() / 100.0;
769 pLayer->set_pitch( fCoarse + fFine );
770 }
771 }
772 }
773 else if ( pRotary == m_pInstrumentGain ) {
774 fVal = fVal;
775 char tmp[20];
776 sprintf( tmp, "%#.2f", fVal );
777 m_pInstrumentGainLCD->setText( tmp );
778 m_pInstrument->set_gain( fVal );
779 }
780 else {
781 ERRORLOG( "[rotaryChanged] unhandled rotary" );
782 }
783 }
784}
785
786
793
794
796{
797 if ( !m_pInstrument ) {
798 return;
799 }
800
802 if( !pCompo ) {
803 return;
804 }
805
806 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
807 if ( pLayer ) {
808 auto pSample = pLayer->get_sample();
809
810 if( pSample != nullptr ) {
811 QString name = pSample->get_filepath();
813 }
814 }
815 else {
817 }
818}
819
821{
822 if ( m_pInstrument ) {
824 if( pCompo ) {
825 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
826 if ( pLayer != nullptr ) {
827 auto pSample = pLayer->get_sample();
828 if ( pSample == nullptr ) {
829 return;
830 }
831 QString name = pSample->get_filepath();
833 }
834 }
835 }
836}
837
839{
840 auto pHydrogen = Hydrogen::get_instance();
841 pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
842
843 if ( m_pInstrument != nullptr ) {
845 if( pCompo != nullptr ) {
846 pCompo->set_layer( nullptr, m_nSelectedLayer );
847
848 pHydrogen->setIsModified( true );
849
850 // Select next loaded layer - if available - in order to
851 // allow for a quick removal of all layers. In case the
852 // last layer was removed, the previous one will be
853 // selected.
854 int nNextLayerIndex = 0;
855 int nCount = 0;
856 for( int n = 0; n < InstrumentComponent::getMaxLayers(); n++ ) {
857 auto pLayer = pCompo->get_layer( n );
858 if( pLayer != nullptr ){
859 nCount++;
860
861 if ( nNextLayerIndex <= m_nSelectedLayer &&
862 n != m_nSelectedLayer ) {
863 nNextLayerIndex = n;
864 }
865 }
866 }
867
868 if( nCount == 0 ){
870 } else {
871 m_pLayerPreview->setSelectedLayer( nNextLayerIndex );
873 }
874
875 }
876 }
877
878 pHydrogen->getAudioEngine()->unlock();
879 selectedInstrumentChangedEvent(); // update all
881}
882
883
884
886{
887 Hydrogen *pHydrogen = Hydrogen::get_instance();
888
890 QString sFilename = "";
891 if ( ! Filesystem::dir_readable( sPath, false ) ){
892 sPath = QDir::homePath();
893 }
894
895 // In case the button was pressed while a layer was selected, we
896 // try to use path of the associated sample as default one.
897 if ( m_nSelectedLayer > 0 &&
898 m_pInstrument != nullptr ) {
900
901 if ( pComponent != nullptr ) {
902 auto pLayer = pComponent->get_layer( m_nSelectedLayer );
903
904 if ( pLayer != nullptr ) {
905 auto pSample = pLayer->get_sample();
906
907 if ( pSample != nullptr ) {
908 if ( ! pSample->get_filepath().isEmpty() ) {
909 QFileInfo fileInfo( pSample->get_filepath() );
910 sPath = fileInfo.absoluteDir().absolutePath();
911 sFilename = fileInfo.absoluteFilePath();
912 }
913 }
914 }
915 }
916 }
917
918
919
920 AudioFileBrowser *pFileBrowser =
921 new AudioFileBrowser( nullptr, true, true, sPath, sFilename );
922 QStringList filename;
923 filename << "false" << "false" << "";
924
925 if (pFileBrowser->exec() == QDialog::Accepted) {
926 filename = pFileBrowser->getSelectedFiles();
927
928 // Only overwrite the default directory if we didn't start
929 // from an existing file or the final directory differs from
930 // the starting one.
931 if ( sFilename.isEmpty() ||
932 sPath != pFileBrowser->getSelectedDirectory() ) {
934 }
935 }
936
937 delete pFileBrowser;
938
939 if ( filename[2].isEmpty() ) {
940 return;
941 }
942
943 bool fnc = false;
944 if ( filename[0] == "true" ){
945 fnc = true;
946 }
947
948 int selectedLayer = m_nSelectedLayer;
949 int firstSelection = selectedLayer;
950
951 // Ensure instrument pointer is current
953 if ( m_pInstrument == nullptr ) {
954 WARNINGLOG( "No instrument selected" );
955 return;
956 }
957
958 if (filename.size() > 2) {
959
960 for ( int i=2; i < filename.size(); ++i )
961 {
962 selectedLayer = m_nSelectedLayer + i - 2;
963 if ( ( i-2 >= InstrumentComponent::getMaxLayers() ) ||
964 ( selectedLayer + 1 > InstrumentComponent::getMaxLayers() ) ) {
965 break;
966 }
967
968 auto pNewSample = Sample::load( filename[i] );
969
970 pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
971
972 /*
973 if we're using multiple layers, we start inserting the first layer
974 at m_nSelectedLayer and the next layer at m_nSelectedLayer+1
975 */
976
978 if( !pCompo ) {
979 pCompo = std::make_shared<InstrumentComponent>( m_nSelectedComponent );
980 m_pInstrument->get_components()->push_back( pCompo );
981 }
982
983 auto pLayer = pCompo->get_layer( selectedLayer );
984
985 if (pLayer != nullptr) {
986 // insert new sample from newInstrument, old sample gets deleted by set_sample
987 pLayer->set_sample( pNewSample );
988 }
989 else {
990 pLayer = std::make_shared<H2Core::InstrumentLayer>( pNewSample );
991 m_pInstrument->get_component(m_nSelectedComponent)->set_layer( pLayer, selectedLayer );
992 }
993
994 if ( fnc ){
995 QString newFilename = filename[i].section( '/', -1 );
996 newFilename.replace( "." + newFilename.section( '.', -1 ), "");
997 m_pInstrument->set_name( newFilename );
998 }
999
1000 //set automatic velocity
1001 if ( filename[1] == "true" ){
1003 }
1004
1005 pHydrogen->getAudioEngine()->unlock();
1006 }
1007
1008 pHydrogen->setIsModified( true );
1009 }
1010
1011 selectedInstrumentChangedEvent(); // update all
1012 selectLayer( firstSelection );
1014}
1015
1016
1018{
1019 if ( m_pInstrument == nullptr ) {
1020 return;
1021 }
1023 if ( pCompo == nullptr ) {
1024 return;
1025 }
1026
1027 int nLayers = 0;
1028 for ( int i = 0; i < InstrumentComponent::getMaxLayers() ; i++ ) {
1029
1030 auto pLayer = pCompo->get_layer( i );
1031 if ( pLayer != nullptr ) {
1032 nLayers++;
1033 }
1034 }
1035
1036 if( nLayers == 0 ){
1037 nLayers = 1;
1038 }
1039
1040 float velocityrange = 1.0 / nLayers;
1041
1042 int nLayer = 0;
1043 for ( int i = 0; i < InstrumentComponent::getMaxLayers() ; i++ ) {
1044 auto pLayer = pCompo->get_layer( i );
1045 if ( pLayer != nullptr ) {
1046 pLayer->set_start_velocity( nLayer * velocityrange);
1047 pLayer->set_end_velocity( nLayer * velocityrange + velocityrange );
1048
1049 ++nLayer;
1050 }
1051 }
1052}
1053
1055{
1056 UNUSED( pRef );
1057 std::shared_ptr<Song> pSong = Hydrogen::get_instance()->getSong();
1058 if ( pSong == nullptr ) {
1059 return;
1060 }
1061 auto pComponent = pSong->getComponent( m_nSelectedComponent );
1062 if ( pComponent == nullptr ) {
1063 return;
1064 }
1065 QString sOldName = pComponent->get_name();
1066 bool bIsOkPressed;
1067 QString sNewName = QInputDialog::getText( this, "Hydrogen", tr( "New component name" ), QLineEdit::Normal, sOldName, &bIsOkPressed );
1068
1069 if ( bIsOkPressed && sOldName != sNewName ) {
1070 pComponent->set_name( sNewName );
1071
1073
1074 // this will force an update...
1076 }
1077}
1078
1080{
1081 if (!m_pInstrument) {
1082 return;
1083 }
1084
1085 m_nSelectedComponent = nComponent;
1087}
1088
1090{
1091 UNUSED( pRef );
1092
1093 if (m_pInstrument) {
1094 QString sOldName = m_pInstrument->get_name();
1095 bool bIsOkPressed;
1096 QString sNewName = QInputDialog::getText( this, "Hydrogen", tr( "New instrument name" ), QLineEdit::Normal, sOldName, &bIsOkPressed );
1097
1098 if ( bIsOkPressed && sNewName != sOldName ) {
1099 auto pHydrogen = Hydrogen::get_instance();
1100
1101 m_pInstrument->set_name( sNewName );
1103
1104 pHydrogen->setIsModified( true );
1105
1106#ifdef H2CORE_HAVE_JACK
1107 pHydrogen->getAudioEngine()->lock( RIGHT_HERE );
1108 pHydrogen->renameJackPorts( pHydrogen->getSong() );
1109 pHydrogen->getAudioEngine()->unlock();
1110#endif
1111
1112 // this will force an update...
1114 }
1115 else {
1116 // user entered nothing or pressed Cancel
1117 }
1118 }
1119}
1120
1121
1123{
1124 if (!m_pInstrument) {
1125 return;
1126 }
1127 m_nSelectedLayer = nLayer;
1128
1129 auto pComponent = m_pInstrument->get_component( m_nSelectedComponent );
1130 if(pComponent && nLayer >= 0 ){
1131 auto pLayer = pComponent->get_layer( nLayer );
1132 m_pWaveDisplay->updateDisplay( pLayer );
1133 if ( pLayer != nullptr ) {
1134 char tmp[20];
1135
1136 // Layer GAIN
1138 m_pLayerGainRotary->setValue( pLayer->get_gain() );
1139 sprintf( tmp, "%#.2f", pLayer->get_gain() );
1140 m_pLayerGainLCD->setText( tmp );
1141
1142 //Component GAIN
1143 char tmp2[20];
1144 sprintf( tmp2, "%#.2f", pComponent->get_gain());
1146 m_pCompoGainRotary->setValue( pComponent->get_gain());
1147 m_pCompoGainLCD->setText( tmp2 );
1148
1149 // Layer PITCH
1150 float fCoarsePitch = round( pLayer->get_pitch() );
1151 float fFinePitch = pLayer->get_pitch() - fCoarsePitch;
1153 m_pLayerPitchCoarseRotary->setValue( fCoarsePitch );
1155 m_pLayerPitchFineRotary->setValue( fFinePitch * 100 );
1156
1157 m_pLayerPitchCoarseLCD->setText( QString( "%1" ).arg( (int) fCoarsePitch ) );
1158 m_pLayerPitchFineLCD->setText( QString( "%1" )
1159 .arg( fFinePitch * 100, 0, 'f', 0 ) );
1160
1163 }
1164 else {
1165 // Layer GAIN
1168 m_pLayerGainLCD->setText( "" );
1169
1170 //Component GAIN
1173 m_pCompoGainLCD->setText( "" );
1174
1175 // Layer PITCH
1180
1181 m_pLayerPitchCoarseLCD->setText( "" );
1182 m_pLayerPitchFineLCD->setText( "" );
1183
1186 }
1187 }
1188 else {
1189 m_pWaveDisplay->updateDisplay( nullptr );
1190
1191 // Layer GAIN
1194 m_pLayerGainLCD->setText( "" );
1195
1198 m_pCompoGainLCD->setText( "" );
1199
1200 // Layer PITCH
1205
1206 m_pLayerPitchCoarseLCD->setText( "" );
1207 m_pLayerPitchFineLCD->setText( "" );
1208
1211 }
1212}
1213
1214
1215
1217{
1218 assert( m_pInstrument );
1219
1220 m_pInstrument->set_mute_group( static_cast<int>(fValue) );
1221 selectedInstrumentChangedEvent(); // force an update
1222}
1223
1230
1232{
1233 assert( m_pInstrument );
1234
1237 selectedInstrumentChangedEvent(); // force an update
1238}
1239
1241 assert( m_pInstrument );
1242
1243 if ( fValue != 0.0 ) {
1244 m_pInstrument->set_midi_out_channel( std::max( static_cast<int>(fValue) - 1,
1245 -1 ) );
1246 } else {
1247 if ( m_fPreviousMidiOutChannel == -1.0 ) {
1249 return;
1250 } else {
1252 return;
1253 }
1254 }
1255
1257}
1258
1260 assert( m_pInstrument );
1261
1262 m_pInstrument->set_midi_out_note( static_cast<int>(fValue) );
1263}
1264
1266{
1267 popCompo->popup( m_pCompoNameLbl->mapToGlobal( QPoint( m_pCompoNameLbl->width() - 40, m_pCompoNameLbl->height() / 2 ) ) );
1268}
1269
1271{
1272 popCompo->clear();
1273
1274 for( int i = 0; i < itemsCompo.size(); i++ ) {
1275 if ( itemsCompo.at(i) != "--sep--" ){
1276 popCompo->addAction( itemsCompo.at(i) );
1277 }else{
1278 popCompo->addSeparator();
1279 }
1280 }
1281}
1282
1284{
1285 bool bFoundFreeSlot = true;
1286 auto pDrumkitComponentList = Hydrogen::get_instance()->getSong()->getComponents();
1287 for ( const auto& pComponent : *pDrumkitComponentList ) {
1288 if ( pComponent->get_id() == startingPoint ) {
1289 bFoundFreeSlot = false;
1290 break;
1291 }
1292 }
1293
1294 if(bFoundFreeSlot) {
1295 return startingPoint;
1296 } else {
1297 return findFreeDrumkitComponentId( startingPoint + 1 );
1298 }
1299}
1300
1302{
1303 QString sSelectedAction = pAction->text();
1304
1305 Hydrogen * pHydrogen = Hydrogen::get_instance();
1306
1307 if( sSelectedAction.compare("add") == 0 ) {
1308 if ( m_pInstrument ) {
1309 bool bIsOkPressed;
1310 QString sNewName = QInputDialog::getText( this, "Hydrogen", tr( "Component name" ), QLineEdit::Normal, "New Component", &bIsOkPressed );
1311 if ( bIsOkPressed ) {
1312 auto pDrumkitComponent = std::make_shared<DrumkitComponent>( findFreeDrumkitComponentId(), sNewName );
1313 pHydrogen->getSong()->getComponents()->push_back( pDrumkitComponent );
1314
1315 //auto instrument_component = std::make_shared<InstrumentComponent>( dm_component->get_id() );
1316 //instrument_component->set_gain( 1.0f );
1317 //m_pInstrument->get_components()->push_back( instrument_component );
1318
1319 m_nSelectedComponent = pDrumkitComponent->get_id();
1320 m_pLayerPreview->set_selected_component( pDrumkitComponent->get_id() );
1321
1323
1324 // this will force an update...
1326
1327#ifdef H2CORE_HAVE_JACK
1328 pHydrogen->renameJackPorts(pHydrogen->getSong());
1329#endif
1330 }
1331 else {
1332 // user entered nothing or pressed Cancel
1333 }
1334 }
1335 }
1336 else if( sSelectedAction.compare("delete") == 0 ) {
1337 auto pDrumkitComponents = pHydrogen->getSong()->getComponents();
1338
1339 if(pDrumkitComponents->size() == 1){
1340 ERRORLOG( "There is just a single component remaining. This one can not be deleted." );
1341 return;
1342 }
1343
1344 auto pDrumkitComponent = pHydrogen->getSong()->getComponent( m_nSelectedComponent );
1345
1346 auto pInstruments = pHydrogen->getSong()->getInstrumentList();
1347 for ( int n = ( int )pInstruments->size() - 1; n >= 0; n-- ) {
1348 auto pInstrument = pInstruments->get( n );
1349 for( int o = 0 ; o < pInstrument->get_components()->size() ; o++ ) {
1350 auto pInstrumentComponent = pInstrument->get_components()->at( o );
1351 if( pInstrumentComponent->get_drumkit_componentID() == pDrumkitComponent->get_id() ) {
1352 pInstrument->get_components()->erase( pInstrument->get_components()->begin() + o );;
1353 break;
1354 }
1355 }
1356 }
1357
1358 for ( int n = 0 ; n < pDrumkitComponents->size() ; n++ ) {
1359 auto pTmpDrumkitComponent = pDrumkitComponents->at( n );
1360 if( pTmpDrumkitComponent->get_id() == pDrumkitComponent->get_id() ) {
1361 pDrumkitComponents->erase( pDrumkitComponents->begin() + n );
1362 break;
1363 }
1364 }
1365
1366 m_nSelectedComponent = pDrumkitComponents->front()->get_id();
1367
1368
1370 // this will force an update...
1372 }
1373 else if( sSelectedAction.compare("rename") == 0 ) {
1374 labelCompoClicked( nullptr );
1375 }
1376 else {
1378 auto pDrumkitComponents = pHydrogen->getSong()->getComponents();
1379 for ( const auto& pComponent : *pDrumkitComponents ) {
1380 if ( pComponent->get_name().compare( sSelectedAction ) == 0) {
1381 m_nSelectedComponent = pComponent->get_id();
1382 m_pCompoNameLbl->setText( pComponent->get_name() );
1383 break;
1384 }
1385 }
1386
1388 INFOLOG("Component needs to be added");
1389
1390 auto pInstrComponent = std::make_shared<InstrumentComponent>( m_nSelectedComponent );
1391 pInstrComponent->set_gain( 1.0f );
1392
1393 m_pInstrument->get_components()->push_back( pInstrComponent );
1394
1395
1396
1397#ifdef H2CORE_HAVE_JACK
1398 pHydrogen->renameJackPorts(pHydrogen->getSong());
1399#endif
1400 }
1401
1403
1405
1406 // this will force an update...
1408 }
1409}
1410
1412{
1413 assert( m_pInstrument );
1414
1415 if ( selected == 0 ){
1417 }
1418 else if ( selected == 1 ){
1420 }
1421 else if ( selected == 2){
1423 }
1424
1425 selectedInstrumentChangedEvent(); // force an update
1426}
1427
1429{
1430 assert( m_pInstrument );
1431 m_pInstrument->set_hihat_grp( static_cast<int>(fValue) );
1432}
1433
1435{
1436 assert( m_pInstrument );
1437 m_pInstrument->set_lower_cc( static_cast<int>(fValue) );
1438 m_pHihatMaxRangeLCD->setMinimum( static_cast<int>(fValue) );
1439}
1440
1442{
1443 assert( m_pInstrument );
1444 m_pInstrument->set_higher_cc( static_cast<int>(fValue) );
1445 m_pHihatMinRangeLCD->setMaximum( static_cast<int>(fValue) );
1446}
1447
1449 auto pPref = H2Core::Preferences::get_instance();
1450
1451 if ( changes & H2Core::Preferences::Changes::Colors ) {
1452 setStyleSheet( QString( "QLabel { background: %1 }" )
1453 .arg( pPref->getColorTheme()->m_windowColor.name() ) );
1454 }
1455}
1456
1458 if ( bShow ) {
1459 m_pInstrumentProp->hide();
1460 m_pShowInstrumentBtn->setChecked( false );
1461 m_pLayerProp->show();
1462 m_pShowLayersBtn->setChecked( true );
1463 }
1464 else {
1465 m_pInstrumentProp->show();
1466 m_pShowInstrumentBtn->setChecked( true );
1467 m_pLayerProp->hide();
1468 m_pShowLayersBtn->setChecked( false );
1469 }
1470}
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
Definition AudioEngine.h:59
#define INFOLOG(x)
Definition Object.h:237
#define WARNINGLOG(x)
Definition Object.h:238
#define ERRORLOG(x)
Definition Object.h:239
This dialog is used to preview audiofiles.
QStringList getSelectedFiles()
Generic Button with SVG icons or text.
Definition Button.h:60
@ Push
Button is not set checkable.
@ Toggle
Button is set checkable.
void setIsActive(bool bIsActive)
Definition Button.cpp:99
Custom QLabel that emits a signal when clicked.
void setText(const QString &sNewText)
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static bool dir_readable(const QString &path, bool silent=false)
returns true if the given path is a readable regular directory
Hydrogen Audio Engine.
Definition Hydrogen.h:54
void renameJackPorts(std::shared_ptr< Song > pSong)
Calls audioEngine_renameJackPorts() if Preferences::m_bJackTrackOuts is set to true.
Definition Hydrogen.cpp:931
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:122
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
std::shared_ptr< Instrument > getSelectedInstrument() const
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
float get_filter_resonance() const
get the filter resonance of the instrument
Definition Instrument.h:525
float get_filter_cutoff() const
get the filter cutoff of the instrument
Definition Instrument.h:535
int get_mute_group() const
get the mute group of the instrument
Definition Instrument.h:427
void set_name(const QString &name)
get the name of the instrument
Definition Instrument.h:389
void set_pitch_offset(float val)
set the pitch offset of the instrument
Definition Instrument.h:575
const QString & get_name() const
set the id of the instrument
Definition Instrument.h:395
float get_gain() const
get gain of the instrument
Definition Instrument.h:495
float get_pitch_offset() const
get the pitch offset of the instrument
Definition Instrument.h:585
bool get_apply_velocity() const
Definition Instrument.h:721
void set_sample_selection_alg(SampleSelectionAlgo selected_algo)
Definition Instrument.h:636
bool is_stop_notes() const
get the stop notes of the instrument
Definition Instrument.h:631
void set_filter_resonance(float val)
set the filter resonance of the instrument
Definition Instrument.h:520
int get_higher_cc() const
set the path of the related drumkit
Definition Instrument.h:671
void set_random_pitch_factor(float val)
set the random pitch factor of the instrument
Definition Instrument.h:570
void set_filter_active(bool active)
activate the filter of the instrument
Definition Instrument.h:510
int get_hihat_grp() const
Definition Instrument.h:651
int get_lower_cc() const
Definition Instrument.h:661
std::shared_ptr< InstrumentComponent > get_component(int DrumkitComponentID)
void set_midi_out_channel(int channel)
set the midi out channel of the instrument
Definition Instrument.h:437
void set_apply_velocity(bool apply_velocity)
Definition Instrument.h:716
int get_midi_out_note() const
get the midi out note of the instrument
Definition Instrument.h:450
void set_stop_notes(bool stopnotes)
set the stop notes status of the instrument
Definition Instrument.h:626
void set_gain(float gain)
set gain of the instrument
Definition Instrument.h:490
void set_midi_out_note(int note)
set the midi out note of the instrument
Definition Instrument.h:455
void set_hihat_grp(int hihat_grp)
Definition Instrument.h:646
float get_random_pitch_factor() const
get the random pitch factor of the instrument
Definition Instrument.h:580
void set_mute_group(int group)
set the mute group of the instrument
Definition Instrument.h:422
std::shared_ptr< ADSR > get_adsr() const
get the ADSR of the instrument
Definition Instrument.h:412
void set_filter_cutoff(float val)
set the filter cutoff of the instrument
Definition Instrument.h:530
bool is_filter_active() const
get the status of the filter of the instrument
Definition Instrument.h:515
void set_higher_cc(int message)
Definition Instrument.h:666
SampleSelectionAlgo sample_selection_alg() const
Definition Instrument.h:641
void set_lower_cc(int message)
Definition Instrument.h:656
std::vector< std::shared_ptr< InstrumentComponent > > * get_components()
Definition Instrument.h:711
int get_midi_out_channel() const
get the midi out channel of the instrument
Definition Instrument.h:432
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
void setLastOpenLayerDirectory(QString sPath)
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ Colors
At least one of the colors has changed.
QString getLastOpenLayerDirectory() const
static std::shared_ptr< Sample > load(const QString &filepath, const License &license=License())
Definition Sample.cpp:136
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
void showSampleEditor(QString name, int mSelectedComponemt, int mSelectedLayer)
static InstrumentEditorPanel * get_instance()
Rotary * m_pRandomPitchRotary
void labelCompoClicked(ClickableLabel *pRef)
ClickableLabel * m_pLayerPitchLbl
PixmapWidget * m_pInstrumentPropTop
LCDSpinBox * m_pMidiOutNoteLCD
Rotary * m_pPitchCoarseRotary
LCDDisplay * m_pInstrumentGainLCD
LCDSpinBox * m_pHihatMaxRangeLCD
void selectLayer(int nLayer)
ClickableLabel * m_pGainLbl
ClickableLabel * m_pMidiOutNoteLbl
Button * m_buttonDropDownCompo
ClickableLabel * m_pLayerGainLbl
void showLayers(bool bShow)
Used by #Shotlist.
ClickableLabel * m_pPitchFineLbl
ClickableLabel * m_pMuteGroupLbl
ClickableLabel * m_pCompoNameLbl
void hihatGroupChanged(double fValue)
ClickableLabel * m_pReleaseLbl
double m_fPreviousMidiOutChannel
In order to allow for enumerations starting at 1 while using -1 to turn off the LCD.
LCDDisplay * m_pLayerPitchFineLCD
ClickableLabel * m_pHihatGroupLbl
void labelClicked(ClickableLabel *pRef)
ClickableLabel * m_pNameLbl
PixmapWidget * m_pInstrumentProp
void muteGroupChanged(double fValue)
ClickableLabel * m_pCutoffLbl
ClickableLabel * m_pDecayLbl
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void onIsApplyVelocityCheckBoxClicked(bool on)
void onIsStopNoteCheckBoxClicked(bool on)
ClickableLabel * m_pAttackLbl
void selectComponent(int nComponent)
QCheckBox * m_pApplyVelocity
void compoChangeAddDelete(QAction *)
ClickableLabel * m_pHihatMinRangeLbl
virtual void drumkitLoadedEvent() override
virtual void instrumentParametersChangedEvent(int) override
ClickableLabel * m_pCompoGainLbl
ClickableLabel * m_pLayerPitchFineLbl
LCDDisplay * m_pLayerPitchCoarseLCD
Rotary * m_pLayerPitchCoarseRotary
ClickableLabel * m_pIsStopNoteLbl
Button * m_pShowInstrumentBtn
ClickableLabel * m_pResonanceLbl
PixmapWidget * m_pLayerProp
ClickableLabel * m_pPitchCoarseLbl
WaveDisplay * m_pWaveDisplay
ClickableLabel * m_pApplyVelocityLbl
ClickableLabel * m_pLayerPitchCoarseLbl
virtual void selectedInstrumentChangedEvent() override
ClickableLabel * m_pSustainLbl
virtual void updateSongEvent(int) override
ClickableLabel * m_pHihatMaxRangeLbl
LCDSpinBox * m_pMidiOutChannelLCD
void hihatMinRangeChanged(double fValue)
LayerPreview * m_pLayerPreview
Rotary * m_pLayerPitchFineRotary
static int findFreeDrumkitComponentId(int startingPoint=0)
InstrumentEditor(QWidget *parent)
LCDSpinBox * m_pMuteGroupLCD
LCDDisplay * m_pLayerGainLCD
void hihatMaxRangeChanged(double fValue)
LCDCombo * m_sampleSelectionAlg
LCDDisplay * m_pCompoGainLCD
void rotaryChanged(WidgetWithInput *ref)
ClickableLabel * m_pPitchLbl
LCDSpinBox * m_pHihatMinRangeLCD
std::shared_ptr< H2Core::Instrument > m_pInstrument
QScrollArea * m_pLayerScrollArea
LCDSpinBox * m_pHihatGroupLCD
void midiOutNoteChanged(double fValue)
void waveDisplayDoubleClicked(QWidget *pRef)
void midiOutChannelChanged(double fValue)
QCheckBox * m_pIsStopNoteCheckBox
ClickableLabel * m_pMidiOutChannelLbl
ClickableLabel * m_pSampleSelectionLbl
ClickableLabel * m_pPitchRandomLbl
LCDDisplay * m_pPitchLCD
void addItem(const QString &text, const QVariant &userData=QVariant())
Definition LCDCombo.cpp:63
Non-interactive display used for both numerical values and the status display.
Definition LCDDisplay.h:40
Custom spin box.
Definition LCDSpinBox.h:50
void setValue(double fValue)
void setSelectedLayer(int nSelectedLayer)
void set_selected_component(int SelectedComponent)
void setPixmap(QString sPixmapPath, bool expand_horiz=false)
Custom rotary widget.
Definition Rotary.h:45
@ Center
The arc features a point at its upmost position.
@ Normal
The arc is of solid red color.
virtual void updateDisplay(std::shared_ptr< H2Core::InstrumentLayer > pLayer)
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 setDefaultValue(float fDefaultValue)
void setIsActive(bool bIsActive)
float getValue() const
float getMax() const
#define UNUSED(v)
Definition Globals.h:42
@ EVENT_SELECTED_INSTRUMENT_CHANGED
Definition EventQueue.h:77