root/branches/undo/gui/src/PatternEditor/PianoRollEditor.cpp @ 1579

Revision 1579, 41.7 KB (checked in by wolke, 3 years ago)

fix small memory problem. rename 'undo stack' into 'command history'.

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22
23#include "PianoRollEditor.h"
24#include "PatternEditorPanel.h"
25#include "NotePropertiesRuler.h"
26#include "UndoActions.h"
27#include <cassert>
28
29#include <hydrogen/hydrogen.h>
30#include <hydrogen/instrument.h>
31#include <hydrogen/note.h>
32#include <hydrogen/Preferences.h>
33#include <hydrogen/Pattern.h>
34#include <hydrogen/audio_engine.h>
35using namespace H2Core;
36
37#include "../HydrogenApp.h"
38
39PianoRollEditor::PianoRollEditor( QWidget *pParent, PatternEditorPanel *panel )
40 : QWidget( pParent )
41 , Object( "PianoRollEditor" )
42 , m_nResolution( 8 )
43 , m_bRightBtnPressed( false )
44 , m_bUseTriplets( false )
45 , m_pPattern( NULL )
46 , m_pPatternEditorPanel( panel )
47 , m_pDraggedNote( NULL )
48{
49        INFOLOG( "INIT" );
50
51        m_nRowHeight = 10;
52        m_nOctaves = 7;
53
54        setAttribute(Qt::WA_NoBackground);
55        setFocusPolicy(Qt::ClickFocus);
56        m_nGridWidth = Preferences::get_instance()->getPatternEditorGridWidth();
57
58        m_nEditorWidth = 20 + m_nGridWidth *  (MAX_NOTES * 4);
59        m_nEditorHeight = m_nOctaves * 12 * m_nRowHeight;
60
61        m_pBackground = new QPixmap( m_nEditorWidth, m_nEditorHeight );
62        m_pTemp = new QPixmap( m_nEditorWidth, m_nEditorHeight );
63
64        resize( m_nEditorWidth, m_nEditorHeight );
65       
66        createBackground();
67
68        HydrogenApp::get_instance()->addEventListener( this );
69}
70
71
72
73PianoRollEditor::~PianoRollEditor()
74{
75        INFOLOG( "DESTROY" );
76}
77
78
79void PianoRollEditor::setResolution(uint res, bool bUseTriplets)
80{
81        this->m_nResolution = res;
82        this->m_bUseTriplets = bUseTriplets;
83        updateEditor();
84}
85
86
87void PianoRollEditor::updateEditor()
88{
89//      uint nEditorWidth;
90        if ( m_pPattern ) {
91                m_nEditorWidth = 20 + m_nGridWidth * m_pPattern->get_length();
92        }
93        else {
94                m_nEditorWidth = 20 + m_nGridWidth * MAX_NOTES;
95        }
96        resize( m_nEditorWidth, height() );
97
98        // redraw all
99        update( 0, 0, width(), height() );
100
101        createBackground();
102        drawPattern();
103//      ERRORLOG(QString("update editor %1").arg(m_nEditorWidth));
104}
105
106
107
108//eventlistener
109void PianoRollEditor::patternModifiedEvent()
110{
111        updateEditor();
112}
113
114
115
116void PianoRollEditor::selectedInstrumentChangedEvent()
117{
118        updateEditor();
119}
120
121
122void PianoRollEditor::selectedPatternChangedEvent()
123{
124        //INFOLOG( "updating m_pPattern pointer" );
125
126        Hydrogen *pEngine = Hydrogen::get_instance();
127        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
128        int nSelectedPatternNumber = pEngine->getSelectedPatternNumber();
129        if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->get_size() ) ) {
130                m_pPattern = pPatternList->get( nSelectedPatternNumber );
131        }
132        else {
133                m_pPattern = NULL;
134        }
135        __selectedPatternNumber = nSelectedPatternNumber;
136        updateEditor();
137}
138
139
140
141void PianoRollEditor::paintEvent(QPaintEvent *ev)
142{
143        QPainter painter( this );
144        painter.drawPixmap( ev->rect(), *m_pTemp, ev->rect() );
145}
146
147
148
149void PianoRollEditor::createBackground()
150{
151        //INFOLOG( "(re)creating the background" );
152
153        QColor backgroundColor( 250, 250, 250 );
154        m_pBackground->fill( backgroundColor );
155
156
157        QColor octaveColor( 230, 230, 230 );
158        QColor octaveAlternateColor( 200, 200, 200 );
159        QColor baseOctaveColor( 245, 245, 245 );
160        QColor baseNoteColor( 255, 255, 255 );
161
162        QColor fbk( 160, 160, 160 );
163
164        unsigned start_x = 0;
165        unsigned end_x = width();
166
167        QPainter p( m_pBackground );
168
169        for ( uint octave = 0; octave < m_nOctaves; ++octave ) {
170                unsigned start_y = octave * 12 * m_nRowHeight;
171
172                if ( octave % 2 ) {
173
174               
175                        if ( octave == 3 ){
176               
177//                              p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, baseOctaveColor );
178                                p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, baseOctaveColor );
179                                p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
180                                p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, baseOctaveColor );
181                                p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
182                                p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, baseOctaveColor );
183                                p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
184                                p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, baseOctaveColor );
185                                p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, baseOctaveColor );
186                                p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
187                                p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, baseOctaveColor );
188                                p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
189                                p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, baseNoteColor );
190                        }
191                        else
192                        {
193                        //      p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, octaveColor );
194                                p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, octaveColor );
195                                p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
196                                p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, octaveColor );
197                                p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
198                                p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, octaveColor );
199                                p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
200                                p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, octaveColor );
201                                p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, octaveColor );
202                                p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
203                                p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, octaveColor );
204                                p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
205                                p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, octaveColor );
206
207                        }
208                }
209                else {
210//                      p.fillRect( start_x, start_y, end_x - start_x, 12 * m_nRowHeight, octaveAlternateColor );
211                        p.fillRect( start_x, start_y, end_x - start_x, start_y + 1 * m_nRowHeight, octaveAlternateColor );
212                        p.fillRect( start_x, start_y + 1 * m_nRowHeight, end_x - start_x, start_y + 2 * m_nRowHeight, fbk );
213                        p.fillRect( start_x, start_y + 2 * m_nRowHeight, end_x - start_x, start_y + 3 * m_nRowHeight, octaveAlternateColor );
214                        p.fillRect( start_x, start_y + 3 * m_nRowHeight, end_x - start_x, start_y + 4 * m_nRowHeight, fbk );
215                        p.fillRect( start_x, start_y + 4 * m_nRowHeight, end_x - start_x, start_y + 5 * m_nRowHeight, octaveAlternateColor );
216                        p.fillRect( start_x, start_y + 5 * m_nRowHeight, end_x - start_x, start_y + 6 * m_nRowHeight, fbk );
217                        p.fillRect( start_x, start_y + 6 * m_nRowHeight, end_x - start_x, start_y + 7 * m_nRowHeight, octaveAlternateColor );
218                        p.fillRect( start_x, start_y + 7 * m_nRowHeight, end_x - start_x, start_y + 8 * m_nRowHeight, octaveAlternateColor );
219                        p.fillRect( start_x, start_y + 8 * m_nRowHeight, end_x - start_x, start_y + 9 * m_nRowHeight, fbk );
220                        p.fillRect( start_x, start_y + 9 * m_nRowHeight, end_x - start_x, start_y + 10 * m_nRowHeight, octaveAlternateColor );
221                        p.fillRect( start_x, start_y + 10 * m_nRowHeight, end_x - start_x, start_y + 11 * m_nRowHeight, fbk );
222                        p.fillRect( start_x, start_y + 11 * m_nRowHeight, end_x - start_x, start_y + 12 * m_nRowHeight, octaveAlternateColor );
223                       
224                }               
225        }
226
227
228        // horiz lines
229        for ( uint row = 0; row < ( 12 * m_nOctaves ); ++row ) {
230                unsigned y = row * m_nRowHeight;
231                p.drawLine( start_x, y,end_x , y );
232        }
233
234        //draw text
235        QFont font;
236        font.setPointSize ( 9 );
237//      font.setWeight( 63 );
238        p.setFont( font );
239        p.setPen( QColor(10, 10, 10 ) );
240
241        int offset = 0;
242        int insertx = 3;
243        for ( int oct = 0; oct < (int)m_nOctaves; oct++ ){
244                if( oct > 3 ){
245                        p.drawText( insertx, m_nRowHeight  + offset, "B" );
246                        p.drawText( insertx, 10 + m_nRowHeight  + offset, "A#" );
247                        p.drawText( insertx, 20 + m_nRowHeight  + offset, "A" );
248                        p.drawText( insertx, 30 + m_nRowHeight  + offset, "G#" );
249                        p.drawText( insertx, 40 + m_nRowHeight  + offset, "G" );
250                        p.drawText( insertx, 50 + m_nRowHeight  + offset, "F#" );
251                        p.drawText( insertx, 60 + m_nRowHeight  + offset, "F" );
252                        p.drawText( insertx, 70 + m_nRowHeight  + offset, "E" );
253                        p.drawText( insertx, 80 + m_nRowHeight  + offset, "D#" );
254                        p.drawText( insertx, 90 + m_nRowHeight  + offset, "D" );
255                        p.drawText( insertx, 100 + m_nRowHeight  + offset, "C#" );
256                        p.drawText( insertx, 110 + m_nRowHeight  + offset, "C" );
257                        offset += 12 * m_nRowHeight;   
258                }else
259                {
260                        p.drawText( insertx, m_nRowHeight  + offset, "b" );
261                        p.drawText( insertx, 10 + m_nRowHeight  + offset, "a#" );
262                        p.drawText( insertx, 20 + m_nRowHeight  + offset, "a" );
263                        p.drawText( insertx, 30 + m_nRowHeight  + offset, "g#" );
264                        p.drawText( insertx, 40 + m_nRowHeight  + offset, "g" );
265                        p.drawText( insertx, 50 + m_nRowHeight  + offset, "f#" );
266                        p.drawText( insertx, 60 + m_nRowHeight  + offset, "f" );
267                        p.drawText( insertx, 70 + m_nRowHeight  + offset, "e" );
268                        p.drawText( insertx, 80 + m_nRowHeight  + offset, "d#" );
269                        p.drawText( insertx, 90 + m_nRowHeight  + offset, "d" );
270                        p.drawText( insertx, 100 + m_nRowHeight  + offset, "c#" );
271                        p.drawText( insertx, 110 + m_nRowHeight  + offset, "c" );
272                        offset += 12 * m_nRowHeight;
273                }
274        }               
275               
276        draw_grid( p );
277}
278
279
280
281
282void PianoRollEditor::draw_grid( QPainter& p )
283{
284        static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
285        static const QColor res_1( pStyle->m_patternEditor_line1Color.getRed(), pStyle->m_patternEditor_line1Color.getGreen(), pStyle->m_patternEditor_line1Color.getBlue() );
286        static const QColor res_2( pStyle->m_patternEditor_line2Color.getRed(), pStyle->m_patternEditor_line2Color.getGreen(), pStyle->m_patternEditor_line2Color.getBlue() );
287        static const QColor res_3( pStyle->m_patternEditor_line3Color.getRed(), pStyle->m_patternEditor_line3Color.getGreen(), pStyle->m_patternEditor_line3Color.getBlue() );
288        static const QColor res_4( pStyle->m_patternEditor_line4Color.getRed(), pStyle->m_patternEditor_line4Color.getGreen(), pStyle->m_patternEditor_line4Color.getBlue() );
289        static const QColor res_5( pStyle->m_patternEditor_line5Color.getRed(), pStyle->m_patternEditor_line5Color.getGreen(), pStyle->m_patternEditor_line5Color.getBlue() );
290
291        // vertical lines
292
293        int nBase;
294        if (m_bUseTriplets) {
295                nBase = 3;
296        }
297        else {
298                nBase = 4;
299        }
300
301        int n4th = 4 * MAX_NOTES / (nBase * 4);
302        int n8th = 4 * MAX_NOTES / (nBase * 8);
303        int n16th = 4 * MAX_NOTES / (nBase * 16);
304        int n32th = 4 * MAX_NOTES / (nBase * 32);
305        int n64th = 4 * MAX_NOTES / (nBase * 64);
306
307        int nNotes = MAX_NOTES;
308        if ( m_pPattern ) {
309                nNotes = m_pPattern->get_length();
310        }
311        if (!m_bUseTriplets) {
312                for ( int i = 0; i < nNotes + 1; i++ ) {
313                        uint x = 20 + i * m_nGridWidth;
314
315                        if ( (i % n4th) == 0 ) {
316                                if (m_nResolution >= 4) {
317                                        p.setPen( QPen( res_1, 1, Qt::DashLine) );
318                                        p.drawLine(x, 1, x, m_nEditorHeight - 1);
319                                }
320                        }
321                        else if ( (i % n8th) == 0 ) {
322                                if (m_nResolution >= 8) {
323                                        p.setPen( QPen( res_2, 0, Qt::DashLine ) );
324                                        p.drawLine(x, 1, x, m_nEditorHeight - 1);
325                                }
326                        }
327                        else if ( (i % n16th) == 0 ) {
328                                if (m_nResolution >= 16) {
329                                        p.setPen( QPen( res_3, 0, Qt::DashLine ) );
330                                        p.drawLine(x, 1, x, m_nEditorHeight - 1);
331                                }
332                        }
333                        else if ( (i % n32th) == 0 ) {
334                                if (m_nResolution >= 32) {
335                                        p.setPen( QPen( res_4, 0, Qt::DashLine ) );
336                                        p.drawLine(x, 1, x, m_nEditorHeight - 1);
337                                }
338                        }
339                        else if ( (i % n64th) == 0 ) {
340                                if (m_nResolution >= 64) {
341                                        p.setPen( QPen( res_5, 0, Qt::DashLine  ) );
342                                        p.drawLine(x, 1, x, m_nEditorHeight - 1);
343                                }
344                        }
345                }
346        }
347        else {  // Triplets
348                uint nCounter = 0;
349                int nSize = 4 * MAX_NOTES / (nBase * m_nResolution);
350
351                for ( int i = 0; i < nNotes + 1; i++ ) {
352                        uint x = 20 + i * m_nGridWidth;
353
354                        if ( (i % nSize) == 0) {
355                                if ((nCounter % 3) == 0) {
356                                        p.setPen( QPen( res_1, 0, Qt::DashLine ) );
357                                }
358                                else {
359                                        p.setPen( QPen( res_3, 0, Qt::DashLine ) );
360                                }
361                                p.drawLine(x, 1, x, m_nEditorHeight - 1);
362                                nCounter++;
363                        }
364                }
365        }
366}
367
368
369void PianoRollEditor::drawPattern()
370{
371        if ( isVisible() == false ) {
372                return;
373        }
374
375
376        //INFOLOG( "draw pattern" );
377
378        QPainter p( m_pTemp );
379        // copy the background image
380        p.drawPixmap( rect(), *m_pBackground, rect() );
381
382
383        // for each note...
384        std::multimap <int, Note*>::iterator pos;
385        for ( pos = m_pPattern->note_map.begin(); pos != m_pPattern->note_map.end(); pos++ ) {
386                //cout << "note" << endl;
387                //cout << "note n: " << pos->first << endl;
388                Note *note = pos->second;
389                assert( note );
390                drawNote( note, &p );
391        }
392
393}
394
395
396void PianoRollEditor::drawNote( Note *pNote, QPainter *pPainter )
397{
398        static const UIStyle *pStyle = Preferences::get_instance()->getDefaultUIStyle();
399        static const QColor noteColor( pStyle->m_patternEditor_noteColor.getRed(), pStyle->m_patternEditor_noteColor.getGreen(), pStyle->m_patternEditor_noteColor.getBlue() );
400        static const QColor noteoffColor( pStyle->m_patternEditor_noteoffColor.getRed(), pStyle->m_patternEditor_noteoffColor.getGreen(), pStyle->m_patternEditor_noteoffColor.getBlue() );
401
402        int nInstrument = -1;
403        InstrumentList * pInstrList = Hydrogen::get_instance()->getSong()->get_instrument_list();
404        for ( uint nInstr = 0; nInstr < pInstrList->get_size(); ++nInstr ) {
405                Instrument *pInstr = pInstrList->get( nInstr );
406                if ( pInstr == pNote->get_instrument() ) {
407                        nInstrument = nInstr;
408                        break;
409                }
410        }
411        if ( nInstrument == -1 ) {
412                //ERRORLOG( "Instrument not found..skipping note" );
413                return;
414        }
415
416        if ( nInstrument != Hydrogen::get_instance()->getSelectedInstrumentNumber() ) {
417                return;
418        }
419
420        uint start_x = 20 + pNote->get_position() * m_nGridWidth;
421        uint start_y = height() - m_nRowHeight - ( m_nRowHeight * pNote->m_noteKey.m_key + ( 12 * (pNote->m_noteKey.m_nOctave +3) ) * m_nRowHeight ) + 1;
422        uint w = 8;
423        uint h = m_nRowHeight - 2;
424
425        int red = (int) (pNote->get_velocity() * 255);
426        int green;
427        int blue;
428        blue = (255 - (int) red)* .33;
429        green =  (255 - (int) red);
430
431        if ( pNote->get_length() == -1 && pNote->get_noteoff() == false ) {
432                pPainter->setBrush(QColor( red,green,blue ));
433                pPainter->drawEllipse( start_x -4 , start_y, w, h );
434        }
435        else if ( pNote->get_length() == 1 && pNote->get_noteoff() == true ){
436                pPainter->setBrush(QColor( noteoffColor ));
437                pPainter->drawEllipse( start_x -4 , start_y, w, h );
438        }
439        else {
440                float fNotePitch = pNote->m_noteKey.m_nOctave * 12 + pNote->m_noteKey.m_key;
441                float fStep = pow( 1.0594630943593, ( double )fNotePitch );
442
443                int nend = m_nGridWidth * pNote->get_length() / fStep;
444                nend = nend - 1;        // lascio un piccolo spazio tra una nota ed un altra
445
446                pPainter->setBrush(QColor( red,green,blue ));
447                pPainter->fillRect( start_x, start_y, nend, h, QColor( red,green,blue ) );
448                pPainter->drawRect( start_x, start_y, nend, h );
449        }
450}
451
452
453int PianoRollEditor::getColumn(QMouseEvent *ev)
454{
455        int nBase;
456        if (m_bUseTriplets) {
457                nBase = 3;
458        }
459        else {
460                nBase = 4;
461        }
462        int nWidth = (m_nGridWidth * 4 * MAX_NOTES) / (nBase * m_nResolution);
463
464        int x = ev->x();
465        int nColumn;
466        nColumn = x - 20 + (nWidth / 2);
467        nColumn = nColumn / nWidth;
468        nColumn = (nColumn * 4 * MAX_NOTES) / (nBase * m_nResolution);
469        return nColumn;
470}
471
472
473void PianoRollEditor::mousePressEvent(QMouseEvent *ev)
474{
475       
476        //ERRORLOG("Mouse press event");
477        if ( m_pPattern == NULL ) {
478                return;
479        }
480
481        Song *pSong = Hydrogen::get_instance()->getSong();
482
483        int row = ((int) ev->y()) / ((int) m_nEditorHeight);
484        if (row >= (int) m_nOctaves * 12 ) {
485                return;
486        }
487
488        int nColumn = getColumn( ev );
489
490        if ( nColumn >= (int)m_pPattern->get_length() ) {
491                update( 0, 0, width(), height() );
492                return;
493        }
494       
495        int pressedline = ((int) ev->y()) / ((int) m_nRowHeight);
496
497        Instrument *pSelectedInstrument = NULL;
498        int nSelectedInstrumentnumber = Hydrogen::get_instance()->getSelectedInstrumentNumber();
499        pSelectedInstrument = pSong->get_instrument_list()->get( nSelectedInstrumentnumber );
500        assert(pSelectedInstrument);
501
502        //ERRORLOG(QString("pressedline: %1, column %2, event ev: %3, editorhight %4").arg(pressedline).arg(nColumn).arg(ev->y()).arg(m_nEditorHeight));
503
504        int pressedoctave = 3 - (pressedline / 12 );
505        int pressednotekey = 0;
506        if ( pressedline < 12 ){
507                pressednotekey = 11 - pressedline;
508        }
509        else
510        {
511                pressednotekey = 11 - pressedline % 12;
512        }
513
514       
515        //ERRORLOG(QString("pressedline: %1, octave %2, notekey: %3").arg(pressedline).arg(pressedoctave).arg(pressednotekey));
516
517        if (ev->button() == Qt::LeftButton ) {
518
519                unsigned nRealColumn = 0;
520                if( ev->x() > 20 ) {
521                        nRealColumn = (ev->x() - 20) / static_cast<float>(m_nGridWidth);
522                }
523
524                H2Core::Note *pDraggedNote;
525                pDraggedNote = NULL;
526               
527                std::multimap <int, Note*>::iterator pos;
528                for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
529                        Note *pNote = pos->second;
530                        assert( pNote );
531
532                        if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
533                                pDraggedNote = pNote;
534                                break;
535                        }
536                }
537                if ( !pDraggedNote ) {
538                        for ( pos = m_pPattern->note_map.lower_bound( nRealColumn ); pos != m_pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
539                                Note *pNote = pos->second;
540                                assert( pNote );
541
542                                if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
543                                        pDraggedNote = pNote;
544                                        break;
545                                }
546                        }       
547
548                }
549
550                int oldLength = -1;
551                float oldVelocity = 0.8f;
552                float oldPan_L = 0.5f;
553                float oldPan_R = 0.5f;
554                float oldLeadLag = 0.0f;
555                int oldNoteKeyVal = 0;
556                int oldOctaveKeyVal = 0;
557
558                if( pDraggedNote ){
559                        oldLength = pDraggedNote->get_length();
560                        oldVelocity = pDraggedNote->get_velocity();
561                        oldPan_L = pDraggedNote->get_pan_l();
562                        oldPan_R = pDraggedNote->get_pan_r();
563                        oldLeadLag = pDraggedNote->get_leadlag();
564                        oldNoteKeyVal = pDraggedNote->m_noteKey.m_key;
565                        oldOctaveKeyVal = pDraggedNote->m_noteKey.m_nOctave;                   
566                }
567
568                SE_addNotePianoRollAction *action = new SE_addNotePianoRollAction( nColumn,
569                                                                                   pressedline,
570                                                                                   __selectedPatternNumber,
571                                                                                   nSelectedInstrumentnumber,
572                                                                                   oldLength,
573                                                                                   oldVelocity,
574                                                                                   oldPan_L,
575                                                                                   oldPan_R,
576                                                                                   oldLeadLag,
577                                                                                   oldNoteKeyVal,
578                                                                                   oldOctaveKeyVal );
579                HydrogenApp::get_instance()->m_undoStack->push( action );
580
581        }
582
583        else if (ev->button() == Qt::RightButton ) {
584                m_bRightBtnPressed = true;
585                m_pDraggedNote = NULL;
586                m_pOldPoint = ev->y();
587
588                unsigned nRealColumn = 0;
589                if( ev->x() > 20 ) {
590                        nRealColumn = (ev->x() - 20) / static_cast<float>(m_nGridWidth);
591                }
592
593//
594                //      __rightclickedpattereditor
595                //      0 = note length
596                //      1 = note off"
597                //      2 = edit velocity
598                //      3 = edit pan
599                //      4 = edit lead lag
600
601                if ( Preferences::get_instance()->__rightclickedpattereditor == 1){
602
603                        SE_addNoteRightClickPianoRollAction *action = new SE_addNoteRightClickPianoRollAction( nColumn, pressedline, __selectedPatternNumber, nSelectedInstrumentnumber );
604                        HydrogenApp::get_instance()->m_undoStack->push( action );
605
606                }
607
608
609//              AudioEngine::get_instance()->lock( RIGHT_HERE );
610
611                std::multimap <int, Note*>::iterator pos;
612                for ( pos = m_pPattern->note_map.lower_bound( nColumn ); pos != m_pPattern->note_map.upper_bound( nColumn ); ++pos ) {
613                        Note *pNote = pos->second;
614                        assert( pNote );
615
616                        if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
617                                m_pDraggedNote = pNote;
618                                break;
619                        }
620                }
621                if ( !m_pDraggedNote ) {
622                        for ( pos = m_pPattern->note_map.lower_bound( nRealColumn ); pos != m_pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
623                                Note *pNote = pos->second;
624                                assert( pNote );
625
626                                if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
627                                        m_pDraggedNote = pNote;
628                                        break;
629                                }
630                        }       
631
632                }
633
634                for ( int nCol = 0; unsigned(nCol) < nRealColumn; ++nCol ) {
635                        if ( m_pDraggedNote ) break;
636                        for ( pos = m_pPattern->note_map.lower_bound( nCol ); pos != m_pPattern->note_map.upper_bound( nCol ); ++pos ) {
637                                Note *pNote = pos->second;
638                                assert( pNote );
639
640                                if ( ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument )
641                                    && ( (nRealColumn <= pNote->get_position() + pNote->get_length() )
642                                    && nRealColumn >= pNote->get_position() ) ){
643                                        m_pDraggedNote = pNote;
644                                        break;
645                                }
646                        }
647                }
648
649
650
651                //needed for undo note length
652                __nRealColumn = nRealColumn;
653                __nColumn = nColumn;
654                __pressedLine = pressedline;
655                __selectedInstrumentnumber = nSelectedInstrumentnumber;
656                if( m_pDraggedNote ){
657                        __oldLength = m_pDraggedNote->get_length();
658                        //needed to undo note properties
659                        __oldVelocity = m_pDraggedNote->get_velocity();
660                        __oldPan_L = m_pDraggedNote->get_pan_l();
661                        __oldPan_R = m_pDraggedNote->get_pan_r();
662                        __oldLeadLag = m_pDraggedNote->get_leadlag();
663       
664                        __velocity = __oldVelocity;
665                        __pan_L = __oldPan_L;
666                        __pan_R = __oldPan_R;
667                        __leadLag = __oldLeadLag;
668                }else
669                {
670                        __oldLength = -1;
671                }
672//              AudioEngine::get_instance()->unlock();
673        }       
674}
675
676void PianoRollEditor::addOrDeleteNoteAction( int nColumn,
677                                             int pressedLine,
678                                             int selectedPatternNumber,
679                                             int selectedinstrument,
680                                             int oldLength,
681                                             float oldVelocity,
682                                             float oldPan_L,
683                                             float oldPan_R,
684                                             float oldLeadLag,
685                                             int oldNoteKeyVal,
686                                             int oldOctaveKeyVal )
687{
688        Hydrogen *pEngine = Hydrogen::get_instance();
689        Song *pSong = pEngine->getSong();
690        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
691        H2Core::Pattern *pPattern;
692
693        Instrument *pSelectedInstrument = NULL;
694        pSelectedInstrument = pSong->get_instrument_list()->get( selectedinstrument );
695        assert(pSelectedInstrument);
696
697        if ( ( selectedPatternNumber != -1 ) && ( (uint)selectedPatternNumber < pPatternList->get_size() ) ) {
698                pPattern = pPatternList->get( selectedPatternNumber );
699        }
700        else {
701                pPattern = NULL;
702        }
703
704        int pressedoctave = 3 - (pressedLine / 12 );
705        int pressednotekey = 0;
706        if ( pressedLine < 12 ){
707                pressednotekey = 11 - pressedLine;
708        }
709        else
710        {
711                pressednotekey = 11 - pressedLine % 12;
712        }
713
714        m_bRightBtnPressed = false;
715
716        bool bNoteAlreadyExist = false;
717        AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
718        std::multimap <int, Note*>::iterator pos;
719        for ( pos = pPattern->note_map.lower_bound( nColumn ); pos != pPattern->note_map.upper_bound( nColumn ); ++pos ) {
720                Note *pNote = pos->second;
721                assert( pNote );
722                if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument ) {
723                        // the note exists...remove it!
724                        bNoteAlreadyExist = true;
725                        delete pNote;
726                        pPattern->note_map.erase( pos );
727                        break;
728                }
729        }
730
731        if ( bNoteAlreadyExist == false ) {
732                // create the new note
733                const unsigned nPosition = nColumn;
734                const float fVelocity = oldVelocity;
735                const float fPan_L = oldPan_L;
736                const float fPan_R = oldPan_R;
737                int nLength = oldLength;
738
739                const float fPitch = 0.0f;
740                Note *pNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch );
741                pNote->set_noteoff( false );
742                pNote->set_leadlag( oldLeadLag );
743
744                if ( pressednotekey == 0 )//note c
745                        pNote->m_noteKey.m_key = H2Core::NoteKey::C;
746                if ( pressednotekey == 1 )
747                        pNote->m_noteKey.m_key = H2Core::NoteKey::Cs;
748                if ( pressednotekey == 2 )
749                        pNote->m_noteKey.m_key = H2Core::NoteKey::D;
750                if ( pressednotekey == 3 )
751                        pNote->m_noteKey.m_key = H2Core::NoteKey::Ef;
752                if ( pressednotekey == 4 )
753                        pNote->m_noteKey.m_key = H2Core::NoteKey::E;
754                if ( pressednotekey == 5 )
755                        pNote->m_noteKey.m_key = H2Core::NoteKey::F;
756                if ( pressednotekey == 6 )
757                        pNote->m_noteKey.m_key = H2Core::NoteKey::Fs;
758                if ( pressednotekey == 7 )
759                        pNote->m_noteKey.m_key = H2Core::NoteKey::G;
760                if ( pressednotekey == 8 )
761                        pNote->m_noteKey.m_key = H2Core::NoteKey::Af;
762                if ( pressednotekey == 9 )
763                        pNote->m_noteKey.m_key = H2Core::NoteKey::A;
764                if ( pressednotekey == 10 )
765                        pNote->m_noteKey.m_key = H2Core::NoteKey::Bf;
766                if ( pressednotekey == 11 )
767                        pNote->m_noteKey.m_key = H2Core::NoteKey::B;
768               
769                pNote->m_noteKey.m_nOctave = pressedoctave;
770                pPattern->note_map.insert( std::make_pair( nPosition, pNote ) );
771
772                // hear note
773                Preferences *pref = Preferences::get_instance();
774                if ( pref->getHearNewNotes() ) {
775                        Note *pNote2 = new Note( pSelectedInstrument, 0, fVelocity, fPan_L, fPan_R, nLength, fPitch);
776                        if ( pressednotekey == 0 )//note c
777                                pNote2->m_noteKey.m_key = H2Core::NoteKey::C;
778                        if ( pressednotekey == 1 )
779                                pNote2->m_noteKey.m_key = H2Core::NoteKey::Cs;
780                        if ( pressednotekey == 2 )
781                                pNote2->m_noteKey.m_key = H2Core::NoteKey::D;
782                        if ( pressednotekey == 3 )
783                                pNote2->m_noteKey.m_key = H2Core::NoteKey::Ef;
784                        if ( pressednotekey == 4 )
785                                pNote2->m_noteKey.m_key = H2Core::NoteKey::E;
786                        if ( pressednotekey == 5 )
787                                pNote2->m_noteKey.m_key = H2Core::NoteKey::F;
788                        if ( pressednotekey == 6 )
789                                pNote2->m_noteKey.m_key = H2Core::NoteKey::Fs;
790                        if ( pressednotekey == 7 )
791                                pNote2->m_noteKey.m_key = H2Core::NoteKey::G;
792                        if ( pressednotekey == 8 )
793                                pNote2->m_noteKey.m_key = H2Core::NoteKey::Af;
794                        if ( pressednotekey == 9 )
795                                pNote2->m_noteKey.m_key = H2Core::NoteKey::A;
796                        if ( pressednotekey == 10 )
797                                pNote2->m_noteKey.m_key = H2Core::NoteKey::Bf;
798                        if ( pressednotekey == 11 )
799                                pNote2->m_noteKey.m_key = H2Core::NoteKey::B;
800                       
801                        pNote2->m_noteKey.m_nOctave = pressedoctave;
802                        AudioEngine::get_instance()->get_sampler()->note_on(pNote2);
803                }
804        }
805        pSong->__is_modified = true;
806        AudioEngine::get_instance()->unlock(); // unlock the audio engine
807
808        updateEditor();
809        m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
810        m_pPatternEditorPanel->getPanEditor()->updateEditor();
811        m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
812        m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
813        m_pPatternEditorPanel->getDrumPatternEditor()->updateEditor();
814}
815
816
817void PianoRollEditor::addNoteRightClickAction( int nColumn, int pressedLine, int selectedPatternNumber, int selectedinstrument)
818{
819        Hydrogen *pEngine = Hydrogen::get_instance();
820        Song *pSong = pEngine->getSong();
821        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
822        H2Core::Pattern *pPattern;
823
824        Instrument *pSelectedInstrument = NULL;
825        pSelectedInstrument = pSong->get_instrument_list()->get( selectedinstrument );
826        assert(pSelectedInstrument);
827
828        if ( ( selectedPatternNumber != -1 ) && ( (uint)selectedPatternNumber < pPatternList->get_size() ) ) {
829                pPattern = pPatternList->get( selectedPatternNumber );
830        }
831        else {
832                pPattern = NULL;
833        }
834
835        int pressedoctave = 3 - (pressedLine / 12 );
836        int pressednotekey = 0;
837        if ( pressedLine < 12 ){
838                pressednotekey = 11 - pressedLine;
839        }
840        else
841        {
842                pressednotekey = 11 - pressedLine % 12;
843        }
844
845        AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
846        // create the new note
847        const unsigned nPosition = nColumn;
848        const float fVelocity = 0.0f;
849        const float fPan_L = 0.5f;
850        const float fPan_R = 0.5f;
851        const int nLength = 1;
852        const float fPitch = 0.0f;
853        Note *poffNote = new Note( pSelectedInstrument, nPosition, fVelocity, fPan_L, fPan_R, nLength, fPitch);
854        poffNote->set_noteoff( true );
855        if ( pressednotekey == 0 )//note c
856                poffNote->m_noteKey.m_key = H2Core::NoteKey::C;
857        if ( pressednotekey == 1 )
858                poffNote->m_noteKey.m_key = H2Core::NoteKey::Cs;
859        if ( pressednotekey == 2 )
860                poffNote->m_noteKey.m_key = H2Core::NoteKey::D;
861        if ( pressednotekey == 3 )
862                poffNote->m_noteKey.m_key = H2Core::NoteKey::Ef;
863        if ( pressednotekey == 4 )
864                poffNote->m_noteKey.m_key = H2Core::NoteKey::E;
865        if ( pressednotekey == 5 )
866                poffNote->m_noteKey.m_key = H2Core::NoteKey::F;
867        if ( pressednotekey == 6 )
868                poffNote->m_noteKey.m_key = H2Core::NoteKey::Fs;
869        if ( pressednotekey == 7 )
870                poffNote->m_noteKey.m_key = H2Core::NoteKey::G;
871        if ( pressednotekey == 8 )
872                poffNote->m_noteKey.m_key = H2Core::NoteKey::Af;
873        if ( pressednotekey == 9 )
874                poffNote->m_noteKey.m_key = H2Core::NoteKey::A;
875        if ( pressednotekey == 10 )
876                poffNote->m_noteKey.m_key = H2Core::NoteKey::Bf;
877        if ( pressednotekey == 11 )
878                poffNote->m_noteKey.m_key = H2Core::NoteKey::B;
879       
880        poffNote->m_noteKey.m_nOctave = pressedoctave;
881       
882        pPattern->note_map.insert( std::make_pair( nPosition, poffNote ) );
883
884        pSong->__is_modified = true;
885        AudioEngine::get_instance()->unlock(); // unlock the audio engine
886
887        updateEditor();
888        m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
889        m_pPatternEditorPanel->getPanEditor()->updateEditor();
890        m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
891        m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
892        m_pPatternEditorPanel->getDrumPatternEditor()->updateEditor();
893}
894
895
896
897void PianoRollEditor::mouseMoveEvent(QMouseEvent *ev)
898{
899        if (m_pPattern == NULL) {
900                return;
901        }
902
903        int row = ((int) ev->y()) / ((int) m_nEditorHeight);
904        if (row >= (int) m_nOctaves * 12 ) {
905                return;
906        }
907
908        //      __rightclickedpattereditor
909        //      0 = note length
910        //      1 = note off"
911        //      2 = edit velocity
912        //      3 = edit pan
913        //      4 = edit lead lag
914
915        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 0 ) ) {
916                if ( m_pDraggedNote->get_noteoff() ) return;
917                int nTickColumn = getColumn( ev );
918
919                AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
920                int nLen = nTickColumn - (int)m_pDraggedNote->get_position();
921
922                if (nLen <= 0) {
923                        nLen = -1;
924                }
925
926                float fNotePitch = m_pDraggedNote->m_noteKey.m_nOctave * 12 + m_pDraggedNote->m_noteKey.m_key;
927                float fStep = 0;
928                if(nLen > -1){
929                        fStep = pow( 1.0594630943593, ( double )fNotePitch );
930                }else
931                {
932                        fStep = 1.0;
933                }
934                m_pDraggedNote->set_length( nLen * fStep);
935
936                Hydrogen::get_instance()->getSong()->__is_modified = true;
937                AudioEngine::get_instance()->unlock(); // unlock the audio engine
938
939                //__draw_pattern();
940                updateEditor();
941                m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
942                m_pPatternEditorPanel->getPanEditor()->updateEditor();
943                m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
944                m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
945        }
946
947        //edit velocity
948        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 2 ) ) {
949                if ( m_pDraggedNote->get_noteoff() ) return;
950
951                AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
952
953                float val = m_pDraggedNote->get_velocity();
954
955               
956                float ymove = m_pOldPoint - ev->y();
957                val = val  +  (ymove / 100);
958                if (val > 1) {
959                        val = 1;
960                }
961                else if (val < 0.0) {
962                        val = 0.0;
963                }
964
965                m_pDraggedNote->set_velocity( val );
966
967                __velocity = val;
968       
969                Hydrogen::get_instance()->getSong()->__is_modified = true;
970                AudioEngine::get_instance()->unlock(); // unlock the audio engine
971
972                //__draw_pattern();
973                updateEditor();
974                m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
975                m_pPatternEditorPanel->getPanEditor()->updateEditor();
976                m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
977                m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
978                m_pOldPoint = ev->y();
979        }
980
981        //edit pan
982        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 3 ) ) {
983                if ( m_pDraggedNote->get_noteoff() ) return;
984
985                AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
986
987                float pan_L, pan_R;
988               
989                float val = (m_pDraggedNote->get_pan_r() - m_pDraggedNote->get_pan_l() + 0.5);
990       
991                float ymove = m_pOldPoint - ev->y();
992                val = val  +  (ymove / 100);
993
994
995                if ( val > 0.5 ) {
996                        pan_L = 1.0 - val;
997                        pan_R = 0.5;
998                }
999                else {
1000                        pan_L = 0.5;
1001                        pan_R = val;
1002                }
1003
1004                m_pDraggedNote->set_pan_l( pan_L );
1005                m_pDraggedNote->set_pan_r( pan_R );
1006
1007                __pan_L = pan_L;
1008                __pan_R = pan_R;
1009
1010                Hydrogen::get_instance()->getSong()->__is_modified = true;
1011                AudioEngine::get_instance()->unlock(); // unlock the audio engine
1012
1013                //__draw_pattern();
1014                updateEditor();
1015                m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
1016                m_pPatternEditorPanel->getPanEditor()->updateEditor();
1017                m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
1018                m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
1019                m_pOldPoint = ev->y();
1020        }
1021
1022        //edit lead lag
1023        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 4 ) ) {
1024                if ( m_pDraggedNote->get_noteoff() ) return;
1025
1026                AudioEngine::get_instance()->lock( RIGHT_HERE );        // lock the audio engine
1027
1028               
1029                float val = ( m_pDraggedNote->get_leadlag() - 1.0 ) / -2.0 ;
1030       
1031                float ymove = m_pOldPoint - ev->y();
1032                val = val  +  (ymove / 100);
1033
1034                if (val > 1.0) {
1035                        val = 1.0;
1036                }
1037                else if (val < 0.0) {
1038                        val = 0.0;
1039                }
1040
1041                m_pDraggedNote->set_leadlag((val * -2.0) + 1.0);
1042
1043                __leadLag = (val * -2.0) + 1.0;
1044
1045                char valueChar[100];
1046                if ( m_pDraggedNote->get_leadlag() < 0.0 ) {
1047                        sprintf( valueChar, "%.2f",  ( m_pDraggedNote->get_leadlag() * -5 ) ); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
1048                        HydrogenApp::get_instance()->setStatusBarMessage( QString("Leading beat by: %1 ticks").arg( valueChar ), 2000 );
1049                } else if ( m_pDraggedNote->get_leadlag() > 0.0 ) {
1050                        sprintf( valueChar, "%.2f",  ( m_pDraggedNote->get_leadlag() * 5 ) ); // FIXME: '5' taken from fLeadLagFactor calculation in hydrogen.cpp
1051                        HydrogenApp::get_instance()->setStatusBarMessage( QString("Lagging beat by: %1 ticks").arg( valueChar ), 2000 );
1052                } else {
1053                        HydrogenApp::get_instance()->setStatusBarMessage( QString("Note on beat"), 2000 );
1054                }
1055
1056                Hydrogen::get_instance()->getSong()->__is_modified = true;
1057                AudioEngine::get_instance()->unlock(); // unlock the audio engine
1058
1059                //__draw_pattern();
1060                updateEditor();
1061                m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
1062                m_pPatternEditorPanel->getPanEditor()->updateEditor();
1063                m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
1064                m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
1065                m_pOldPoint = ev->y();
1066        }
1067
1068}
1069
1070
1071void PianoRollEditor::mouseReleaseEvent(QMouseEvent *ev)
1072{
1073        //INFOLOG("Mouse release event" );
1074        if (m_pPattern == NULL) {
1075                return;
1076        }
1077
1078        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor == 0 ) ) {
1079                if ( m_pDraggedNote->get_noteoff() ) return;
1080
1081                SE_editNoteLenghtPianoRollAction *action = new SE_editNoteLenghtPianoRollAction( m_pDraggedNote->get_position(),  m_pDraggedNote->get_position(), m_pDraggedNote->get_length(),__oldLength, __selectedPatternNumber, __selectedInstrumentnumber, __pressedLine );
1082                HydrogenApp::get_instance()->m_undoStack->push( action );
1083                return;
1084        }
1085
1086        if (m_bRightBtnPressed && m_pDraggedNote && ( Preferences::get_instance()->__rightclickedpattereditor >=2 ) ) {
1087                if ( m_pDraggedNote->get_noteoff() ) return;
1088
1089                SE_editNotePropertiesPianoRollAction *action = new SE_editNotePropertiesPianoRollAction( m_pDraggedNote->get_position(),
1090                                                                                                         m_pDraggedNote->get_position(),
1091                                                                                                         __selectedPatternNumber,
1092                                                                                                         __selectedInstrumentnumber,
1093                                                                                                         __velocity,
1094                                                                                                         __oldVelocity,
1095                                                                                                         __pan_L,
1096                                                                                                         __oldPan_L,
1097                                                                                                         __pan_R,
1098                                                                                                         __oldPan_R,
1099                                                                                                         __leadLag,
1100                                                                                                          __oldLeadLag,
1101                                                                                                         __pressedLine );
1102                HydrogenApp::get_instance()->m_undoStack->push( action );
1103        }
1104}
1105
1106
1107void PianoRollEditor::editNoteLenghtAction( int nColumn,  int nRealColumn,  int length, int selectedPatternNumber, int nSelectedInstrumentnumber, int pressedline)
1108{
1109
1110        Hydrogen *pEngine = Hydrogen::get_instance();
1111        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
1112
1113        H2Core::Pattern *pPattern;
1114        if ( (selectedPatternNumber != -1) && ( (uint)selectedPatternNumber < pPatternList->get_size() ) ) {
1115                pPattern = pPatternList->get( selectedPatternNumber );
1116        }
1117        else {
1118                pPattern = NULL;
1119        }
1120
1121        Note *pDraggedNote;
1122        Song *pSong = pEngine->getSong();
1123        int nInstruments = pSong->get_instrument_list()->get_size();
1124
1125        Instrument *pSelectedInstrument = pSong->get_instrument_list()->get( nSelectedInstrumentnumber );
1126
1127        AudioEngine::get_instance()->lock( RIGHT_HERE );
1128
1129        int pressedoctave = 3 - (pressedline / 12 );
1130        int pressednotekey = 0;
1131        if ( pressedline < 12 ){
1132                pressednotekey = 11 - pressedline;
1133        }
1134        else
1135        {
1136                pressednotekey = 11 - pressedline % 12;
1137        }
1138
1139        std::multimap <int, Note*>::iterator pos;
1140        for ( pos = pPattern->note_map.lower_bound( nColumn ); pos != pPattern->note_map.upper_bound( nColumn ); ++pos ) {
1141                Note *pNote = pos->second;
1142                assert( pNote );
1143
1144                if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
1145                        pDraggedNote = pNote;
1146                        break;
1147                }
1148        }
1149        if ( !pDraggedNote ) {
1150                for ( pos = pPattern->note_map.lower_bound( nRealColumn ); pos != pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
1151                        Note *pNote = pos->second;
1152                        assert( pNote );
1153
1154                        if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
1155                                pDraggedNote = pNote;
1156                                break;
1157                        }
1158                }       
1159
1160        }
1161
1162        for ( int nCol = 0; unsigned(nCol) < nRealColumn; ++nCol ) {
1163                if ( pDraggedNote ) break;
1164                for ( pos = pPattern->note_map.lower_bound( nCol ); pos != pPattern->note_map.upper_bound( nCol ); ++pos ) {
1165                        Note *pNote = pos->second;
1166                        assert( pNote );
1167
1168                        if ( ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument )
1169                                && ( (nRealColumn <= pNote->get_position() + pNote->get_length() )
1170                                && nRealColumn >= pNote->get_position() ) ){
1171                                pDraggedNote = pNote;
1172                                break;
1173                        }
1174                }
1175        }
1176
1177
1178        if ( pDraggedNote ){
1179                pDraggedNote->set_length( length );
1180        }
1181        AudioEngine::get_instance()->unlock();
1182        updateEditor();
1183        m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
1184        m_pPatternEditorPanel->getPanEditor()->updateEditor();
1185        m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
1186        m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
1187        m_pPatternEditorPanel->getDrumPatternEditor()->updateEditor();
1188}
1189
1190
1191
1192void PianoRollEditor::editNotePropertiesAction( int nColumn,
1193                                                int nRealColumn,
1194                                                int selectedPatternNumber,
1195                                                int selectedInstrumentnumber,
1196                                                float velocity,
1197                                                float pan_L,
1198                                                float pan_R,
1199                                                float leadLag,
1200                                                int pressedline )
1201{
1202
1203        Hydrogen *pEngine = Hydrogen::get_instance();
1204        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
1205
1206        H2Core::Pattern *pPattern;
1207        if ( (selectedPatternNumber != -1) && ( (uint)selectedPatternNumber < pPatternList->get_size() ) ) {
1208                pPattern = pPatternList->get( selectedPatternNumber );
1209        }
1210        else {
1211                pPattern = NULL;
1212        }
1213
1214
1215        int pressedoctave = 3 - (pressedline / 12 );
1216        int pressednotekey = 0;
1217        if ( pressedline < 12 ){
1218                pressednotekey = 11 - pressedline;
1219        }
1220        else
1221        {
1222                pressednotekey = 11 - pressedline % 12;
1223        }
1224
1225        Note *pDraggedNote;
1226        Song *pSong = pEngine->getSong();
1227        int nInstruments = pSong->get_instrument_list()->get_size();
1228
1229        Instrument *pSelectedInstrument = pSong->get_instrument_list()->get( selectedInstrumentnumber );
1230
1231        AudioEngine::get_instance()->lock( RIGHT_HERE );
1232
1233        std::multimap <int, Note*>::iterator pos;
1234        for ( pos = pPattern->note_map.lower_bound( nColumn ); pos != pPattern->note_map.upper_bound( nColumn ); ++pos ) {
1235                Note *pNote = pos->second;
1236                assert( pNote );
1237
1238                if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
1239                        pDraggedNote = pNote;
1240                        break;
1241                }
1242        }
1243        if ( !pDraggedNote ) {
1244                for ( pos = pPattern->note_map.lower_bound( nRealColumn ); pos != pPattern->note_map.upper_bound( nRealColumn ); ++pos ) {
1245                        Note *pNote = pos->second;
1246                        assert( pNote );
1247
1248                        if ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument) {
1249                                pDraggedNote = pNote;
1250                                break;
1251                        }
1252                }       
1253
1254        }
1255
1256        for ( int nCol = 0; unsigned(nCol) < nRealColumn; ++nCol ) {
1257                if ( pDraggedNote ) break;
1258                for ( pos = pPattern->note_map.lower_bound( nCol ); pos != pPattern->note_map.upper_bound( nCol ); ++pos ) {
1259                        Note *pNote = pos->second;
1260                        assert( pNote );
1261
1262                        if ( ( pNote->m_noteKey.m_nOctave ==  pressedoctave && pNote->m_noteKey.m_key  ==  pressednotekey && pNote->get_instrument() == pSelectedInstrument )
1263                                && ( (nRealColumn <= pNote->get_position() + pNote->get_length() )
1264                                && nRealColumn >= pNote->get_position() ) ){
1265                                pDraggedNote = pNote;
1266                                break;
1267                        }
1268                }
1269        }
1270
1271        if ( pDraggedNote ){
1272                pDraggedNote->set_velocity( velocity );
1273                pDraggedNote->set_pan_l( pan_L );
1274                pDraggedNote->set_pan_r( pan_R );       
1275                pDraggedNote->set_leadlag( leadLag );
1276        }
1277        AudioEngine::get_instance()->unlock();
1278        updateEditor();
1279        m_pPatternEditorPanel->getVelocityEditor()->updateEditor();
1280        m_pPatternEditorPanel->getPanEditor()->updateEditor();
1281        m_pPatternEditorPanel->getLeadLagEditor()->updateEditor();
1282        m_pPatternEditorPanel->getNoteKeyEditor()->updateEditor();
1283        m_pPatternEditorPanel->getDrumPatternEditor()->updateEditor();
1284}
1285
1286
1287
1288void PianoRollEditor::zoom_in()
1289{
1290        if (m_nGridWidth >= 3){
1291                m_nGridWidth *= 2;
1292        }else
1293        {
1294                m_nGridWidth *= 1.5;
1295        }
1296        updateEditor();
1297}
1298
1299
1300
1301void PianoRollEditor::zoom_out()
1302{
1303        if ( m_nGridWidth > 1.5 ) {
1304                if (m_nGridWidth > 3){
1305                        m_nGridWidth /= 2;
1306                }else
1307                {
1308                        m_nGridWidth /= 1.5;
1309                }
1310                updateEditor();
1311        }
1312}
Note: See TracBrowser for help on using the browser.