80 auto pAudioEngine = pHydrogen->getAudioEngine();
83 ERRORLOG(
"FIXME: skipping pattern editor update (state should be READY or PLAYING)" );
90 auto pSong = pHydrogen->getSong();
91 int nInstruments = pSong->getInstrumentList()->size();
106 bool bDoAdd,
bool bDoDelete,
115 if ( pSong ==
nullptr ) {
120 auto pSelectedInstrument = pSong->getInstrumentList()->get( nRow );
121 if ( pSelectedInstrument ==
nullptr ) {
122 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
130 float oldVelocity = 0.8f;
132 float oldLeadLag = 0.0f;
133 float fProbability = 1.0f;
136 bool isNoteOff = bIsNoteOff;
138 if ( pOldNote && !bDoDelete ) {
141 }
else if ( !pOldNote && !bDoAdd ) {
149 fOldPan = pOldNote->
getPan();
151 oldNoteKeyVal = pOldNote->
get_key();
186 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
187 if ( pSong ==
nullptr ) {
193 int nInstruments = pSong->getInstrumentList()->size();
194 int row = (int)( pEv->position().y() / (
float)
m_nGridHeight);
195 if (row >= nInstruments) {
198 int nColumn =
getColumn( pEv->position().x(),
true );
206 if ( nColumn >= (
int)
m_pPattern->get_length() ) {
209 auto pSelectedInstrument = pSong->getInstrumentList()->get( row );
210 if ( pSelectedInstrument ==
nullptr ) {
211 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
216 if ( ev->button() == Qt::LeftButton ) {
220 ev->modifiers() & Qt::ShiftModifier );
223 }
else if ( ev->button() == Qt::RightButton ) {
231 if ( ! pHydrogenApp->hideKeyboardCursor() ) {
251 auto pSong = pHydrogen->getSong();
252 int nInstruments = pSong->getInstrumentList()->size();
253 int nRow =
static_cast<int>( pEv->position().y() /
255 if ( nRow >= nInstruments || nRow < 0 ) {
259 pHydrogen->setSelectedInstrumentNumber( nRow );
263 bool bOldCursorHidden = pHydrogenApp->hideKeyboardCursor();
264 pHydrogenApp->setHideKeyboardCursor(
true );
267 if ( bOldCursorHidden != pHydrogenApp->hideKeyboardCursor() ) {
276 int nColumn =
getColumn( pEv->position().x(),
true );
283 pHydrogen->setSelectedInstrumentNumber( nRow );
302 auto pSong = pHydrogen->getSong();
306 int nRow = std::floor(
static_cast<float>(pEv->position().y()) /
308 pHydrogen->setSelectedInstrumentNumber( nRow );
309 auto pSelectedInstrument = pHydrogen->getSelectedInstrument();
311 if ( pSelectedInstrument ==
nullptr ) {
312 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
321 int nColumn =
getColumn( pEv->position().x() );
323 if ( ev->button() == Qt::RightButton ) {
329 static_cast<int>(std::floor(
335 pSelectedInstrument,
false );
351 static_cast<int>(std::floor(
static_cast<float>(pEv->position().y()) /
362 int nSelectedPatternNumber,
372 bool isInstrumentMode,
377 auto pSong = pHydrogen->
getSong();
379 if ( pSong ==
nullptr ) {
384 PatternList *pPatternList = pSong->getPatternList();
386 if ( nSelectedPatternNumber < 0 ||
387 nSelectedPatternNumber >= pPatternList->
size() ) {
388 ERRORLOG( QString(
"Invalid pattern number [%1]" )
389 .arg( nSelectedPatternNumber ) );
393 auto pPattern = pPatternList->
get( nSelectedPatternNumber );
394 if ( pPattern ==
nullptr ) {
395 ERRORLOG( QString(
"Pattern found for pattern number [%1] is not valid" )
396 .arg( nSelectedPatternNumber ) );
400 auto pSelectedInstrument = pSong->getInstrumentList()->get( nInstrumentRow );
401 if ( pSelectedInstrument ==
nullptr ) {
402 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
403 .arg( nInstrumentRow ) );
415 Note *pNote = it->second;
416 if ( pNote ==
nullptr ) {
420 if ( pNote->
get_instrument()->get_id() == pSelectedInstrument->get_id() &&
422 ( pNote->
get_key() == oldNoteKeyVal &&
433 ERRORLOG(
"Did not find note to delete" );
438 unsigned nPosition = nColumn;
439 float fVelocity = oldVelocity;
440 float fPan = fOldPan ;
441 int nLength = oldLength;
451 Note *pNote =
new Note( pSelectedInstrument, nPosition, fVelocity, fPan, nLength );
458 pPattern->insert_note( pNote );
468 if ( listen && !isNoteOff && pSelectedInstrument->hasSamples() ) {
469 Note *pNote2 =
new Note( pSelectedInstrument, 0, fVelocity, fPan, nLength);
493 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
496 PatternList *pPatternList = pSong->getPatternList();
497 auto pInstrumentList = pSong->getInstrumentList();
499 Note *pFoundNote =
nullptr;
501 if ( nPattern < 0 || nPattern > pPatternList->
size() ) {
502 ERRORLOG(
"Invalid pattern number" );
507 auto pFromInstrument = pInstrumentList->get( nRow );
508 auto pToInstrument = pInstrumentList->get( nNewRow );
511 Note *pCandidateNote = it->second;
519 pFoundNote = pCandidateNote;
526 if ( pFoundNote ==
nullptr ) {
527 ERRORLOG(
"Couldn't find note to move" );
533 if ( pFromInstrument == pToInstrument ) {
539 Note *pNewNote =
new Note( pFoundNote, pToInstrument );
542 m_selection.removeFromSelection( pFoundNote,
false );
572 if ( offset.x() == 0 && offset.y() == 0 ) {
582 pUndo->beginMacro(
"copy notes" );
584 pUndo->beginMacro(
"move notes" );
586 std::list< Note * > selectedNotes;
588 selectedNotes.push_back( pNote );
599 for (
auto pNote : selectedNotes ) {
600 int nInstrument = pInstrumentList->index( pNote->get_instrument() );
601 int nPosition = pNote->get_position();
602 int nNewInstrument = nInstrument + offset.y();
603 int nNewPosition = nPosition + offset.x();
604 if ( nNewInstrument < 0 || nNewInstrument >= pInstrumentList->size()
605 || nNewPosition < 0 || nNewPosition >=
m_pPattern->get_length() ) {
615 pNote->get_velocity(),
617 pNote->get_lead_lag(),
620 pNote->get_probability(),
625 pNote->get_note_off() ) );
635 pNote->get_velocity(),
637 pNote->get_lead_lag(),
640 pNote->get_probability(),
645 pNote->get_note_off() ) );
649 nNewPosition, nNewInstrument, pNote ) );
670 bool bOldCursorHidden = pHydrogenApp->hideKeyboardCursor();
672 const int nBlockSize = 5, nWordSize = 5;
675 int nMaxInstrument = pHydrogen->
getSong()->getInstrumentList()->size();
676 bool bUnhideCursor =
true;
678 bool bIsSelectionKey =
m_selection.keyPressEvent( ev );
681 if ( bIsSelectionKey ) {
683 }
else if ( ev->matches( QKeySequence::MoveToNextChar ) || ev->matches( QKeySequence::SelectNextChar ) ) {
687 }
else if ( ev->matches( QKeySequence::MoveToNextWord ) || ev->matches( QKeySequence::SelectNextWord ) ) {
691 }
else if ( ev->matches( QKeySequence::MoveToEndOfLine ) || ev->matches( QKeySequence::SelectEndOfLine ) ) {
695 }
else if ( ev->matches( QKeySequence::MoveToPreviousChar ) || ev->matches( QKeySequence::SelectPreviousChar ) ) {
699 }
else if ( ev->matches( QKeySequence::MoveToPreviousWord ) || ev->matches( QKeySequence::SelectPreviousWord ) ) {
703 }
else if ( ev->matches( QKeySequence::MoveToStartOfLine ) || ev->matches( QKeySequence::SelectStartOfLine ) ) {
707 }
else if ( ev->matches( QKeySequence::MoveToNextLine ) || ev->matches( QKeySequence::SelectNextLine ) ) {
708 if ( nSelectedInstrument + 1 < nMaxInstrument ) {
711 }
else if ( ev->matches( QKeySequence::MoveToEndOfBlock ) || ev->matches( QKeySequence::SelectEndOfBlock ) ) {
713 nMaxInstrument-1 ) );
715 }
else if ( ev->matches( QKeySequence::MoveToNextPage ) || ev->matches( QKeySequence::SelectNextPage ) ) {
717 QWidget *pParent =
dynamic_cast< QWidget *
>( parent() );
721 if ( nSelectedInstrument >= nMaxInstrument ) {
722 nSelectedInstrument = nMaxInstrument - 1;
726 }
else if ( ev->matches( QKeySequence::MoveToEndOfDocument ) || ev->matches( QKeySequence::SelectEndOfDocument ) ) {
729 }
else if ( ev->matches( QKeySequence::MoveToPreviousLine ) || ev->matches( QKeySequence::SelectPreviousLine ) ) {
730 if ( nSelectedInstrument > 0 ) {
733 }
else if ( ev->matches( QKeySequence::MoveToStartOfBlock ) || ev->matches( QKeySequence::SelectStartOfBlock ) ) {
736 }
else if ( ev->matches( QKeySequence::MoveToPreviousPage ) || ev->matches( QKeySequence::SelectPreviousPage ) ) {
737 QWidget *pParent =
dynamic_cast< QWidget *
>( parent() );
740 if ( nSelectedInstrument < 0 ) {
741 nSelectedInstrument = 0;
745 }
else if ( ev->matches( QKeySequence::MoveToStartOfDocument ) || ev->matches( QKeySequence::SelectStartOfDocument ) ) {
748 }
else if ( ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return ) {
753 }
else if ( ev->key() == Qt::Key_Delete ) {
755 bUnhideCursor =
false;
766 }
else if ( ev->matches( QKeySequence::SelectAll ) ) {
767 bUnhideCursor =
false;
770 }
else if ( ev->matches( QKeySequence::Deselect ) ) {
771 bUnhideCursor =
false;
774 }
else if ( ev->matches( QKeySequence::Copy ) ) {
775 bUnhideCursor =
false;
778 }
else if ( ev->matches( QKeySequence::Paste ) ) {
779 bUnhideCursor =
false;
782 }
else if ( ev->matches( QKeySequence::Cut ) ) {
783 bUnhideCursor =
false;
788 pHydrogenApp->setHideKeyboardCursor(
true );
790 if ( bOldCursorHidden != pHydrogenApp->hideKeyboardCursor() ) {
797 if ( bUnhideCursor ) {
798 pHydrogenApp->setHideKeyboardCursor(
false );
810 if ( ! pHydrogenApp->hideKeyboardCursor() ) {
831 std::vector<SelectionIndex> result;
833 return std::move( result );
837 auto pInstrList = pSong->getInstrumentList();
847 if ( r.top() == r.bottom() && r.left() == r.right() ) {
848 r += QMargins( 2, 2, 2, 2 );
850 r += QMargins( 4, h/2, 4, h/2 );
859 for (
auto it = notes->lower_bound( x_min ); it != notes->end() && it->first <= x_max; ++it ) {
860 Note *note = it->second;
862 if ( nInstrument == -1 ) {
870 if ( r.contains( QPoint( x_pos, y_pos + h/2) ) ) {
871 result.push_back( note );
875 return std::move( result );
886 const int nSelectedInstrument =
898 return QRect( x - fHalfWidth, y + 2, fHalfWidth * 2,
m_nGridHeight - 3 );
926 auto pInstrumentList = pHydrogen->
getSong()->getInstrumentList();
932 std::list< QUndoCommand *> actions;
934 if ( pInstrumentList->index( pNote->get_instrument() ) == -1 ) {
941 pInstrumentList->index( pNote->get_instrument() ),
944 pNote->get_velocity(),
946 pNote->get_lead_lag(),
949 pNote->get_probability(),
954 pNote->get_note_off() ) );
959 pUndo->beginMacro(
"delete notes");
960 for ( QUndoCommand *pAction : actions ) {
961 pUndo->push( pAction );
980 QClipboard *clipboard = QApplication::clipboard();
984 int nDeltaPos = 0, nDeltaInstrument = 0;
987 if ( ! doc.setContent( clipboard->text() ) ) {
992 XMLNode selection = doc.firstChildElement(
"noteSelection" );
993 if ( ! selection.isNull() ) {
998 noteList = selection.firstChildElement(
"noteList" );
999 if ( noteList.isNull() ) {
1003 XMLNode positionNode = selection.firstChildElement(
"sourcePosition" );
1008 if ( !positionNode.isNull() ) {
1012 nDeltaPos = nCurrentPos -
1013 positionNode.
read_int(
"minColumn", nCurrentPos );
1014 nDeltaInstrument = nCurrentInstrument -
1015 positionNode.
read_int(
"minRow", nCurrentInstrument );
1019 XMLNode instrumentLine = doc.firstChildElement(
"instrument_line" );
1020 if ( ! instrumentLine.isNull() ) {
1027 XMLNode patternList = instrumentLine.firstChildElement(
"patternList" );
1028 if ( patternList.isNull() ) {
1031 XMLNode pattern = patternList.firstChildElement(
"pattern" );
1032 if ( pattern.isNull() ) {
1036 if ( ! pattern.nextSiblingElement(
"pattern" ).isNull() ) {
1037 QMessageBox::information(
this,
"Hydrogen", tr(
"Cannot paste multi-pattern selection" ) );
1040 noteList = pattern.firstChildElement(
"noteList" );
1041 if ( noteList.isNull() ) {
1050 if ( noteList.hasChildNodes() ) {
1052 pUndo->beginMacro(
"paste notes" );
1053 for (
XMLNode n = noteList.firstChildElement(
"note" ); ! n.isNull(); n = n.nextSiblingElement() ) {
1056 int nInstrument = pInstrList->index( pNote->
get_instrument() ) + nDeltaInstrument;
1058 if ( nPos >= 0 && nPos < m_pPattern->get_length()
1059 && nInstrument >= 0 && nInstrument < pInstrList->size() ) {
1097 auto pInstrList = pSong->getInstrumentList();
1112 if ( pNotes->size() == 0 ) {
1115 bool bIsForeground = ( pPattern ==
m_pPattern );
1117 std::vector< int > noteCount;
1118 std::stack<std::shared_ptr<Instrument>> instruments;
1123 for (
auto posIt = pNotes->begin(); posIt != pNotes->end(); ) {
1124 if ( posIt->first >= pPattern->get_length() ) {
1130 int nPosition = posIt->second->get_position();
1133 auto noteIt = posIt;
1134 while ( noteIt != pNotes->end() && noteIt->second->get_position() == nPosition ) {
1135 Note *pNote = noteIt->second;
1146 if ( nInstrumentID >= 0 ) {
1147 if ( nInstrumentID >= noteCount.size() ) {
1148 noteCount.resize( nInstrumentID+1, 0 );
1151 if ( ++noteCount[ nInstrumentID ] == 1) {
1155 drawNote( pNote, painter, bIsForeground );
1163 while ( ! instruments.empty() ) {
1164 auto pInstrument = instruments.top();
1165 int nInstrumentID = pInstrument->get_id();
1166 if ( noteCount[ nInstrumentID ] > 1 ) {
1168 int nInstrument = pInstrList->index( pInstrument );
1171 const int boxWidth = 128;
1173 QFont font( pPref->getApplicationFontFamily(),
getPointSize( pPref->getFontSize() ) );
1174 painter.setFont( font );
1175 painter.setPen( QColor( 0, 0, 0 ) );
1177 painter.drawText( QRect( x-boxWidth-6, y, boxWidth,
m_nGridHeight),
1178 Qt::AlignRight | Qt::AlignVCenter,
1179 ( QString(
"%1" ) + QChar( 0x00d7 )).arg( noteCount[ nInstrumentID ] ) );
1181 noteCount[ nInstrumentID ] = 0;
1202 if ( nInstrument == -1 ) {
1203 ERRORLOG(
"Instrument not found..skipping note" );
1218 const QColor backgroundColor( pPref->getColorTheme()->m_patternEditor_backgroundColor );
1219 const QColor backgroundInactiveColor( pPref->getColorTheme()->m_windowColor );
1220 const QColor alternateRowColor( pPref->getColorTheme()->m_patternEditor_alternateRowColor );
1221 const QColor selectedRowColor( pPref->getColorTheme()->m_patternEditor_selectedRowColor );
1222 const QColor lineColor( pPref->getColorTheme()->m_patternEditor_lineColor );
1223 const QColor lineInactiveColor( pPref->getColorTheme()->m_windowTextColor.darker( 170 ) );
1225 std::shared_ptr<Song> pSong = pHydrogen->getSong();
1226 int nInstruments = pSong->getInstrumentList()->size();
1227 int nSelectedInstrument = pHydrogen->getSelectedInstrumentNumber();
1232 backgroundInactiveColor);
1235 for (
int ii = 0; ii < nInstruments; ii++ ) {
1237 if ( ii == nSelectedInstrument ) {
1241 else if ( ( ii % 2 ) != 0 ) {
1256 for (
int ii = 0; ii < nInstruments; ii++ ) {
1258 if ( ii == nSelectedInstrument ) {
1261 if ( ( ii % 2 ) == 0 ) {
1274 p.setPen( QPen( lineColor, 1, Qt::SolidLine ) );
1275 for ( uint i = 0; i < (uint)nInstruments; i++ ) {
1281 p.setPen( QPen( lineInactiveColor, 1, Qt::SolidLine ) );
1282 for ( uint i = 0; i < (uint)nInstruments; i++ ) {
1289 p.setPen( lineColor );
1293 p.setPen( lineInactiveColor );
1297 p.setPen( QPen( lineColor, 2, Qt::SolidLine ) );
1306 qreal pixelRatio = devicePixelRatio();
1330 qreal pixelRatio = devicePixelRatio();
1335 QPainter painter(
this );
1336 painter.drawPixmap( ev->rect(), *
m_pBackgroundPixmap, QRectF( pixelRatio * ev->rect().x(),
1337 pixelRatio * ev->rect().y(),
1338 pixelRatio * ev->rect().width(),
1339 pixelRatio * ev->rect().height() ) );
1349 painter.drawLine( nX, 0, nX, height() );
1361 QPen p( pPref->getColorTheme()->m_cursorColor );
1363 painter.setPen( p );
1364 painter.setBrush( Qt::NoBrush );
1365 painter.setRenderHint( QPainter::Antialiasing );
1379 QColor color = pPref->getColorTheme()->m_highlightColor;
1384 if ( ! hasFocus() ) {
1385 color.setAlpha( 125 );
1391 nStartY +
HydrogenApp::get_instance()->getPatternEditorPanel()->getDrumPatternEditorScrollArea()->viewport()->size().height() );
1392 int nEndX = std::min( nStartX +
HydrogenApp::get_instance()->getPatternEditorPanel()->getDrumPatternEditorScrollArea()->viewport()->size().width(), width() );
1396 painter.setPen( pen );
1397 painter.drawLine( QPoint( nStartX, nStartY ), QPoint( nEndX, nStartY ) );
1398 painter.drawLine( QPoint( nStartX, nStartY ), QPoint( nStartX, nEndY ) );
1399 painter.drawLine( QPoint( nEndX, nStartY ), QPoint( nEndX, nEndY ) );
1400 painter.drawLine( QPoint( nEndX, nEndY ), QPoint( nStartX, nEndY ) );
1437 int nSelectedPatternNumber,
1438 int nSelectedInstrument,
1447 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
1451 if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->size() ) ) {
1452 pPattern = pPatternList->
get( nSelectedPatternNumber );
1455 if( pPattern !=
nullptr ) {
1458 Note *pNote = it->second;
1461 if ( pNote->
get_instrument() != pSong->getInstrumentList()->get( nSelectedInstrument ) ) {
1507 Pattern* pPattern = pPatternList->
get( patternNumber );
1508 if ( pPattern ==
nullptr ) {
1509 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1510 .arg( patternNumber ) );
1514 std::list < H2Core::Note *>::const_iterator pos;
1515 for ( pos = noteList.begin(); pos != noteList.end(); ++pos){
1517 pNote =
new Note(*pos);
1534 while (appliedList.size() > 0)
1537 Pattern *pApplied = appliedList.front();
1550 Note *pNote = it->second;
1557 Note *pFoundNote = it->second;
1570 appliedList.pop_front();
1588 std::list < H2Core::Pattern *>::iterator pos;
1589 for ( pos = changeList.begin(); pos != changeList.end(); ++pos)
1610 Note *pNote = it->second;
1614 bool noteExists =
false;
1618 Note *pFoundNote = it->second;
1636 appliedList.push_back(pApplied);
1651 auto pSong = pHydrogen->
getSong();
1652 PatternList* pPatternList = pSong->getPatternList();
1653 Pattern* pPattern = pPatternList->
get( patternNumber );
1654 if ( pPattern ==
nullptr ) {
1655 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1656 .arg( patternNumber ) );
1660 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1661 if ( pSelectedInstrument ==
nullptr ) {
1662 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1663 .arg( nSelectedInstrument ) );
1669 for (
int i = 0; i < noteList.size(); i++ ) {
1670 int nColumn = noteList.value(i).toInt();
1673 Note *pNote = it->second;
1693 auto pSong = pHydrogen->
getSong();
1694 PatternList* pPatternList = pSong->getPatternList();
1695 Pattern* pPattern = pPatternList->
get( patternNumber );
1696 if ( pPattern ==
nullptr ) {
1697 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1698 .arg( patternNumber ) );
1702 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1703 if ( pSelectedInstrument ==
nullptr ) {
1704 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1705 .arg( nSelectedInstrument ) );
1710 for (
int i = 0; i < noteList.size(); i++ ) {
1713 int position = noteList.value(i).toInt();
1714 Note *pNote =
new Note( pSelectedInstrument, position );
1727 auto pSong = pHydrogen->
getSong();
1728 PatternList* pPatternList = pSong->getPatternList();
1729 Pattern* pPattern = pPatternList->
get( selectedPatternNumber );
1730 if ( pPattern ==
nullptr ) {
1731 ERRORLOG( QString(
"Couldn't find pattern [%1]" )
1732 .arg( selectedPatternNumber ) );
1736 auto pSelectedInstrument = pSong->getInstrumentList()->get( nSelectedInstrument );
1737 if ( pSelectedInstrument ==
nullptr ) {
1738 ERRORLOG( QString(
"Couldn't find instrument [%1]" )
1739 .arg( nSelectedInstrument ) );
1746 int positionCount = 0;
1747 for (
int i = 0; i < pPattern->
get_length(); i += nResolution) {
1750 Note *pNote = it->second;
1752 float velocity = noteVeloValue.value( positionCount ).toFloat();
1771 std::shared_ptr<Song> pSong = pHydrogen->getSong();
1772 auto pInstrumentList = pSong->getInstrumentList();
1774 if ( ( nTargetInstrument > (
int)pInstrumentList->size() ) || ( nTargetInstrument < 0) ) {
1779 pInstrumentList->move( nSourceInstrument, nTargetInstrument );
1781 pHydrogen->renameJackPorts( pSong );
1784 pHydrogen->setSelectedInstrumentNumber( nTargetInstrument );
1786 pHydrogen->setIsModified(
true );
1795 auto pDrumkitComponents = pHydrogen->
getSong()->getComponents();
1797 for (
const auto& nComponent : *AddedComponents ) {
1799 for (
int n = 0 ; n < pDrumkitComponents->size() ; n++ ) {
1800 auto pTmpDrumkitComponent = pDrumkitComponents->at( n );
1801 if ( pTmpDrumkitComponent->get_id() == nComponent ) {
1802 pDrumkitComponents->erase( pDrumkitComponents->begin() + n );
1822 auto pSong = pHydrogen->getSong();
1825 if ( pNewInstrument ==
nullptr ||
1826 ( pNewInstrument->get_name() ==
"Empty Instrument" &&
1827 pNewInstrument->get_drumkit_path().isEmpty() ) ){
1829 QMessageBox::critical(
this,
"Hydrogen", pCommonString->getInstrumentLoadError() );
1834 pHydrogen->getSoundLibraryDatabase()->getDrumkit( sDrumkitPath );
1835 if( pNewDrumkit ==
nullptr ){
1836 ERRORLOG( QString(
"Unable to load drumkit [%1]" ).arg( sDrumkitPath ) );
1845 auto pOldInstrumentComponents =
new std::vector<std::shared_ptr<InstrumentComponent>>( pNewInstrument->get_components()->begin(), pNewInstrument->get_components()->end() );
1846 pNewInstrument->get_components()->clear();
1848 for (
auto pComponent : *(pNewDrumkit->get_components()) ) {
1849 int nOldID = pComponent->get_id();
1853 int nNewID = pSong->findExistingComponent( pComponent->get_name() );
1855 if ( nNewID == -1 ) {
1861 nNewID = pSong->findFreeComponentID();
1863 pAddedComponents->push_back( nNewID );
1865 pComponent->set_id( nNewID );
1866 pComponent->set_name( pSong->makeComponentNameUnique( pComponent->get_name() ) );
1867 auto pNewComponent = std::make_shared<DrumkitComponent>( pComponent );
1868 pSong->getComponents()->push_back( pNewComponent );
1871 for (
auto pOldInstrCompo : *pOldInstrumentComponents ) {
1872 if( pOldInstrCompo->get_drumkit_componentID() == nOldID ) {
1873 auto pNewInstrCompo = std::make_shared<InstrumentComponent>( pOldInstrCompo );
1874 pNewInstrCompo->set_drumkit_componentID( nNewID );
1876 pNewInstrument->get_components()->push_back( pNewInstrCompo );
1881 pOldInstrumentComponents->clear();
1882 delete pOldInstrumentComponents;
1886 for ( uint i = 0; i < pSong->getInstrumentList()->size(); ++i ) {
1887 auto pInstr = pSong->getInstrumentList()->get( i );
1888 if ( pInstr->get_id() > nID ) {
1889 nID = pInstr->get_id();
1894 pNewInstrument->set_id( nID );
1896 pSong->getInstrumentList()->add( pNewInstrument );
1898 pHydrogen->renameJackPorts( pSong );
1900 pHydrogen->setIsModified(
true );
1907 pHydrogen->setSelectedInstrumentNumber(nTargetInstrument);
1915 auto pSong = pHydrogen->
getSong();
1916 std::shared_ptr<Instrument> pNewInstrument;
1917 if( sDrumkitPath ==
"" ){
1918 pNewInstrument = std::make_shared<Instrument>( pSong->getInstrumentList()->size() -1, sInstrumentName );
1922 if( pNewInstrument ==
nullptr ) {
1928 for ( uint i = 0; i < pSong->getInstrumentList()->size(); ++i ) {
1929 auto pInstr = pSong->getInstrumentList()->get( i );
1930 if ( pInstr->get_id() > nID ) {
1931 nID = pInstr->get_id();
1936 pNewInstrument->set_id( nID );
1939 pSong->getInstrumentList()->add( pNewInstrument );
1953 PatternList *pPatternList = pSong->getPatternList();
1960 if(noteList.size() > 0 ){
1961 std::list < H2Core::Note *>::const_iterator pos;
1962 for ( pos = noteList.begin(); pos != noteList.end(); ++pos){
1963 Note *pNote =
new Note( *pos, pNewInstrument );
1978 auto pSong = pHydrogen->
getSong();
1980 if ( pSong ==
nullptr ) {
2002 auto pSong = pHydrogen->getSong();
2004 if ( pSong ==
nullptr ) {
2009 auto pList = pSong->getInstrumentList();
2015 for ( uint i = 0; i < pList->size(); ++i ) {
2016 auto pInstr = pList->get( i );
2017 if ( pInstr !=
nullptr &&
2018 ( pInstr->get_id() > nID ) ) {
2019 nID = pInstr->get_id();
2024 auto pNewInstr = std::make_shared<Instrument>( nID,
"New instrument");
2025 pNewInstr->set_drumkit_path( pSong->getLastLoadedDrumkitPath() );
2026 pNewInstr->set_drumkit_name( pSong->getLastLoadedDrumkitName() );
2028 pList->add( pNewInstr );
2030 pHydrogen->renameJackPorts( pSong );
2032 pHydrogen->setIsModified(
true );
2035 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)
========================================================== undo / redo actions from pattern editor in...
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)
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.
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 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
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.
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()
Compatibility class to support QMouseEvent more esily in Qt5 and Qt6.
const QScrollBar * getVerticalScrollBar() const
const QScrollBar * getHorizontalScrollBar() const
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
PatternEditor(QWidget *pParent, PatternEditorPanel *panel)
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.
static void setPlayheadPen(QPainter *p, bool bHovered=false)
static int getPlayheadShaftOffset()
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
#define MAX_NOTES
Maximum number of notes.
@ EVENT_SELECTED_INSTRUMENT_CHANGED