57 , m_bIsSelected( false )
64 int h = pPref->getPatternEditorGridHeight();
67 QFont nameFont( pPref->getLevel2FontFamily(),
getPointSize( pPref->getFontSize() ) );
78 pCommonStrings->getSmallMuteButton(),
79 true, QSize(), tr(
"Mute instrument"),
83 m_pMuteBtn->setObjectName(
"InstrumentLineMuteButton" );
90 pCommonStrings->getSmallSoloButton(),
91 false, QSize(), tr(
"Solo"),
95 m_pSoloBtn->setObjectName(
"InstrumentLineSoloButton" );
99 "warning.svg",
"",
false, QSize(),
100 tr(
"Some samples for this instrument failed to load." ),
123 auto selectNotesAction =
m_pFunctionPopup->addAction( tr(
"Select notes" ) );
124 connect( selectNotesAction, &QAction::triggered,
this,
135 auto deleteAction =
m_pFunctionPopup->addAction( tr(
"Delete instrument" ) );
136 connect( deleteAction, &QAction::triggered,
this, [=](){
188 textColor = pPref->getColorTheme()->m_patternEditor_selectedRowTextColor;
190 textColor = pPref->getColorTheme()->m_patternEditor_textColor;
197 }" ).arg( textColor.name() ) );
216 QPainter painter(
this);
218 QColor backgroundColor;
220 backgroundColor = pPref->getColorTheme()->m_patternEditor_selectedRowColor.darker( 114 );
224 backgroundColor = pPref->getColorTheme()->m_patternEditor_backgroundColor.darker( 120 );
226 backgroundColor = pPref->getColorTheme()->m_patternEditor_alternateRowColor.darker( 132 );
231 bool bHovered =
false;
237 backgroundColor, bHovered );
240 if ( (
m_bIsSelected && pHydrogenApp->getPatternEditorPanel() !=
nullptr &&
241 pHydrogenApp->getPatternEditorPanel()->getDrumPatternEditor()->hasFocus() &&
242 ! pHydrogenApp->hideKeyboardCursor() ) ||
249 pen.setColor( pPref->getColorTheme()->m_highlightColor);
251 pen.setColor( pPref->getColorTheme()->m_cursorColor );
255 painter.setPen( pen );
256 painter.setRenderHint( QPainter::Antialiasing );
258 height() - 2 ), 4, 4 );
293 if ( bSamplesMissing ) {
305 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
306 if ( pSong ==
nullptr ) {
311 auto pInstrList = pSong->getInstrumentList();
313 if ( pInstr ==
nullptr ) {
314 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
330 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
331 if ( pSong ==
nullptr ) {
336 auto pInstrList = pSong->getInstrumentList();
338 if ( pInstr ==
nullptr ) {
339 ERRORLOG( QString(
"Unable to retrieve instrument [%1]" )
352 QMessageBox::information(
this,
"Hydrogen",
353 tr(
"One or more samples for this instrument failed to load. This may be because the"
354 " songfile uses an older default drumkit. This might be fixed by opening a new "
368 if ( ev->button() == Qt::LeftButton ) {
371 if ( pSong ==
nullptr ) {
376 if ( pInstr !=
nullptr && pInstr->hasSamples() ) {
379 const float fVelocity = std::min((
float)ev->x()/(
float)nWidth, 1.0f);
380 Note *pNote =
new Note( pInstr, 0, fVelocity);
384 }
else if (ev->button() == Qt::RightButton ) {
390 ERRORLOG(
"A dialog is still opened. It needs to be closed first." );
400 PixmapWidget::mousePressEvent(ev);
411 assert( pPatternList !=
nullptr );
414 if ( nSelectedPatternNumber != -1 &&
415 nSelectedPatternNumber < pPatternList->size() ) {
416 Pattern* pCurrentPattern = pPatternList->
get( nSelectedPatternNumber );
417 return pCurrentPattern;
431 if ( pSelectedInstrument ==
nullptr ) {
432 ERRORLOG(
"No instrument selected" );
436 if ( selectedPatternNr == -1 ) {
441 std::list< Note* > noteList;
444 Note *pNote = it->second;
447 noteList.push_back( pNote );
450 if( noteList.size() > 0 ){
460 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
461 if ( pSong ==
nullptr ) {
469 if ( sSerialized.isEmpty() ) {
470 ERRORLOG( QString(
"Unable to serialize instrument line [%1]" )
475 QClipboard *clipboard = QApplication::clipboard();
476 clipboard->setText( sSerialized );
483 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
484 if ( pSong ==
nullptr ) {
491 std::list<Pattern*> patternList;
494 QClipboard *clipboard = QApplication::clipboard();
495 QString sSerialized = clipboard->text();
496 if ( ! pSong->pasteInstrumentLineFromString( sSerialized,
503 if (patternList.size() <= 0) {
515 PatternList *pPatternList = pSong->getPatternList();
517 if ( pSelectedInstrument ==
nullptr ) {
518 ERRORLOG(
"No instrument selected" );
523 pUndo->beginMacro( tr(
"Delete all notes on %1" ).arg( pSelectedInstrument->get_name() ) );
524 for (
int nPattern = 0; nPattern < pPatternList->
size(); nPattern++ ) {
525 std::list< Note* > noteList;
526 Pattern *pPattern = pPatternList->
get( nPattern );
529 if ( it->second->get_instrument() == pSelectedInstrument ) {
530 noteList.push_back( it->second );
533 if ( noteList.size() > 0 ) {
576 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
578 QStringList notePositions;
581 if (pCurrentPattern !=
nullptr) {
582 int nPatternSize = pCurrentPattern->
get_length();
584 if ( pSelectedInstrument ==
nullptr ) {
585 ERRORLOG(
"No instrument selected" );
590 for (
int i = 0; i < nPatternSize; i += nResolution) {
591 bool noteAlreadyPresent =
false;
594 Note *pNote = it->second;
597 noteAlreadyPresent =
true;
602 if ( noteAlreadyPresent ==
false ) {
603 notePositions << QString(
"%1").arg(i);
636 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
638 QStringList noteVeloValue;
639 QStringList oldNoteVeloValue;
642 if (pCurrentPattern !=
nullptr) {
643 int nPatternSize = pCurrentPattern->
get_length();
645 if ( pSelectedInstrument ==
nullptr ) {
646 ERRORLOG(
"No instrument selected" );
651 for (
int i = 0; i < nPatternSize; i += nResolution) {
654 Note *pNote = it->second;
656 float fVal = ( rand() % 100 ) / 100.0;
657 oldNoteVeloValue << QString(
"%1").arg( pNote->
get_velocity() );
665 noteVeloValue << QString(
"%1").arg(fVal);
683 if ( pSelectedInstrument ==
nullptr ) {
684 ERRORLOG(
"No instrument selected" );
688 QString sOldName = pSelectedInstrument->get_name();
690 QString sNewName = QInputDialog::getText(
this,
"Hydrogen", tr(
"New instrument name" ), QLineEdit::Normal, sOldName, &bIsOkPressed );
691 if ( bIsOkPressed ) {
692 pSelectedInstrument->set_name( sNewName );
746 setAcceptDrops(
true);
759 QScrollArea *pScrollArea =
dynamic_cast< QScrollArea *
>( parentWidget()->parentWidget() );
760 assert( pScrollArea );
788 if ( nEvent == 0 || nEvent == 1 ) {
799 auto pSong = pHydrogen->getSong();
800 auto pInstrList = pSong->getInstrumentList();
802 unsigned nInstruments = pInstrList->size();
804 if ( nInstr < nInstruments &&
814 auto pSong = pHydrogen->getSong();
815 auto pInstrList = pSong->getInstrumentList();
817 unsigned nSelectedInstr = pHydrogen->getSelectedInstrumentNumber();
819 unsigned nInstruments = pInstrList->size();
821 if ( nInstr < nInstruments &&
836 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
837 auto pInstrList = pSong->getInstrumentList();
841 unsigned nInstruments = pInstrList->size();
843 if ( nInstr >= nInstruments ) {
849 resize( width(), newHeight );
861 resize( width(), newHeight );
864 auto pInstr = pInstrList->get(nInstr);
868 pLine->
setName( pInstr->get_name() );
870 pLine->
setMuted( pInstr->is_muted() );
881 event->acceptProposedAction();
887 if ( ! event->mimeData()->hasFormat(
"text/plain") ) {
893 std::shared_ptr<Song> pSong = pHydrogen->getSong();
894 auto pInstrumentList = pSong->getInstrumentList();
895 int nInstruments = pInstrumentList->size();
898 QMessageBox::critical(
this,
"Hydrogen", tr(
"Unable to insert further instruments. Maximum possible number" ) +
903 QString sText =
event->mimeData()->text();
906 if ( sText.startsWith(
"Songs:") ||
907 sText.startsWith(
"Patterns:") ||
908 sText.startsWith(
"move pattern:") ||
909 sText.startsWith(
"drag pattern:") ) {
913 if (sText.startsWith(
"move instrument:")) {
915 int nSourceInstrument = pHydrogen->getSelectedInstrumentNumber();
920 int pos_y = (
event->pos().x() >=
m_nEditorWidth ) ? event->pos().y() - 50 :
event->pos().y();
924 if( nTargetInstrument >= pInstrumentList->size() ){
925 nTargetInstrument = pInstrumentList->size() - 1;
928 if ( nSourceInstrument == nTargetInstrument ) {
929 event->acceptProposedAction();
936 event->acceptProposedAction();
938 if( sText.startsWith(
"importInstrument:") ) {
941 sText = sText.remove(0,QString(
"importInstrument:").length());
943 QStringList tokens = sText.split(
"::" );
944 QString sDrumkitPath = tokens.at( 0 );
945 QString sInstrumentName = tokens.at( 1 );
953 if ( event->pos().x() > 181 ) {
954 nTargetInstrument = (
event->pos().y() - 90 ) /
m_nGridHeight ;
957 if( nTargetInstrument > pInstrumentList->size() ){
958 nTargetInstrument = pInstrumentList->size();
963 if ( sDrumkitPath.isEmpty() ) {
964 QMessageBox::critical(
this,
"Hydrogen", pCommonString->getInstrumentLoadError() );
971 event->acceptProposedAction();
979 if (event->button() == Qt::LeftButton) {
989 if (!(event->buttons() & Qt::LeftButton)) {
998 if ( pSelectedInstrument ==
nullptr ) {
999 ERRORLOG(
"No instrument selected" );
1003 QString sText = QString(
"move instrument:%1").arg( pSelectedInstrument->get_name() );
1005 QDrag *pDrag =
new QDrag(
this);
1006 QMimeData *pMimeData =
new QMimeData;
1008 pMimeData->setText( sText );
1009 pDrag->setMimeData( pMimeData);
1012 pDrag->exec( Qt::CopyAction | Qt::MoveAction );
1016 QWidget::mouseMoveEvent(event);
1023 if ( nInstrumentNumber == -1 ) {
1027 if ( pInstrumentLine !=
nullptr ) {
1028 auto pInstrument = pInstrumentList->get( ii );
1029 if ( pInstrument ==
nullptr ) {
1030 ERRORLOG( QString(
"Instrument [%1] associated to InstrumentLine [%1] not found" )
1035 pInstrumentLine->setName( pInstrument->get_name() );
1036 pInstrumentLine->setMuted( pInstrument->is_muted() );
1037 pInstrumentLine->setSoloed( pInstrument->is_soloed() );
1043 auto pInstrument = pInstrumentList->get( nInstrumentNumber );
1044 if ( pInstrument ==
nullptr ) {
1045 ERRORLOG( QString(
"Instrument [%1] not found" )
1046 .arg( nInstrumentNumber ) );
1051 if ( pInstrumentLine ==
nullptr ) {
1052 ERRORLOG( QString(
"No InstrumentLine for instrument [%1] created yet" )
1053 .arg( nInstrumentNumber ) );
1057 pInstrumentLine->setName( pInstrument->get_name() );
1058 pInstrumentLine->setMuted( pInstrument->is_muted() );
1059 pInstrumentLine->setSoloed( pInstrument->is_soloed() );
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define FOREACH_NOTE_CST_IT_BOUND_LENGTH(_notes, _it, _bound, _pattern)
Iterate over all notes in column _bound in an immutable way if it is contained in _pattern.
#define FOREACH_NOTE_CST_IT_BEGIN_END(_notes, _it)
Iterate over all provided notes in an immutable way.
virtual void updateEditor(bool bPatternOnly=false) override
void unlock()
Mutex unlocking of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
Sampler * getSampler() const
bool setStripIsMuted(int nStrip, bool isMuted)
bool setStripIsSoloed(int nStrip, bool isSoloed)
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
bool hasJackAudioDriver() const
void renameJackPorts(std::shared_ptr< Song > pSong)
Calls audioEngine_renameJackPorts() if Preferences::m_bJackTrackOuts is set to true.
std::shared_ptr< Song > getSong() const
Get the current song.
int getSelectedInstrumentNumber() const
int getSelectedPatternNumber() const
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
AudioEngine * getAudioEngine() const
std::shared_ptr< Instrument > getSelectedInstrument() const
CoreActionController * getCoreActionController() const
A note plays an associated instrument with a velocity left and right pan.
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
float get_velocity() const
__velocity accessor
PatternList is a collection of patterns.
int size() const
returns the numbers of patterns
Pattern * get(int idx)
get a pattern from the list
Pattern class is a Note container.
int get_length() const
set the denominator of the pattern
const notes_t * get_notes() const
get the virtual pattern set
std::multimap< int, Note * > notes_t
< multimap note type
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
unsigned getPatternEditorGridHeight()
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ Font
Either the font size or font family have changed.
@ Colors
At least one of the colors has changed.
void noteOn(Note *pNote)
Start playing a note.
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
QUndoStack * m_pUndoStack
PatternEditorPanel * getPatternEditorPanel()
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
QMenu * m_pFunctionPopupSub
void setRowSelection(RowSelection rowSelection)
virtual void enterEvent(QEvent *ev)
void selectInstrumentNotes()
InstrumentLine(QWidget *pParent)
virtual void mousePressEvent(QMouseEvent *ev) override
virtual void mouseDoubleClickEvent(QMouseEvent *ev) override
virtual void leaveEvent(QEvent *ev)
void functionDeleteNotesAllPatterns()
void functionFillNotes(int every)
void setNumber(int nIndex)
void functionFillEveryTwelveNotes()
void functionRenameInstrument()
void functionCopyAllInstrumentPatterns()
void functionClearNotes()
void functionFillEverySixNotes()
void functionFillEveryThreeNotes()
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void setMuted(bool isMuted)
void setSelected(bool isSelected)
Button * m_pSampleWarning
void functionPasteAllInstrumentPatterns()
void setSamplesMissing(bool bSamplesMissing)
H2Core::Pattern * getCurrentPattern()
void functionFillAllNotes()
void setSoloed(bool soloed)
void setName(const QString &sName)
static constexpr int m_nButtonWidth
void sampleWarningClicked()
virtual void paintEvent(QPaintEvent *ev) override
void functionCutNotesAllPatterns()
void functionRandomizeVelocity()
int m_nInstrumentNumber
The related instrument number.
void functionFillEverySixteenNotes()
void functionFillEveryTwoNotes()
bool m_bEntered
Whether the cursor entered the boundary of the widget.
void functionFillEveryEightNotes()
void functionFillEveryFourNotes()
~PatternEditorInstrumentList()
virtual void mouseMoveEvent(QMouseEvent *event) override
void updateInstrumentLines()
Update every InstrumentLine, create or destroy lines if necessary.
InstrumentLine * createInstrumentLine()
Create a new InstrumentLine.
PatternEditorPanel * m_pPatternEditorPanel
virtual void mousePressEvent(QMouseEvent *event) override
PatternEditorInstrumentList(QWidget *parent, PatternEditorPanel *pPatternEditorPanel)
virtual void drumkitLoadedEvent() override
virtual void instrumentParametersChangedEvent(int) override
DragScroller * m_pDragScroller
virtual void dragEnterEvent(QDragEnterEvent *event) override
virtual void selectedInstrumentChangedEvent() override
virtual void updateSongEvent(int nEvent) override
void repaintInstrumentLines()
QPoint __drag_start_position
virtual void dropEvent(QDropEvent *event) override
H2Core::Pattern * m_pPattern
InstrumentLine * m_pInstrumentLine[MAX_INSTRUMENTS]
void selectInstrumentNotes(int nInstrument)
DrumPatternEditor * getDrumPatternEditor()
bool isUsingTriplets() const
uint getResolution() const
static void drawListBackground(QPainter *p, QRect rect, QColor background, bool bHovered)
Draws the background of a row in both the pattern list of the SongEditor and the instrument list in t...
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
#define MAX_NOTES
Maximum number of notes.
@ EVENT_SELECTED_INSTRUMENT_CHANGED