79 auto pAudioEngine = pHydrogen->getAudioEngine();
82 ERRORLOG(
"FIXME: skipping pattern editor update (state should be READY or PLAYING)" );
89 auto pSong = pHydrogen->getSong();
90 int nInstruments = pSong->getInstrumentList()->size();
105 bool bDoAdd,
bool bDoDelete,
114 if ( pSong ==
nullptr ) {
119 auto pSelectedInstrument = pSong->getInstrumentList()->get( nRow );
120 if ( pSelectedInstrument ==
nullptr ) {
121 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
129 float oldVelocity = 0.8f;
131 float oldLeadLag = 0.0f;
132 float fProbability = 1.0f;
135 bool isNoteOff = bIsNoteOff;
137 if ( pOldNote && !bDoDelete ) {
140 }
else if ( !pOldNote && !bDoAdd ) {
148 fOldPan = pOldNote->
getPan();
150 oldNoteKeyVal = pOldNote->
get_key();
185 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
186 if ( pSong ==
nullptr ) {
189 int nInstruments = pSong->getInstrumentList()->size();
191 if (row >= nInstruments) {
194 int nColumn =
getColumn( ev->x(),
true );
204 auto pSelectedInstrument = pSong->getInstrumentList()->get( row );
205 if ( pSelectedInstrument ==
nullptr ) {
206 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
211 if ( ev->button() == Qt::LeftButton ) {
215 ev->modifiers() & Qt::ShiftModifier );
218 }
else if ( ev->button() == Qt::RightButton ) {
226 if ( ! pHydrogenApp->hideKeyboardCursor() ) {
244 auto pSong = pHydrogen->getSong();
245 int nInstruments = pSong->getInstrumentList()->size();
246 int nRow =
static_cast<int>( ev->y() /
static_cast<float>(
m_nGridHeight) );
247 if ( nRow >= nInstruments || nRow < 0 ) {
251 pHydrogen->setSelectedInstrumentNumber( nRow );
255 bool bOldCursorHidden = pHydrogenApp->hideKeyboardCursor();
256 pHydrogenApp->setHideKeyboardCursor(
true );
259 if ( bOldCursorHidden != pHydrogenApp->hideKeyboardCursor() ) {
268 int nColumn =
getColumn( ev->x(),
true );
275 pHydrogen->setSelectedInstrumentNumber( nRow );
292 auto pSong = pHydrogen->getSong();
296 int nRow = std::floor(
static_cast<float>(ev->y()) /
298 pHydrogen->setSelectedInstrumentNumber( nRow );
299 auto pSelectedInstrument = pHydrogen->getSelectedInstrument();
301 if ( pSelectedInstrument ==
nullptr ) {
302 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
313 if ( ev->button() == Qt::RightButton ) {
319 static_cast<int>(std::floor(
325 pSelectedInstrument,
false );
340 static_cast<int>(std::floor(
static_cast<float>(ev->y()) /
351 int nSelectedPatternNumber,
361 bool isInstrumentMode,
366 auto pSong = pHydrogen->
getSong();
368 if ( pSong ==
nullptr ) {
373 PatternList *pPatternList = pSong->getPatternList();
375 if ( nSelectedPatternNumber < 0 ||
376 nSelectedPatternNumber >= pPatternList->
size() ) {
377 ERRORLOG( QString(
"Invalid pattern number [%1]" )
378 .arg( nSelectedPatternNumber ) );
382 auto pPattern = pPatternList->
get( nSelectedPatternNumber );
383 if ( pPattern ==
nullptr ) {
384 ERRORLOG( QString(
"Pattern found for pattern number [%1] is not valid" )
385 .arg( nSelectedPatternNumber ) );
389 auto pSelectedInstrument = pSong->getInstrumentList()->get( nInstrumentRow );
390 if ( pSelectedInstrument ==
nullptr ) {
391 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
392 .arg( nInstrumentRow ) );
404 Note *pNote = it->second;
405 if ( pNote ==
nullptr ) {
409 if ( pNote->
get_instrument()->get_id() == pSelectedInstrument->get_id() &&
411 ( pNote->
get_key() == oldNoteKeyVal &&
422 ERRORLOG(
"Did not find note to delete" );
427 unsigned nPosition = nColumn;
428 float fVelocity = oldVelocity;
429 float fPan = fOldPan ;
430 int nLength = oldLength;
440 Note *pNote =
new Note( pSelectedInstrument, nPosition, fVelocity, fPan, nLength );
447 pPattern->insert_note( pNote );
457 if ( listen && !isNoteOff && pSelectedInstrument->hasSamples() ) {
458 Note *pNote2 =
new Note( pSelectedInstrument, 0, fVelocity, fPan, nLength);
482 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
485 PatternList *pPatternList = pSong->getPatternList();
486 auto pInstrumentList = pSong->getInstrumentList();
488 Note *pFoundNote =
nullptr;
490 if ( nPattern < 0 || nPattern > pPatternList->
size() ) {
491 ERRORLOG(
"Invalid pattern number" );
496 auto pFromInstrument = pInstrumentList->get( nRow );
497 auto pToInstrument = pInstrumentList->get( nNewRow );
500 Note *pCandidateNote = it->second;
508 pFoundNote = pCandidateNote;
515 if ( pFoundNote ==
nullptr ) {
516 ERRORLOG(
"Couldn't find note to move" );
522 if ( pFromInstrument == pToInstrument ) {
528 Note *pNewNote =
new Note( pFoundNote, pToInstrument );
561 if ( offset.x() == 0 && offset.y() == 0 ) {
571 pUndo->beginMacro(
"copy notes" );
573 pUndo->beginMacro(
"move notes" );
575 std::list< Note * > selectedNotes;
577 selectedNotes.push_back( pNote );
588 for (
auto pNote : selectedNotes ) {
589 int nInstrument = pInstrumentList->index( pNote->get_instrument() );
590 int nPosition = pNote->get_position();
591 int nNewInstrument = nInstrument + offset.y();
592 int nNewPosition = nPosition + offset.x();
593 if ( nNewInstrument < 0 || nNewInstrument >= pInstrumentList->size()
604 pNote->get_velocity(),
606 pNote->get_lead_lag(),
609 pNote->get_probability(),
614 pNote->get_note_off() ) );
624 pNote->get_velocity(),
626 pNote->get_lead_lag(),
629 pNote->get_probability(),
634 pNote->get_note_off() ) );
638 nNewPosition, nNewInstrument, pNote ) );
659 bool bOldCursorHidden = pHydrogenApp->hideKeyboardCursor();
661 const int nBlockSize = 5, nWordSize = 5;
664 int nMaxInstrument = pHydrogen->
getSong()->getInstrumentList()->size();
665 bool bUnhideCursor =
true;
670 if ( bIsSelectionKey ) {
672 }
else if ( ev->matches( QKeySequence::MoveToNextChar ) || ev->matches( QKeySequence::SelectNextChar ) ) {
676 }
else if ( ev->matches( QKeySequence::MoveToNextWord ) || ev->matches( QKeySequence::SelectNextWord ) ) {
680 }
else if ( ev->matches( QKeySequence::MoveToEndOfLine ) || ev->matches( QKeySequence::SelectEndOfLine ) ) {
684 }
else if ( ev->matches( QKeySequence::MoveToPreviousChar ) || ev->matches( QKeySequence::SelectPreviousChar ) ) {
688 }
else if ( ev->matches( QKeySequence::MoveToPreviousWord ) || ev->matches( QKeySequence::SelectPreviousWord ) ) {
692 }
else if ( ev->matches( QKeySequence::MoveToStartOfLine ) || ev->matches( QKeySequence::SelectStartOfLine ) ) {
696 }
else if ( ev->matches( QKeySequence::MoveToNextLine ) || ev->matches( QKeySequence::SelectNextLine ) ) {
697 if ( nSelectedInstrument + 1 < nMaxInstrument ) {
700 }
else if ( ev->matches( QKeySequence::MoveToEndOfBlock ) || ev->matches( QKeySequence::SelectEndOfBlock ) ) {
702 nMaxInstrument-1 ) );
704 }
else if ( ev->matches( QKeySequence::MoveToNextPage ) || ev->matches( QKeySequence::SelectNextPage ) ) {
706 QWidget *pParent =
dynamic_cast< QWidget *
>( parent() );
710 if ( nSelectedInstrument >= nMaxInstrument ) {
711 nSelectedInstrument = nMaxInstrument - 1;
715 }
else if ( ev->matches( QKeySequence::MoveToEndOfDocument ) || ev->matches( QKeySequence::SelectEndOfDocument ) ) {
718 }
else if ( ev->matches( QKeySequence::MoveToPreviousLine ) || ev->matches( QKeySequence::SelectPreviousLine ) ) {
719 if ( nSelectedInstrument > 0 ) {
722 }
else if ( ev->matches( QKeySequence::MoveToStartOfBlock ) || ev->matches( QKeySequence::SelectStartOfBlock ) ) {
725 }
else if ( ev->matches( QKeySequence::MoveToPreviousPage ) || ev->matches( QKeySequence::SelectPreviousPage ) ) {
726 QWidget *pParent =
dynamic_cast< QWidget *
>( parent() );
729 if ( nSelectedInstrument < 0 ) {
730 nSelectedInstrument = 0;
734 }
else if ( ev->matches( QKeySequence::MoveToStartOfDocument ) || ev->matches( QKeySequence::SelectStartOfDocument ) ) {
737 }
else if ( ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return ) {
742 }
else if ( ev->key() == Qt::Key_Delete ) {
744 bUnhideCursor =
false;
755 }
else if ( ev->matches( QKeySequence::SelectAll ) ) {
756 bUnhideCursor =
false;
759 }
else if ( ev->matches( QKeySequence::Deselect ) ) {
760 bUnhideCursor =
false;
763 }
else if ( ev->matches( QKeySequence::Copy ) ) {
764 bUnhideCursor =
false;
767 }
else if ( ev->matches( QKeySequence::Paste ) ) {
768 bUnhideCursor =
false;
771 }
else if ( ev->matches( QKeySequence::Cut ) ) {
772 bUnhideCursor =
false;
777 pHydrogenApp->setHideKeyboardCursor(
true );
779 if ( bOldCursorHidden != pHydrogenApp->hideKeyboardCursor() ) {
786 if ( bUnhideCursor ) {
787 pHydrogenApp->setHideKeyboardCursor(
false );
799 if ( ! pHydrogenApp->hideKeyboardCursor() ) {
820 std::vector<SelectionIndex> result;
822 return std::move( result );
826 auto pInstrList = pSong->getInstrumentList();
836 if ( r.top() == r.bottom() && r.left() == r.right() ) {
837 r += QMargins( 2, 2, 2, 2 );
839 r += QMargins( 4, h/2, 4, h/2 );
848 for (
auto it = notes->lower_bound( x_min ); it != notes->end() && it->first <= x_max; ++it ) {
849 Note *note = it->second;
854 if ( r.contains( QPoint( x_pos, y_pos + h/2) ) ) {
855 result.push_back( note );
859 return std::move( result );
899 auto pInstrumentList = pHydrogen->
getSong()->getInstrumentList();
905 std::list< QUndoCommand *> actions;
909 pInstrumentList->index( pNote->get_instrument() ),
912 pNote->get_velocity(),
914 pNote->get_lead_lag(),
917 pNote->get_probability(),
922 pNote->get_note_off() ) );
927 pUndo->beginMacro(
"delete notes");
928 for ( QUndoCommand *pAction : actions ) {
929 pUndo->push( pAction );
948 QClipboard *clipboard = QApplication::clipboard();
952 int nDeltaPos = 0, nDeltaInstrument = 0;
955 if ( ! doc.setContent( clipboard->text() ) ) {
960 XMLNode selection = doc.firstChildElement(
"noteSelection" );
961 if ( ! selection.isNull() ) {
966 noteList = selection.firstChildElement(
"noteList" );
967 if ( noteList.isNull() ) {
971 XMLNode positionNode = selection.firstChildElement(
"sourcePosition" );
976 if ( !positionNode.isNull() ) {
980 nDeltaPos = nCurrentPos - positionNode.
read_int(
"position", nCurrentPos );
981 nDeltaInstrument = nCurrentInstrument - positionNode.
read_int(
"instrument", nCurrentInstrument );
985 XMLNode instrumentLine = doc.firstChildElement(
"instrument_line" );
986 if ( ! instrumentLine.isNull() ) {
993 XMLNode patternList = instrumentLine.firstChildElement(
"patternList" );
994 if ( patternList.isNull() ) {
997 XMLNode pattern = patternList.firstChildElement(
"pattern" );
998 if ( pattern.isNull() ) {
1002 if ( ! pattern.nextSiblingElement(
"pattern" ).isNull() ) {
1003 QMessageBox::information(
this,
"Hydrogen", tr(
"Cannot paste multi-pattern selection" ) );
1006 noteList = pattern.firstChildElement(
"noteList" );
1007 if ( noteList.isNull() ) {
1016 if ( noteList.hasChildNodes() ) {
1018 pUndo->beginMacro(
"paste notes" );
1019 for (
XMLNode n = noteList.firstChildElement(
"note" ); ! n.isNull(); n = n.nextSiblingElement() ) {
1022 int nInstrument = pInstrList->index( pNote->
get_instrument() ) + nDeltaInstrument;
1024 if ( nPos >= 0 && nPos < m_pPattern->get_length()
1025 && nInstrument >= 0 && nInstrument < pInstrList->size() ) {
1063 auto pInstrList = pSong->getInstrumentList();
1078 if ( pNotes->size() == 0 ) {
1081 bool bIsForeground = ( pPattern ==
m_pPattern );
1083 std::vector< int > noteCount;
1084 std::stack<std::shared_ptr<Instrument>> instruments;
1089 for (
auto posIt = pNotes->begin(); posIt != pNotes->end(); ) {
1090 if ( posIt->first >= pPattern->get_length() ) {
1096 int nPosition = posIt->second->get_position();
1099 auto noteIt = posIt;
1100 while ( noteIt != pNotes->end() && noteIt->second->get_position() == nPosition ) {
1101 Note *pNote = noteIt->second;
1104 if ( nInstrumentID >= noteCount.size() ) {
1105 noteCount.resize( nInstrumentID+1, 0 );
1108 if ( ++noteCount[ nInstrumentID ] == 1) {
1112 drawNote( pNote, painter, bIsForeground );
1118 while ( ! instruments.empty() ) {
1119 auto pInstrument = instruments.top();
1120 int nInstrumentID = pInstrument->get_id();
1121 if ( noteCount[ nInstrumentID ] > 1 ) {
1123 int nInstrument = pInstrList->index( pInstrument );
1126 const int boxWidth = 128;
1128 QFont font( pPref->getApplicationFontFamily(),
getPointSize( pPref->getFontSize() ) );
1129 painter.setFont( font );
1130 painter.setPen( QColor( 0, 0, 0 ) );
1132 painter.drawText( QRect( x-boxWidth-6, y, boxWidth,
m_nGridHeight),
1133 Qt::AlignRight | Qt::AlignVCenter,
1134 ( QString(
"%1" ) + QChar( 0x00d7 )).arg( noteCount[ nInstrumentID ] ) );
1136 noteCount[ nInstrumentID ] = 0;
1157 if ( nInstrument == -1 ) {
1158 ERRORLOG(
"Instrument not found..skipping note" );
1173 const QColor backgroundColor( pPref->getColorTheme()->m_patternEditor_backgroundColor );
1174 const QColor backgroundInactiveColor( pPref->getColorTheme()->m_windowColor );
1175 const QColor alternateRowColor( pPref->getColorTheme()->m_patternEditor_alternateRowColor );
1176 const QColor selectedRowColor( pPref->getColorTheme()->m_patternEditor_selectedRowColor );
1177 const QColor lineColor( pPref->getColorTheme()->m_patternEditor_lineColor );
1178 const QColor lineInactiveColor( pPref->getColorTheme()->m_windowTextColor.darker( 170 ) );
1180 std::shared_ptr<Song> pSong = pHydrogen->getSong();
1181 int nInstruments = pSong->getInstrumentList()->size();
1182 int nSelectedInstrument = pHydrogen->getSelectedInstrumentNumber();
1187 backgroundInactiveColor);
1190 for (
int ii = 0; ii < nInstruments; ii++ ) {
1192 if ( ii == nSelectedInstrument ) {
1196 else if ( ( ii % 2 ) != 0 ) {
1211 for (
int ii = 0; ii < nInstruments; ii++ ) {
1213 if ( ii == nSelectedInstrument ) {
1216 if ( ( ii % 2 ) == 0 ) {
1229 p.setPen( QPen( lineColor, 1, Qt::SolidLine ) );
1230 for ( uint i = 0; i < (uint)nInstruments; i++ ) {
1236 p.setPen( QPen( lineInactiveColor, 1, Qt::SolidLine ) );
1237 for ( uint i = 0; i < (uint)nInstruments; i++ ) {
1244 p.setPen( lineColor );
1248 p.setPen( lineInactiveColor );
1252 p.setPen( QPen( lineColor, 2, Qt::SolidLine ) );
1261 qreal pixelRatio = devicePixelRatio();
1285 qreal pixelRatio = devicePixelRatio();
1290 QPainter painter(
this );
1291 painter.drawPixmap( ev->rect(), *
m_pBackgroundPixmap, QRectF( pixelRatio * ev->rect().x(),
1292 pixelRatio * ev->rect().y(),
1293 pixelRatio * ev->rect().width(),
1294 pixelRatio * ev->rect().height() ) );
1304 painter.drawLine( nX, 0, nX, height() );
1316 QPen p( pPref->getColorTheme()->m_cursorColor );
1318 painter.setPen( p );
1319 painter.setBrush( Qt::NoBrush );
1320 painter.setRenderHint( QPainter::Antialiasing );
1334 QColor color = pPref->getColorTheme()->m_highlightColor;
1339 if ( ! hasFocus() ) {
1340 color.setAlpha( 125 );
1346 nStartY +
HydrogenApp::get_instance()->getPatternEditorPanel()->getDrumPatternEditorScrollArea()->viewport()->size().height() );
1347 int nEndX = std::min( nStartX +
HydrogenApp::get_instance()->getPatternEditorPanel()->getDrumPatternEditorScrollArea()->viewport()->size().width(), width() );
1351 painter.setPen( pen );
1352 painter.drawLine( QPoint( nStartX, nStartY ), QPoint( nEndX, nStartY ) );
1353 painter.drawLine( QPoint( nStartX, nStartY ), QPoint( nStartX, nEndY ) );
1354 painter.drawLine( QPoint( nEndX, nStartY ), QPoint( nEndX, nEndY ) );
1355 painter.drawLine( QPoint( nEndX, nEndY ), QPoint( nStartX, nEndY ) );
1392 int nSelectedPatternNumber,
1393 int nSelectedInstrument,
1402 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
1406 if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->size() ) ) {
1407 pPattern = pPatternList->
get( nSelectedPatternNumber );
1410 if( pPattern !=
nullptr ) {
1413 Note *pNote = it->second;
1416 if ( pNote->
get_instrument() != pSong->getInstrumentList()->get( nSelectedInstrument ) ) {
1461 auto pSong = pHydrogen->
getSong();
1462 PatternList* pPatternList = pSong->getPatternList();
1463 Pattern* pPattern = pPatternList->
get( nPatternNumber );
1464 if ( pPattern ==
nullptr ) {
1465 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1466 .arg( nPatternNumber ) );
1470 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1471 if ( pSelectedInstrument ==
nullptr ) {
1472 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1473 .arg( nSelectedInstrument ) );
1486 Pattern* pPattern = pPatternList->
get( patternNumber );
1487 if ( pPattern ==
nullptr ) {
1488 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1489 .arg( patternNumber ) );
1493 std::list < H2Core::Note *>::const_iterator pos;
1494 for ( pos = noteList.begin(); pos != noteList.end(); ++pos){
1496 pNote =
new Note(*pos);
1513 while (appliedList.size() > 0)
1516 Pattern *pApplied = appliedList.front();
1529 Note *pNote = it->second;
1536 Note *pFoundNote = it->second;
1549 appliedList.pop_front();
1567 std::list < H2Core::Pattern *>::iterator pos;
1568 for ( pos = changeList.begin(); pos != changeList.end(); ++pos)
1589 Note *pNote = it->second;
1593 bool noteExists =
false;
1597 Note *pFoundNote = it->second;
1615 appliedList.push_back(pApplied);
1630 auto pSong = pHydrogen->
getSong();
1631 PatternList* pPatternList = pSong->getPatternList();
1632 Pattern* pPattern = pPatternList->
get( patternNumber );
1633 if ( pPattern ==
nullptr ) {
1634 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1635 .arg( patternNumber ) );
1639 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1640 if ( pSelectedInstrument ==
nullptr ) {
1641 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1642 .arg( nSelectedInstrument ) );
1648 for (
int i = 0; i < noteList.size(); i++ ) {
1649 int nColumn = noteList.value(i).toInt();
1652 Note *pNote = it->second;
1672 auto pSong = pHydrogen->
getSong();
1673 PatternList* pPatternList = pSong->getPatternList();
1674 Pattern* pPattern = pPatternList->
get( patternNumber );
1675 if ( pPattern ==
nullptr ) {
1676 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1677 .arg( patternNumber ) );
1681 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1682 if ( pSelectedInstrument ==
nullptr ) {
1683 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1684 .arg( nSelectedInstrument ) );
1689 for (
int i = 0; i < noteList.size(); i++ ) {
1692 int position = noteList.value(i).toInt();
1693 Note *pNote =
new Note( pSelectedInstrument, position );
1706 auto pSong = pHydrogen->
getSong();
1707 PatternList* pPatternList = pSong->getPatternList();
1708 Pattern* pPattern = pPatternList->
get( selectedPatternNumber );
1709 if ( pPattern ==
nullptr ) {
1710 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1711 .arg( selectedPatternNumber ) );
1715 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1716 if ( pSelectedInstrument ==
nullptr ) {
1717 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1718 .arg( nSelectedInstrument ) );
1725 int positionCount = 0;
1726 for (
int i = 0; i < pPattern->
get_length(); i += nResolution) {
1729 Note *pNote = it->second;
1731 float velocity = noteVeloValue.value( positionCount ).toFloat();
1750 std::shared_ptr<Song> pSong = pHydrogen->getSong();
1751 auto pInstrumentList = pSong->getInstrumentList();
1753 if ( ( nTargetInstrument > (
int)pInstrumentList->size() ) || ( nTargetInstrument < 0) ) {
1758 pInstrumentList->move( nSourceInstrument, nTargetInstrument );
1760 pHydrogen->renameJackPorts( pSong );
1763 pHydrogen->setSelectedInstrumentNumber( nTargetInstrument );
1765 pHydrogen->setIsModified(
true );
1774 auto pDrumkitComponents = pHydrogen->
getSong()->getComponents();
1776 for (
const auto& nComponent : *AddedComponents ) {
1778 for (
int n = 0 ; n < pDrumkitComponents->size() ; n++ ) {
1779 auto pTmpDrumkitComponent = pDrumkitComponents->at( n );
1780 if ( pTmpDrumkitComponent->get_id() == nComponent ) {
1781 pDrumkitComponents->erase( pDrumkitComponents->begin() + n );
1801 auto pSong = pHydrogen->getSong();
1804 if ( pNewInstrument ==
nullptr ||
1805 ( pNewInstrument->get_name() ==
"Empty Instrument" &&
1806 pNewInstrument->get_drumkit_path().isEmpty() ) ){
1808 QMessageBox::critical(
this,
"Hydrogen", pCommonString->getInstrumentLoadError() );
1813 pHydrogen->getSoundLibraryDatabase()->getDrumkit( sDrumkitPath );
1814 if( pNewDrumkit ==
nullptr ){
1815 ERRORLOG( QString(
"Unable to load drumkit [%1]" ).arg( sDrumkitPath ) );
1824 auto pOldInstrumentComponents =
new std::vector<std::shared_ptr<InstrumentComponent>>( pNewInstrument->get_components()->begin(), pNewInstrument->get_components()->end() );
1825 pNewInstrument->get_components()->clear();
1827 for (
auto pComponent : *(pNewDrumkit->get_components()) ) {
1828 int nOldID = pComponent->get_id();
1832 int nNewID = pSong->findExistingComponent( pComponent->get_name() );
1834 if ( nNewID == -1 ) {
1840 nNewID = pSong->findFreeComponentID();
1842 pAddedComponents->push_back( nNewID );
1844 pComponent->set_id( nNewID );
1845 pComponent->set_name( pSong->makeComponentNameUnique( pComponent->get_name() ) );
1846 auto pNewComponent = std::make_shared<DrumkitComponent>( pComponent );
1847 pSong->getComponents()->push_back( pNewComponent );
1850 for (
auto pOldInstrCompo : *pOldInstrumentComponents ) {
1851 if( pOldInstrCompo->get_drumkit_componentID() == nOldID ) {
1852 auto pNewInstrCompo = std::make_shared<InstrumentComponent>( pOldInstrCompo );
1853 pNewInstrCompo->set_drumkit_componentID( nNewID );
1855 pNewInstrument->get_components()->push_back( pNewInstrCompo );
1860 pOldInstrumentComponents->clear();
1861 delete pOldInstrumentComponents;
1865 for ( uint i = 0; i < pSong->getInstrumentList()->size(); ++i ) {
1866 auto pInstr = pSong->getInstrumentList()->get( i );
1867 if ( pInstr->get_id() > nID ) {
1868 nID = pInstr->get_id();
1873 pNewInstrument->set_id( nID );
1875 pSong->getInstrumentList()->add( pNewInstrument );
1877 pHydrogen->renameJackPorts( pSong );
1879 pHydrogen->setIsModified(
true );
1886 pHydrogen->setSelectedInstrumentNumber(nTargetInstrument);
1894 auto pSong = pHydrogen->
getSong();
1895 std::shared_ptr<Instrument> pNewInstrument;
1896 if( sDrumkitPath ==
"" ){
1897 pNewInstrument = std::make_shared<Instrument>( pSong->getInstrumentList()->size() -1, sInstrumentName );
1901 if( pNewInstrument ==
nullptr ) {
1907 for ( uint i = 0; i < pSong->getInstrumentList()->size(); ++i ) {
1908 auto pInstr = pSong->getInstrumentList()->get( i );
1909 if ( pInstr->get_id() > nID ) {
1910 nID = pInstr->get_id();
1915 pNewInstrument->set_id( nID );
1918 pSong->getInstrumentList()->add( pNewInstrument );
1932 PatternList *pPatternList = pSong->getPatternList();
1939 if(noteList.size() > 0 ){
1940 std::list < H2Core::Note *>::const_iterator pos;
1941 for ( pos = noteList.begin(); pos != noteList.end(); ++pos){
1942 Note *pNote =
new Note( *pos, pNewInstrument );
1957 auto pSong = pHydrogen->
getSong();
1959 if ( pSong ==
nullptr ) {
1981 auto pSong = pHydrogen->getSong();
1983 if ( pSong ==
nullptr ) {
1988 auto pList = pSong->getInstrumentList();
1994 for ( uint i = 0; i < pList->size(); ++i ) {
1995 auto pInstr = pList->get( i );
1996 if ( pInstr !=
nullptr &&
1997 ( pInstr->get_id() > nID ) ) {
1998 nID = pInstr->get_id();
2003 auto pNewInstr = std::make_shared<Instrument>( nID,
"New instrument");
2004 pNewInstr->set_drumkit_path( pSong->getLastLoadedDrumkitPath() );
2005 pNewInstr->set_drumkit_name( pSong->getLastLoadedDrumkitName() );
2007 pList->add( pNewInstr );
2009 pHydrogen->renameJackPorts( pSong );
2011 pHydrogen->setIsModified(
true );
2014 pHydrogen->setSelectedInstrumentNumber( pList->size() - 1 );
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define FOREACH_NOTE_CST_IT_BOUND_END(_notes, _it, _bound)
Iterate over all notes in column _bound in an immutable way.
#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_IT_BOUND_END(_notes, _it, _bound)
Iterate over all notes in column _bound in a mutable way.
#define FOREACH_NOTE_CST_IT_BEGIN_END(_notes, _it)
Iterate over all provided notes in an immutable way.
#define FOREACH_NOTE_CST_IT_BEGIN_LENGTH(_notes, _it, _pattern)
Iterate over all accessible notes between position 0 and length of _pattern in an immutable way.
void functionClearNotesUndoAction(std::list< H2Core::Note * > noteList, int nSelectedInstrument, int patternNumber)
virtual void hideEvent(QHideEvent *ev) override
void functionRandomVelocityAction(QStringList noteVeloValue, int nSelectedInstrument, int selectedPatternNumber)
virtual void mouseDragUpdateEvent(QMouseEvent *ev) override
Update the state during a Selection drag.
void drawNote(H2Core::Note *pNote, QPainter &painter, bool bIsForeground=true)
Draw a note.
virtual void keyReleaseEvent(QKeyEvent *ev) override
virtual void updateEditor(bool bPatternOnly=false) override
virtual void mousePressEvent(QMouseEvent *ev) override
Raw Qt mouse events are passed to the Selection.
void functionDropInstrumentUndoAction(int nTargetInstrument, std::vector< int > *AddedComponents)
virtual std::vector< SelectionIndex > elementsIntersecting(QRect r) override
Find all elements which intersect a selection area.
virtual void selectionMoveEndEvent(QInputEvent *ev) override
Move or copy notes.
DrumPatternEditor(QWidget *parent, PatternEditorPanel *panel)
void drawPattern(QPainter &painter)
Draws a pattern.
virtual QRect getKeyboardCursorRect() override
The screen area occupied by the keyboard cursor.
void functionAddEmptyInstrumentUndo()
void functionMoveInstrumentAction(int nSourceInstrument, int nTargetInstrument)
void addOrRemoveNote(int nColumn, int nRealColumn, int row, bool bDoAdd=true, bool bDoDelete=true, bool bIsNoteOff=false)
virtual void selectAll() override
void functionAddEmptyInstrumentRedo()
void onPreferencesChanged(H2Core::Preferences::Changes changes)
void drawBackground(QPainter &pointer)
void moveNoteAction(int nColumn, int nRow, int nPattern, int nNewColumn, int nNewRow, H2Core::Note *note)
virtual void songModeActivationEvent() override
virtual void drumkitLoadedEvent() override
virtual void keyPressEvent(QKeyEvent *ev) override
Handle key press events.
virtual void paste() override
Paste selection.
virtual void showEvent(QShowEvent *ev) override
virtual void mouseDragStartEvent(QMouseEvent *ev) override
void functionFillNotesRedoAction(QStringList noteList, int nSelectedInstrument, int patternNumber)
void createBackground() override
Updates m_pBackgroundPixmap to show the latest content.
virtual void selectedInstrumentChangedEvent() override
void addOrDeleteNoteAction(int nColumn, int row, int selectedPatternNumber, int oldLength, float oldVelocity, float fOldPan, float oldLeadLag, int oldNoteKeyVal, int oldOctaveKeyVal, float probability, bool listen, bool isMidi, bool isInstrumentMode, bool isNoteOff, bool isDelete)
void functionFillNotesUndoAction(QStringList noteList, int nSelectedInstrument, int patternNumber)
virtual void mouseClickEvent(QMouseEvent *ev) override
virtual void paintEvent(QPaintEvent *ev) override
virtual void deleteSelection() override
void undoRedoAction(int column, NotePropertiesRuler::Mode mode, int nSelectedPatternNumber, int nSelectedInstrument, float velocity, float pan, float leadLag, float probability, int noteKeyVal, int octaveKeyVal)
NotePropertiesRuler undo redo action.
void functionPasteNotesUndoAction(std::list< H2Core::Pattern * > &appliedList)
void functionClearNotesRedoAction(int nSelectedInstrument, int selectedPatternNumber)
========================================================== undo / redo actions from pattern editor in...
virtual void selectedPatternChangedEvent() override
void functionDeleteInstrumentUndoAction(std::list< H2Core::Note * > noteList, int nSelectedInstrument, QString instrumentName, QString drumkitName)
void drawFocus(QPainter &painter)
void functionPasteNotesRedoAction(std::list< H2Core::Pattern * > &changeList, std::list< H2Core::Pattern * > &appliedList)
void functionDropInstrumentRedoAction(QString sDrumkitPath, QString sInstrumentName, int nTargetInstrument, std::vector< int > *pAddedComponents)
@ Playing
Transport is rolling.
@ Ready
Ready to process audio.
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
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.
void removeInstrument(int nInstrumentNumber)
Delete an #Instrument.
int getSelectedInstrumentNumber() const
void setSelectedInstrumentNumber(int nInstrument, bool bTriggerEvent=true)
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
static std::shared_ptr< Instrument > load_instrument(const QString &drumkit_path, const QString &instrument_name)
creates a new Instrument, loads samples from a given instrument within a given drumkit
A note plays an associated instrument with a velocity left and right pan.
int get_position() const
__position accessor
void set_lead_lag(float value)
__lead_lag setter
void set_key_octave(const QString &str)
parse str and set __key and __octave
static Note * load_from(XMLNode *node, std::shared_ptr< InstrumentList > instruments, bool bSilent=false)
load a note from an XMLNode
Octave get_octave()
__octave accessor
void set_probability(float value)
void set_position(int value)
__position setter
std::shared_ptr< Instrument > get_instrument()
__instrument accessor
float get_lead_lag() const
__lead_lag accessor
void set_just_recorded(bool value)
__just_recorded setter
int get_length() const
__length accessor
int get_pattern_idx() const
__pattern_idx accessor
float get_velocity() const
__velocity accessor
bool get_note_off() const
__note_off accessor
void setPan(float val)
set pan of the note.
void set_velocity(float value)
__velocity setter
void set_note_off(bool value)
__note_off setter
Key get_key()
__key accessor
float get_probability() const
float getPan() const
get pan of the note.
int get_instrument_id() const
__instrument_id accessor
PatternList is a collection of patterns.
Pattern * find(const QString &name)
find a pattern within the 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.
const QString & get_info() const
get the category of the pattern
const QString & get_name() const
set the category of the pattern
const QString & get_category() const
set the length of the pattern
void purge_instrument(std::shared_ptr< Instrument > instr, bool bRequiredLock=true)
delete the notes referencing the given instrument The function is thread safe (it locks the audio dat...
void remove_note(Note *note)
removes a given note from __notes, it's not deleted
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
Note * find_note(int idx_a, int idx_b, std::shared_ptr< Instrument > instrument, bool strict=true) const
search for a note at a given index within __notes which correspond to the given arguments
void insert_note(Note *note)
insert a new note within __notes
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
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.
XMLDoc is a subclass of QDomDocument with read and write methods.
XMLNode is a subclass of QDomNode with read and write values methods.
int read_int(const QString &node, int default_value, bool inexistent_ok=true, bool empty_ok=true, bool bSilent=false)
reads an integer stored into a child node
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
QUndoStack * m_pUndoStack
PatternEditorPanel * getPatternEditorPanel()
virtual void selectedInstrumentChangedEvent() override
void repaintInstrumentLines()
void setCursorPosition(int nCursorPosition)
const QScrollBar * getVerticalScrollBar() const
void updateEditors(bool bPatternOnly=false)
PatternEditorInstrumentList * getInstrumentList()
int moveCursorLeft(int n=1)
void ensureCursorVisible()
PatternEditorRuler * getPatternEditorRuler()
const QScrollBar * getHorizontalScrollBar() const
int moveCursorRight(int n=1)
virtual void mouseDragUpdateEvent(QMouseEvent *ev) override
virtual void validateSelection() override
Ensure that the Selection contains only valid elements.
int m_nSelectedPatternNumber
virtual void mousePressEvent(QMouseEvent *ev) override
Raw Qt mouse events are passed to the Selection.
virtual void updateModifiers(QInputEvent *ev)
Update the status of modifier keys in response to input events.
virtual void selectNone()
int granularity() const
Granularity of grid positioning (in ticks)
void storeNoteProperties(const H2Core::Note *pNote)
Stores the properties of pNote in member variables.
static void triggerStatusMessage(H2Core::Note *pNote, Mode mode)
void drawNoteSymbol(QPainter &p, QPoint pos, H2Core::Note *pNote, bool bIsForeground=true) const
Draw a note.
static constexpr int nMargin
PatternEditorPanel * m_pPatternEditorPanel
H2Core::AudioEngine * m_pAudioEngine
H2Core::Note * m_pDraggedNote
void updatePatternInfo()
Update current pattern information.
virtual void mouseDragStartEvent(QMouseEvent *ev) override
virtual void copy()
Copy selection to clipboard in XML.
std::vector< H2Core::Pattern * > getPatternsToShow(void)
Get notes to show in pattern editor.
QPixmap * m_pBackgroundPixmap
int getColumn(int x, bool bUseFineGrained=false) const
H2Core::Pattern * m_pPattern
void invalidateBackground()
void updateWidth()
Adjusts m_nActiveWidth and m_nEditorWidth to the current state of the editor.
Selection< SelectionIndex > m_selection
The Selection object.
QPoint movingGridOffset() const
bool m_bEntered
Indicates whether the mouse pointer entered the widget.
bool m_bBackgroundInvalid
void drawGridLines(QPainter &p, Qt::PenStyle style=Qt::SolidLine) const
Draw lines for note grid.
void paintSelection(QPainter *painter)
Paint selection-related elements (ie lasso)
bool isLasso() const
Is there an ongoing lasso gesture?
void addToSelection(Elem e)
void removeFromSelection(Elem e, bool bCheck=true)
void updateWidgetGroup()
Update any widgets in this selection group.
void clearSelection(bool bCheck=true)
bool keyPressEvent(QKeyEvent *ev)
Key press event filter.
void updateKeyboardCursorPosition(QRect cursor)
Update the keyboard cursor.
bool isSelected(Elem e) const
Is an element in the set of currently selected elements?
static void setPlayheadPen(QPainter *p, bool bHovered=false)
static int getPlayheadShaftOffset()
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
@ EVENT_SELECTED_INSTRUMENT_CHANGED