Hey guys,
Here is a new feature, based on stable-0.4 (e5bc77f). It add, for the piano
roll, the possibility to mark single tone or a specified note based
diatonic scale (major and natural minor).
I think it also respond to this requested feature:
http://sourceforge.net/tracker/?func=detail&aid=3450211&group_id=105168&atid=640437
When are you planning to release the 0.4.13 ? Because there are huge bugs
on piano roll and b+b editor when changing the time signature, and i may
have fixed them in few days.
regards,
From b118ec3be88bb9d74c2cf78a2de67eee9477efa7 Mon Sep 17 00:00:00 2001
From: NoiseByNorthwest <[email protected]>
Date: Sun, 29 Jan 2012 16:45:02 +0100
Subject: [PATCH] Add tone marking feature
---
include/piano_roll.h | 13 ++++-
src/gui/piano_roll.cpp | 133 +++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 133 insertions(+), 13 deletions(-)
diff --git a/include/piano_roll.h b/include/piano_roll.h
index c00d649..7780875 100644
--- a/include/piano_roll.h
+++ b/include/piano_roll.h
@@ -141,6 +141,7 @@ protected slots:
void quantizeChanged();
void changeNoteEditMode( int i );
+ void markTone( int i );
private:
@@ -170,6 +171,14 @@ private:
NoteEditCount // make sure this one is always last
};
+ enum toneMarkerAction
+ {
+ tmmeUnmarkAll,
+ tmmeMarkCurrent,
+ tmmeMarkMinorScale,
+ tmmeMarkMajorScale,
+ };
+
enum pianoRollKeyTypes
{
PR_WHITE_KEY_SMALL,
@@ -179,7 +188,9 @@ private:
QVector<QString> m_nemStr; // gui names of each edit mode
QMenu * m_noteEditMenu; // when you right click below the key area
- QSignalMapper * m_signalMapper; // to keep track of edit mode events
+
+ QList<int> m_markedTones;
+ QMenu * m_toneMarkerMenu; // when you right click on the key area
pianoRoll();
pianoRoll( const pianoRoll & );
diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp
index 7bb995f..3ad36cc 100644
--- a/src/gui/piano_roll.cpp
+++ b/src/gui/piano_roll.cpp
@@ -43,6 +43,7 @@
#endif
#include <math.h>
+#include <algorithm>
#include "piano_roll.h"
#include "bb_track_container.h"
@@ -137,7 +138,7 @@ const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DefaultStepsPerTact;
pianoRoll::pianoRoll() :
m_nemStr( QVector<QString>() ),
m_noteEditMenu( NULL ),
- m_signalMapper( NULL ),
+ m_toneMarkerMenu( NULL ),
m_zoomingModel(),
m_quantizeModel(),
m_noteLenModel(),
@@ -172,19 +173,45 @@ pianoRoll::pianoRoll() :
m_nemStr.push_back( tr( "Note Volume" ) );
m_nemStr.push_back( tr( "Note Panning" ) );
- m_signalMapper = new QSignalMapper( this );
+ QSignalMapper * signalMapper = new QSignalMapper( this );
m_noteEditMenu = new QMenu( this );
m_noteEditMenu->clear();
for( int i=0; i<m_nemStr.size(); ++i )
{
QAction * act = new QAction( m_nemStr.at(i), this );
- connect( act, SIGNAL(triggered()), m_signalMapper, SLOT(map()) );
- m_signalMapper->setMapping( act, i );
+ connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) );
+ signalMapper->setMapping( act, i );
m_noteEditMenu->addAction( act );
}
- connect( m_signalMapper, SIGNAL(mapped(int)),
+ connect( signalMapper, SIGNAL(mapped(int)),
this, SLOT(changeNoteEditMode(int)) );
+ signalMapper = new QSignalMapper( this );
+ m_toneMarkerMenu = new QMenu( this );
+
+ QAction * act = new QAction( tr("Mark/unmark current tone"), this );
+ connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) );
+ signalMapper->setMapping( act, static_cast<int>( tmmeMarkCurrent ) );
+ m_toneMarkerMenu->addAction( act );
+
+ act = new QAction( tr("Mark minor scale"), this );
+ connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) );
+ signalMapper->setMapping( act, static_cast<int>( tmmeMarkMinorScale ) );
+ m_toneMarkerMenu->addAction( act );
+
+ act = new QAction( tr("Mark major scale"), this );
+ connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) );
+ signalMapper->setMapping( act, static_cast<int>( tmmeMarkMajorScale ) );
+ m_toneMarkerMenu->addAction( act );
+
+ act = new QAction( tr("Unmark all"), this );
+ connect( act, SIGNAL(triggered()), signalMapper, SLOT(map()) );
+ signalMapper->setMapping( act, static_cast<int>( tmmeUnmarkAll ) );
+ m_toneMarkerMenu->addAction( act );
+
+ connect( signalMapper, SIGNAL(mapped(int)),
+ this, SLOT(markTone(int)) );
+
// init pixmaps
if( s_whiteKeySmallPm == NULL )
{
@@ -537,6 +564,63 @@ void pianoRoll::changeNoteEditMode( int i )
}
+void pianoRoll::markTone( int i )
+{
+ static const int major_scale[KeysPerOctave] = {
+ 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1
+ };
+
+ static const int minor_scale[KeysPerOctave] = {
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0
+ };
+
+ const int * scale = 0;
+ const int key = getKey( mapFromGlobal( m_toneMarkerMenu->pos() ).y() );
+
+ switch( static_cast<toneMarkerAction>( i ) )
+ {
+ case tmmeUnmarkAll:
+ m_markedTones.clear();
+ break;
+ case tmmeMarkCurrent:
+ {
+ QList<int>::iterator i = qFind( m_markedTones.begin(), m_markedTones.end(), key );
+ if( i != m_markedTones.end() )
+ {
+ m_markedTones.erase( i );
+ }
+ else
+ {
+ m_markedTones.push_back( key );
+ }
+ break;
+ }
+ case tmmeMarkMinorScale:
+ scale = minor_scale;
+ case tmmeMarkMajorScale:
+ if( ! scale )
+ {
+ scale = major_scale;
+ }
+
+ for( int i = 0; i <= NumKeys; i++ )
+ {
+ if( scale[std::abs( key - i ) % KeysPerOctave] )
+ {
+ m_markedTones.push_back( i );
+ }
+ }
+ break;
+ default:
+ ;
+ }
+
+ qSort( m_markedTones.begin(), m_markedTones.end(), qGreater<int>() );
+ QList<int>::iterator new_end = std::unique( m_markedTones.begin(), m_markedTones.end() );
+ m_markedTones.erase( new_end, m_markedTones.end() );
+}
+
+
pianoRoll::~pianoRoll()
{
}
@@ -1574,14 +1658,23 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
}
else if( _me->y() < keyAreaBottom() )
{
- // clicked on keyboard on the left - play note
- m_lastKey = key_num;
- if( ! m_recording && ! engine::getSong()->isPlaying() )
+ // clicked on keyboard on the left
+ if( _me->buttons() == Qt::RightButton )
{
- int v = ( (float) x ) / ( (float) WHITE_KEY_WIDTH ) * 127;
- m_pattern->instrumentTrack()->processInEvent(
- midiEvent( MidiNoteOn, 0, key_num, v ),
- midiTime() );
+ // right click, tone marker contextual menu
+ m_toneMarkerMenu->popup( mapToGlobal( QPoint( _me->x(), _me->y() ) ) );
+ }
+ else
+ {
+ // left click - play the note
+ m_lastKey = key_num;
+ if( ! m_recording && ! engine::getSong()->isPlaying() )
+ {
+ int v = ( (float) x ) / ( (float) WHITE_KEY_WIDTH ) * 127;
+ m_pattern->instrumentTrack()->processInEvent(
+ midiEvent( MidiNoteOn, 0, key_num, v ),
+ midiTime() );
+ }
}
}
else
@@ -2609,6 +2702,22 @@ void pianoRoll::paintEvent( QPaintEvent * _pe )
++key;
}
+ // display note marks
+ for( int i = 0; i < m_markedTones.size(); i++ )
+ {
+ const int key_num = m_markedTones.at( i );
+ const int y = keyAreaBottom() + 5
+ - KEY_LINE_HEIGHT * ( key_num - m_startKey + 1 );
+
+ if( y > keyAreaBottom() )
+ {
+ break;
+ }
+
+ p.fillRect( WHITE_KEY_WIDTH, y,
+ width() - 10, 1,
+ QColor( 64, 64 + ( key_num % KeysPerOctave ) * 7, 96 + key_num ) );
+ }
// erase the area below the piano, because there might be keys that
// should be only half-visible
--
1.7.5.4
------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
LMMS-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lmms-devel