From 933a295ebd9341b3d945741bc69cd8aea086f2ac Mon Sep 17 00:00:00 2001 From: Javier Serrano Polo Date: Wed, 6 Dec 2006 00:36:30 +0000 Subject: [PATCH] detuning display, automation time, journalling and some improvements git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@433 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 70 ++++ Makefile.am | 3 +- configure.in | 4 +- include/automatable_object.h | 45 ++- include/automation_editor.h | 8 +- include/automation_pattern.h | 13 +- include/journalling_object.h | 7 + include/note.h | 2 + include/note_play_handle.h | 4 + include/piano_roll.h | 4 +- include/xqmap.h | 519 +++++++++++++++++++++++++ src/audio/audio_alsa.cpp | 41 +- src/core/arp_and_chords_tab_widget.cpp | 2 + src/core/automation_editor.cpp | 182 +++++---- src/core/bb_editor.cpp | 5 + src/core/name_label.cpp | 16 +- src/core/note.cpp | 10 + src/core/piano_roll.cpp | 127 +++--- src/core/setup_dialog.cpp | 23 +- src/tracks/automation_pattern.cpp | 21 +- src/tracks/instrument_track.cpp | 2 +- src/widgets/knob.cpp | 4 +- src/widgets/lcd_spinbox.cpp | 2 +- src/widgets/tempo_sync_knob.cpp | 80 ++-- src/widgets/volume_knob.cpp | 3 +- 25 files changed, 957 insertions(+), 240 deletions(-) create mode 100644 include/xqmap.h diff --git a/ChangeLog b/ChangeLog index a78745804..8a82f29fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,73 @@ +2006-12-06 Javier Serrano Polo + + * include/note.h: + * src/core/note.cpp: + show detuning in the piano roll + + * include/piano_roll.h: + * src/core/piano_roll.cpp: + - show note detuning + - save last key when starting to play, fixes held notes bug + - removed cursor enter/leave events, they could be ignored + - optimized unsafe loops + + * include/xqmap.h: + initial release, QMap with lowerBound for Qt3 + + * include/automation_pattern.h: + * src/tracks/automation_pattern.cpp: + - use lowerBound find, resets to proper values + - work with inverted midi time + + * include/automation_editor.h: + * src/core/automation_editor.cpp: + - work with inverted midi time + - fixed display of hidden values + - added red cross + - update detuning in the piano roll + - removed cursor enter/leave events, they could be ignored + - optimized unsafe loops + - minor optimizations + + * include/note_play_handle.h: + * src/core/arp_and_chords_tab_widget.cpp: + set subnotes' BB track + + * data/track_icons/*.png: + re-added corrupted images + + * src/core/name_label.cpp: + added bad pixmap protection + + * src/audio/audio_alsa.cpp: + - removed unnecessary asynchronous behaviour, fixes large audio buffers + - fill the whole period buffer, avoids underrun in synchronous mode + + * src/core/setup_dialog.cpp: + don't use the journal + + * include/journalling_object.h: + ease short disabling + + * include/automatable_object.h: + - use light journal disabling + - use the journal if necessary + + * src/widgets/knob.cpp: + * src/widgets/lcd_spinbox.cpp: + * src/widgets/volume_knob.cpp: + use the journal if necessary + + * src/widgets/tempo_sync_knob.cpp: + - change icon when changing mode, fixes automation crash + - disable the journal when calculating sync time + + * src/core/bb_editor.cpp: + don't create TCOs when there aren't any BB tracks + + * src/tracks/instrument_track.cpp: + removed temporary fix + 2006-12-05 Tobias Doerffel * plugins/ladspa_effect/caps/Makefile.am: diff --git a/Makefile.am b/Makefile.am index a55688885..69df2fd36 100644 --- a/Makefile.am +++ b/Makefile.am @@ -350,7 +350,8 @@ lmms_SOURCES = \ $(srcdir)/include/dummy_effect.h \ $(srcdir)/include/ladspa-1.1.h \ $(srcdir)/include/meter_dialog.h \ - $(srcdir)/include/qxembed.h + $(srcdir)/include/qxembed.h \ + $(srcdir)/include/xqmap.h diff --git a/configure.in b/configure.in index 86b14fb7d..4d50bbbdb 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.2.1-svn20061205, lmms-devel/at/lists/dot/sf/dot/net) -AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20061205) +AC_INIT(lmms, 0.2.1-svn20061206, lmms-devel/at/lists/dot/sf/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20061206) AM_CONFIG_HEADER(config.h) diff --git a/include/automatable_object.h b/include/automatable_object.h index 6e3944366..118a57cd8 100755 --- a/include/automatable_object.h +++ b/include/automatable_object.h @@ -62,13 +62,13 @@ public: const T _max = 0, const T _step = defaultRelStep() ) : journallingObject( _engine ), - m_oldValue( _val ), m_value( _val ), m_minValue( _min ), m_maxValue( _max ), m_step( _step ), m_automation_pattern( NULL ), - m_track( _track ) + m_track( _track ), + m_journalEntryReady( FALSE ) { m_curLevel = level( _val ); m_minLevel = level( _min ); @@ -161,13 +161,13 @@ public: inline virtual void setInitValue( const T _value ) { - saveJournallingState( FALSE ); + bool journalling = testAndSetJournalling( FALSE ); setValue( _value ); if( m_automation_pattern ) { setFirstValue(); } - restoreJournallingState(); + setJournalling( journalling ); } inline virtual void setValue( const T _value ) @@ -197,10 +197,11 @@ public: it->fittedValue( value() ) != it->value() ) { - it->saveJournallingState( + bool journalling = + it->testAndSetJournalling( isJournalling() ); it->setValue( value() ); - it->restoreJournallingState(); + it->setJournalling( journalling ); } } } @@ -380,7 +381,7 @@ public: protected: virtual void redoStep( journalEntry & _je ) { - saveJournallingState( FALSE ); + bool journalling = testAndSetJournalling( FALSE ); /*#ifndef QT3 setValue( static_cast( value() + _je.data().value() ) ); @@ -388,7 +389,7 @@ protected: setValue( static_cast( value() + static_cast( _je.data().toDouble() ) ) ); //#endif - restoreJournallingState(); + setJournalling( journalling ); } virtual void undoStep( journalEntry & _je ) @@ -403,13 +404,25 @@ protected: redoStep( je ); } - - // most objects will need this temporarily - T m_oldValue; + inline void prepareJournalEntryFromOldVal( void ) + { + m_oldValue = value(); + saveJournallingState( FALSE ); + m_journalEntryReady = TRUE; + } inline void addJournalEntryFromOldToCurVal( void ) { - addJournalEntry( journalEntry( 0, value() - m_oldValue ) ); + if( m_journalEntryReady ) + { + restoreJournallingState(); + if( value() != m_oldValue ) + { + addJournalEntry( journalEntry( 0, value() - + m_oldValue ) ); + } + m_journalEntryReady = FALSE; + } } inline void setFirstValue( void ) @@ -438,6 +451,10 @@ private: QPointer m_automation_pattern; track * m_track; + // most objects will need this temporarily + T m_oldValue; + bool m_journalEntryReady; + QVariant m_data; typedef vvector autoObjVector; @@ -483,11 +500,11 @@ private: { return; } - saveJournallingState( FALSE ); + bool journalling = testAndSetJournalling( FALSE ); m_automation_pattern->setUpdateFirst( FALSE ); setValue( _level * m_step ); m_automation_pattern->setUpdateFirst( TRUE ); - restoreJournallingState(); + setJournalling( journalling ); } inline int level( T _value ) const diff --git a/include/automation_editor.h b/include/automation_editor.h index 8e4ac9040..1bb593104 100644 --- a/include/automation_editor.h +++ b/include/automation_editor.h @@ -88,11 +88,14 @@ public: } +public slots: + void update( void ); + + protected: typedef automationPattern::timeMap timeMap; virtual void closeEvent( QCloseEvent * _ce ); - virtual void enterEvent( QEvent * _e ); virtual void keyPressEvent( QKeyEvent * _ke ); virtual void leaveEvent( QEvent * _e ); virtual void mousePressEvent( QMouseEvent * _me ); @@ -195,7 +198,6 @@ private: comboBox * m_quantizeComboBox; QPixmap m_paintPixmap; - bool m_cursorInside; automationPattern * m_pattern; @@ -238,7 +240,7 @@ private: timeLine * m_timeLine; bool m_scrollBack; - bool xVisible( int _x ); + void drawCross( QPainter & _p ); bool inBBEditor( void ); diff --git a/include/automation_pattern.h b/include/automation_pattern.h index a379e9ce9..b20c33746 100644 --- a/include/automation_pattern.h +++ b/include/automation_pattern.h @@ -31,6 +31,12 @@ #include "track.h" #include "level_object.h" +#ifdef QT3 + +#include "xqmap.h" + +#endif + @@ -38,7 +44,12 @@ class automationPattern : public QObject, public journallingObject { Q_OBJECT public: - typedef QMap timeMap; + // map negative midiTime to level +#ifdef QT3 + typedef XQMap timeMap; +#else + typedef QMap timeMap; +#endif automationPattern( track * _track, levelObject * _object ); automationPattern( engine * _engine, levelObject * _object ); diff --git a/include/journalling_object.h b/include/journalling_object.h index 073402c8c..a97c356f4 100755 --- a/include/journalling_object.h +++ b/include/journalling_object.h @@ -172,6 +172,13 @@ protected: m_journalling = _sr; } + inline bool testAndSetJournalling( const bool _sr ) + { + bool old_journalling = m_journalling; + m_journalling = _sr; + return( old_journalling ); + } + // to be implemented by sub-objects virtual void FASTCALL saveSettings( QDomDocument & _doc, diff --git a/include/note.h b/include/note.h index 52591827e..fa2fc537a 100644 --- a/include/note.h +++ b/include/note.h @@ -177,6 +177,8 @@ public: void editDetuningPattern( void ); void detachCurrentDetuning( void ); + bool hasDetuningInfo( void ); + protected: virtual void FASTCALL saveSettings( QDomDocument & _doc, diff --git a/include/note_play_handle.h b/include/note_play_handle.h index d092c256f..a3492afce 100644 --- a/include/note_play_handle.h +++ b/include/note_play_handle.h @@ -181,6 +181,10 @@ public: { m_bbTrack = _bb_track; } + void setBBTrackFrom( notePlayHandle * _handle ) + { + m_bbTrack = _handle->m_bbTrack; + } virtual bool supportsParallelizing( void ) const diff --git a/include/piano_roll.h b/include/piano_roll.h index c6438cc75..cff274e3e 100644 --- a/include/piano_roll.h +++ b/include/piano_roll.h @@ -95,7 +95,6 @@ public: protected: virtual void closeEvent( QCloseEvent * _ce ); - virtual void enterEvent( QEvent * _e ); virtual void keyPressEvent( QKeyEvent * _ke ); virtual void keyReleaseEvent( QKeyEvent * _ke ); virtual void leaveEvent( QEvent * _e ); @@ -215,7 +214,6 @@ private: comboBox * m_noteLenComboBox; QPixmap m_paintPixmap; - bool m_cursorInside; pattern * m_pattern; @@ -244,7 +242,6 @@ private: midiTime m_lenOfNewNotes; int m_startKey; // first key when drawing - int m_keyMouseOver; int m_lastKey; noteVector m_notesToCopy; @@ -257,6 +254,7 @@ private: timeLine * m_timeLine; bool m_scrollBack; + void drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, Uint16 _y ); bool mouseOverNote( void ); note * noteUnderMouse( void ); noteVector::iterator noteIteratorUnderMouse( void ); diff --git a/include/xqmap.h b/include/xqmap.h new file mode 100644 index 000000000..607be9c06 --- /dev/null +++ b/include/xqmap.h @@ -0,0 +1,519 @@ +/* + * XQMap.h - eXtended QMap template for Qt3 + * + * Copyright (c) 2006 Javier Serrano Polo + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef XQMAP_H +#define XQMAP_H + +#include + + + + +template +class XQMapPrivate : public QMapPrivate +{ +public: + typedef QMapConstIterator ConstIterator; + typedef QMapNode * NodePtr; + + XQMapPrivate( void ); + XQMapPrivate( const XQMapPrivate * _map ); + + ConstIterator lowerBound( const Key & _k ) const; + +}; + + + + +template +Q_INLINE_TEMPLATES XQMapPrivate::XQMapPrivate( void ) +{ +} + + + + +template +Q_INLINE_TEMPLATES XQMapPrivate::XQMapPrivate( + const XQMapPrivate * _map ) : + QMapPrivate( _map ) +{ +} + + + + +template +Q_INLINE_TEMPLATES Q_TYPENAME XQMapPrivate::ConstIterator + XQMapPrivate::lowerBound( const Key & _k ) const +{ + QMapNodeBase * y = QMapPrivate::header; // Last node + QMapNodeBase * x = QMapPrivate::header->parent; // Root node + + while( x != 0 ) { + // If as k <= key(x) go left + if( !( QMapPrivate::key( x ) < _k ) ) + { + y = x; + x = x->left; + } + else + { + x = x->right; + } + } + + // Was _k bigger then the biggest element of the tree? Return end() + if( y == QMapPrivate::header ) + { + return( ConstIterator( QMapPrivate::header ) ); + } + return( ConstIterator( (NodePtr)y ) ); +} + + + + +template +class XQMap +{ +public: + /** + * Typedefs + */ + typedef Key key_type; + typedef T mapped_type; + typedef QPair value_type; + typedef value_type * pointer; + typedef const value_type * const_pointer; + typedef value_type & reference; + typedef const value_type & const_reference; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef size_t size_type; + typedef QMapIterator iterator; + typedef QMapConstIterator const_iterator; + typedef QPair insert_pair; + + typedef QMapIterator Iterator; + typedef QMapConstIterator ConstIterator; + typedef T ValueType; + typedef XQMapPrivate Priv; + + /** + * API + */ + XQMap( void ) + { + m_sh = new XQMapPrivate; + } + XQMap( const XQMap & _m ) + { + m_sh = _m.m_sh; + m_sh->ref(); + } + +#ifndef QT_NO_STL + XQMap( const std::map & _m ) + { + m_sh = new XQMapPrivate; + Q_TYPENAME std::map::const_iterator it = _m.begin(); + for( ; it != _m.end(); ++it ) + { + value_type p( ( *it ).first, ( *it ).second ); + insert( p ); + } + } +#endif + ~XQMap() + { + if( m_sh->deref() ) + { + delete m_sh; + } + } + XQMap & operator=( const XQMap & _m ); +#ifndef QT_NO_STL + XQMap & operator=( const std::map & _m ) + { + clear(); + Q_TYPENAME std::map::const_iterator it = _m.begin(); + for( ; it != _m.end(); ++it ) + { + value_type p( ( *it ).first, ( *it ).second ); + insert( p ); + } + return( *this ); + } +#endif + + iterator begin( void ) + { + detach(); + return( m_sh->begin() ); + } + iterator end( void ) + { + detach(); + return( m_sh->end() ); + } + const_iterator begin( void ) const + { + return( ( (const Priv *)m_sh )->begin() ); + } + const_iterator end( void ) const + { + return( ( (const Priv *)m_sh )->end() ); + } + const_iterator constBegin( void ) const + { + return( begin() ); + } + const_iterator constEnd( void ) const + { + return( end() ); + } + + iterator replace( const Key & _k, const T & _v ) + { + remove( _k ); + return( insert( _k, _v ) ); + } + + size_type size( void ) const + { + return( m_sh->node_count ); + } + bool empty( void ) const + { + return( m_sh->node_count == 0 ); + } + QPair insert( const value_type & _x ); + + void erase( iterator _it ) + { + detach(); + m_sh->remove( _it ); + } + void erase( const key_type & _k ); + size_type count( const key_type & _k ) const; + T & operator[]( const Key & _k ); + void clear( void ); + + iterator find( const Key & _k ) + { + detach(); + return( iterator( m_sh->find( _k ).node ) ); + } + + iterator lowerBound( const Key & _k ) + { + detach(); + return( iterator( m_sh->lowerBound( _k ).node ) ); + } + + const_iterator find( const Key & _k ) const + { + return( m_sh->find( _k ) ); + } + + const_iterator lowerBound( const Key & _k ) const + { + return( m_sh->lowerBound( _k ) ); + } + + const T & operator[]( const Key & _k ) const + { + QT_CHECK_INVALID_MAP_ELEMENT; + return( m_sh->find( _k ).data() ); + } + bool contains( const Key & _k ) const + { + return( find( _k ) != end() ); + } + + size_type count( void ) const + { + return( m_sh->node_count ); + } + + QValueList keys( void ) const + { + QValueList r; + for( const_iterator i = begin(); i != end(); ++i ) + { + r.append( i.key() ); + } + return( r ); + } + + QValueList values( void ) const + { + QValueList r; + for( const_iterator i = begin(); i != end(); ++i ) + r.append( *i ); + return( r ); + } + + bool isEmpty( void ) const + { + return( m_sh->node_count == 0 ); + } + + iterator insert( const Key & _key, const T & _value, + bool _overwrite = TRUE ); + void remove( iterator _it ) + { + detach(); + m_sh->remove( _it ); + } + void remove( const Key & _k ); + +#if defined( Q_FULL_TEMPLATE_INSTANTIATION ) + bool operator==( const XQMap & ) const + { + return( FALSE ); + } +#ifndef QT_NO_STL + bool operator==( const std::map & ) const + { + return( FALSE ); + } +#endif +#endif + + +protected: + /** + * Helpers + */ + void detach( void ) + { + if( m_sh->count > 1 ) + { + detachInternal(); + } + } + + Priv * m_sh; + + +private: + void detachInternal( void ); + + friend class QDeepCopy< XQMap >; + +} ; + + + + +template +Q_INLINE_TEMPLATES XQMap & XQMap::operator=( + const XQMap & _m ) +{ + _m.m_sh->ref(); + if( m_sh->deref() ) + { + delete m_sh; + } + m_sh = _m.m_sh; + return( *this ); +} + + + + +template +Q_INLINE_TEMPLATES Q_TYPENAME XQMap::insert_pair + XQMap::insert( const Q_TYPENAME XQMap::value_type & _x ) +{ + detach(); + size_type n = size(); + iterator it = m_sh->insertSingle( _x.first ); + bool inserted = FALSE; + if( n < size() ) + { + inserted = TRUE; + it.data() = _x.second; + } + return( QPair( it, inserted ) ); +} + + + + +template +Q_INLINE_TEMPLATES void XQMap::erase( const Key & _k ) +{ + detach(); + iterator it( m_sh->find( _k ).node ); + if( it != end() ) + { + m_sh->remove( it ); + } +} + +template +Q_INLINE_TEMPLATES Q_TYPENAME XQMap::size_type + XQMap::count( const Key & _k ) const +{ + const_iterator it( m_sh->find( _k ).node ); + if( it != end() ) + { + size_type c = 0; + while( it != end() ) + { + ++it; + ++c; + } + return( c ); + } + return( 0 ); +} + + + + +template +Q_INLINE_TEMPLATES T & XQMap::operator[]( const Key & _k ) +{ + detach(); + QMapNode * p = m_sh->find( _k ).node; + if( p != m_sh->end().node ) + { + return( p->data ); + } + return( insert( _k, T() ).data() ); +} + + + + +template +Q_INLINE_TEMPLATES void XQMap::clear( void ) +{ + if( m_sh->count == 1 ) + { + m_sh->clear(); + } + else + { + m_sh->deref(); + m_sh = new XQMapPrivate; + } +} + + + + +template +Q_INLINE_TEMPLATES Q_TYPENAME XQMap::iterator XQMap::insert( + const Key & _key, const T & _value, bool _overwrite ) +{ + detach(); + size_type n = size(); + iterator it = m_sh->insertSingle( _key ); + if( _overwrite || n < size() ) + { + it.data() = _value; + } + return( it ); +} + + + + +template +Q_INLINE_TEMPLATES void XQMap::remove( const Key & _k ) +{ + detach(); + iterator it( m_sh->find( _k ).node ); + if( it != end() ) + { + m_sh->remove( it ); + } +} + + + + +template +Q_INLINE_TEMPLATES void XQMap::detachInternal( void ) +{ + m_sh->deref(); + m_sh = new XQMapPrivate( m_sh ); +} + + + + +#ifndef QT_NO_DATASTREAM +template +Q_INLINE_TEMPLATES QDataStream & operator>>( QDataStream & _s, + XQMap & _m ) +{ + _m.clear(); + Q_UINT32 c; + _s >> c; + for( Q_UINT32 i = 0; i < c; ++i ) + { + Key k; + T t; + _s >> k >> t; + _m.insert( k, t ); + if( _s.atEnd() ) + { + break; + } + } + return( _s ); +} + + + + +template +Q_INLINE_TEMPLATES QDataStream & operator<<( QDataStream & _s, + const XQMap & _m ) +{ + _s << (Q_UINT32)_m.size(); + QMapConstIterator it = _m.begin(); + for( ; it != _m.end(); ++it ) + { + _s << it.key() << it.data(); + } + return( _s ); +} +#endif + + + + +#endif diff --git a/src/audio/audio_alsa.cpp b/src/audio/audio_alsa.cpp index 801c62df0..7dbb6f85a 100644 --- a/src/audio/audio_alsa.cpp +++ b/src/audio/audio_alsa.cpp @@ -79,7 +79,7 @@ audioALSA::audioALSA( const sample_rate_t _sample_rate, bool & _success_ful, probeDevice().ascii(), #endif SND_PCM_STREAM_PLAYBACK, - SND_PCM_NONBLOCK ) ) < 0 ) + 0 ) ) < 0 ) { printf( "Playback open error: %s\n", snd_strerror( err ) ); return; @@ -221,25 +221,47 @@ void audioALSA::run( void ) int_sample_t * outbuf = bufferAllocator::alloc( getMixer()->framesPerAudioBuffer() * channels() ); + int_sample_t * pcmbuf = bufferAllocator::alloc( + m_periodSize * channels() ); m_quit = FALSE; + int outbuf_size = getMixer()->framesPerAudioBuffer() * channels(); + int outbuf_pos = 0; + int pcmbuf_size = m_periodSize * channels(); + while( m_quit == FALSE ) { - const f_cnt_t frames = getNextBuffer( temp ); + int_sample_t * ptr = pcmbuf; + int len = pcmbuf_size; + while( len ) + { + if( outbuf_pos == 0 ) + { + const fpab_t frames = getNextBuffer( temp ); - convertToS16( temp, frames, getMixer()->masterGain(), outbuf, - m_convertEndian ); + convertToS16( temp, frames, + getMixer()->masterGain(), + outbuf, + m_convertEndian ); + } + int min_len = tMin( len, outbuf_size - outbuf_pos ); + memcpy( ptr, outbuf + outbuf_pos, + min_len * sizeof( int_sample_t ) ); + ptr += min_len; + len -= min_len; + outbuf_pos += min_len; + outbuf_pos %= outbuf_size; + } - f_cnt_t frame = 0; - int_sample_t * ptr = outbuf; + f_cnt_t frames = m_periodSize; + ptr = pcmbuf; - while( frame < frames ) + while( frames ) { int err = snd_pcm_writei( m_handle, ptr, frames ); if( err == -EAGAIN ) { - usleep( 10 ); continue; } @@ -253,12 +275,13 @@ void audioALSA::run( void ) break; // skip this buffer } ptr += err * channels(); - frame += err; + frames -= err; } } bufferAllocator::free( temp ); bufferAllocator::free( outbuf ); + bufferAllocator::free( pcmbuf ); } diff --git a/src/core/arp_and_chords_tab_widget.cpp b/src/core/arp_and_chords_tab_widget.cpp index 4a97b5cce..6b846d75a 100644 --- a/src/core/arp_and_chords_tab_widget.cpp +++ b/src/core/arp_and_chords_tab_widget.cpp @@ -476,6 +476,7 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n ) _n->getInstrumentTrack(), _n->framesAhead(), _n->frames(), note_copy ); + note_play_handle->setBBTrackFrom( _n ); // add sub-note to base-note, now all stuff is // done by notePlayHandle::play_note() _n->addSubNote( note_play_handle ); @@ -638,6 +639,7 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n ) gated_frames, new_note, TRUE ); + note_play_handle->setBBTrackFrom( _n ); // add sub-note to base-note - now all stuff is done by // notePlayHandle::playNote() diff --git a/src/core/automation_editor.cpp b/src/core/automation_editor.cpp index 46a2e19f5..6a6f0d21a 100644 --- a/src/core/automation_editor.cpp +++ b/src/core/automation_editor.cpp @@ -89,7 +89,6 @@ automationEditor::automationEditor( engine * _engine ) : QWidget( _engine->getMainWindow()->workspace() ), journallingObject( _engine ), m_paintPixmap(), - m_cursorInside( FALSE ), m_pattern( NULL ), m_min_level( 0 ), m_max_level( 0 ), @@ -678,10 +677,10 @@ void automationEditor::updatePaintPixmap( void ) if( validPattern() == TRUE ) { timeMap & time_map = m_pattern->getTimeMap(); - - for( timeMap::iterator it = time_map.begin(), it_next; - it != time_map.end(); ++it ) + timeMap::iterator it = time_map.end(); + do { + --it; Sint32 len_tact_64th = 4; #ifdef QT3 @@ -690,36 +689,35 @@ void automationEditor::updatePaintPixmap( void ) const int level = it.value(); #endif - Sint32 pos_tact_64th = it.key(); + Sint32 pos_tact_64th = -it.key(); const int x = ( pos_tact_64th - m_currentPosition ) * m_ppt / 64; - - it_next = it; - ++it_next; - - int next_x; - int rect_width; - if( it_next != time_map.end() ) + if( x > width() - VALUES_WIDTH ) { - Sint32 next_pos_tact_64th = it_next.key(); - next_x = ( next_pos_tact_64th + break; + } + + int rect_width; + if( it != time_map.begin() ) + { + timeMap::iterator it_prev = it; + --it_prev; + Sint32 next_pos_tact_64th = -it_prev.key(); + int next_x = ( next_pos_tact_64th - m_currentPosition ) * m_ppt / 64; + // skip this value if not in visible area at all + if( next_x < 0 ) + { + continue; + } rect_width = next_x - x; } else { - next_x = -1; rect_width = width() - x; } - // skip this value if not in visible area at all - if( !xVisible( x ) && !xVisible( next_x ) - && it_next != time_map.end() ) - { - continue; - } - // is the value in visible area? if( ( level >= m_bottom_level && level <= m_top_level ) || ( level > m_top_level && m_top_level >= 0 ) @@ -776,7 +774,7 @@ void automationEditor::updatePaintPixmap( void ) rect_width, rect_height, is_selected ); } - } + } while( it != time_map.begin() ); } else { @@ -852,15 +850,6 @@ void automationEditor::closeEvent( QCloseEvent * _ce ) -void automationEditor::enterEvent( QEvent * _e ) -{ - m_cursorInside = TRUE; - QWidget::enterEvent( _e ); -} - - - - void automationEditor::keyPressEvent( QKeyEvent * _ke ) { switch( _ke->key() ) @@ -1018,7 +1007,6 @@ void automationEditor::leaveEvent( QEvent * _e ) { QApplication::restoreOverrideCursor(); } - m_cursorInside = FALSE; QWidget::leaveEvent( _e ); } @@ -1062,9 +1050,9 @@ void automationEditor::mousePressEvent( QMouseEvent * _me ) // and check whether the user clicked on an // existing value - if( pos_tact_64th >= it.key() && + if( pos_tact_64th >= -it.key() && len > 0 && - pos_tact_64th <= it.key() + len && + pos_tact_64th <= -it.key() + len && #ifdef QT3 it.data() == level ) #else @@ -1094,18 +1082,13 @@ void automationEditor::mousePressEvent( QMouseEvent * _me ) // reset it so that it can be used for // ops (move, resize) after this // code-block - it = time_map.begin(); - while( it != time_map.end() && - it.key() != new_time ) - { - ++it; - } + it = time_map.find( -new_time ); } // move it m_action = MOVE_VALUE; int aligned_x = (int)( (float)( ( - it.key() - + -it.key() - m_currentPosition ) * m_ppt ) / 64.0f ); m_moveXOffset = x - aligned_x - 1; @@ -1123,7 +1106,7 @@ void automationEditor::mousePressEvent( QMouseEvent * _me ) if( it != time_map.end() ) { - m_pattern->removeValue( it.key() ); + m_pattern->removeValue( -it.key() ); eng()->getSongEditor()->setModified(); } } @@ -1268,8 +1251,8 @@ void automationEditor::mouseMoveEvent( QMouseEvent * _me ) { // and check whether the cursor is over an // existing value - if( pos_tact_64th >= it.key() && - pos_tact_64th <= it.key() + + if( pos_tact_64th >= -it.key() && + pos_tact_64th <= -it.key() + //TODO: Add constant 4 && #ifdef QT3 @@ -1456,31 +1439,27 @@ void automationEditor::mouseMoveEvent( QMouseEvent * _me ) for( timeMap::iterator it = m_selValuesForMove.begin(); it != m_selValuesForMove.end(); ++it ) { - int value_tact = it.key().getTact() + tact_diff; - int value_tact_64th = it.key().getTact64th() + + int value_tact = ( -it.key() >> 6 ) + tact_diff; + int value_tact_64th = ( -it.key() & 63 ) + tact_64th_diff; - while( value_tact_64th < 0 ) + // ensure value_tact_64th range + if( value_tact_64th >> 6 ) { - --value_tact; - value_tact_64th += 64; + value_tact += value_tact_64th >> 6; + value_tact_64th &= 63; } - while( value_tact_64th > 64 ) - { - ++value_tact; - value_tact_64th -= 64; - } - m_pattern->removeValue( it.key() ); + m_pattern->removeValue( -it.key() ); midiTime new_value_pos( value_tact, value_tact_64th ); #ifdef QT3 new_selValuesForMove[ - m_pattern->putValue( new_value_pos, + -m_pattern->putValue( new_value_pos, it.data () + level_diff, FALSE )] = it.data() + level_diff; #else new_selValuesForMove[ - m_pattern->putValue( new_value_pos, + -m_pattern->putValue( new_value_pos, it.value () + level_diff, FALSE )] = it.value() + level_diff; @@ -1590,31 +1569,26 @@ void automationEditor::paintEvent( QPaintEvent * ) #endif p.drawPixmap( 0, 0, m_paintPixmap ); - if( m_cursorInside == TRUE ) - { - p.setClipRect( VALUES_WIDTH, TOP_MARGIN, width() - VALUES_WIDTH, + p.setClipRect( VALUES_WIDTH, TOP_MARGIN, width() - VALUES_WIDTH, height() - TOP_MARGIN - SCROLLBAR_SIZE ); - if( validPattern() == TRUE ) - { -//TODO: What's this? - p.fillRect( 10, height() + 3 - SCROLLBAR_SIZE, - width() - 10, DEFAULT_Y_DELTA - 7, - QColor( 64, 64, 64 ) ); - } - const QPixmap * cursor = NULL; - // draw current edit-mode-icon below the cursor - switch( m_editMode ) - { - case DRAW: cursor = s_toolDraw; break; - case ERASE: cursor = s_toolErase; break; - case SELECT: cursor = s_toolSelect; break; - case MOVE: cursor = s_toolMove; break; - } - p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), - *cursor ); + if( validPattern() == TRUE ) + { + drawCross( p ); } + const QPixmap * cursor = NULL; + // draw current edit-mode-icon below the cursor + switch( m_editMode ) + { + case DRAW: cursor = s_toolDraw; break; + case ERASE: cursor = s_toolErase; break; + case SELECT: cursor = s_toolSelect; break; + case MOVE: cursor = s_toolMove; break; + } + p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), + *cursor ); + #ifndef QT4 // and blit all the drawn stuff on the screen... bitBlt( this, rect().topLeft(), &draw_pm ); @@ -1624,6 +1598,26 @@ void automationEditor::paintEvent( QPaintEvent * ) +inline void automationEditor::drawCross( QPainter & _p ) +{ + QPoint mouse_pos = mapFromGlobal( QCursor::pos() ); + int level = getLevel( mouse_pos.y() ); + int grid_bottom = height() - SCROLLBAR_SIZE - 1; + int cross_y = m_y_auto ? + grid_bottom - (int)roundf( ( grid_bottom - TOP_MARGIN ) + * ( level - m_min_level ) + / (float)( m_max_level - m_min_level ) ) : + grid_bottom - ( level - m_bottom_level ) * m_y_delta; + + _p.setPen( QColor( 0xFF, 0x33, 0x33 ) ); + _p.drawLine( VALUES_WIDTH, cross_y, width(), cross_y ); + _p.drawLine( mouse_pos.x(), TOP_MARGIN, mouse_pos.x(), + height() - SCROLLBAR_SIZE ); +} + + + + // responsible for moving/resizing scrollbars after window-resizing void automationEditor::resizeEvent( QResizeEvent * ) { @@ -1919,7 +1913,7 @@ void automationEditor::selectAll( void ) const int level = it.value(); #endif - Uint32 pos_tact_64th = it.key(); + Uint32 pos_tact_64th = -it.key(); if( level <= m_selectStartLevel || first_time ) { // if we move start-level down, we have to add @@ -1988,7 +1982,7 @@ void automationEditor::getSelectedValues( timeMap & _selected_values ) #else int level = it.value(); #endif - Sint32 pos_tact_64th = it.key(); + Sint32 pos_tact_64th = -it.key(); if( level > sel_level_start && level <= sel_level_end && pos_tact_64th >= sel_pos_start && @@ -2011,8 +2005,6 @@ void automationEditor::copySelectedValues( void ) if( !selected_values.isEmpty() ) { - midiTime start_pos( selected_values.begin().key().getTact(), - 0 ); for( timeMap::iterator it = selected_values.begin(); it != selected_values.end(); ++it ) { @@ -2048,9 +2040,6 @@ void automationEditor::cutSelectedValues( void ) { eng()->getSongEditor()->setModified(); - midiTime start_pos( selected_values.begin().key().getTact(), - 0 ); - for( timeMap::iterator it = selected_values.begin(); it != selected_values.end(); ++it ) { @@ -2059,7 +2048,7 @@ void automationEditor::cutSelectedValues( void ) #else m_valuesToCopy[it.key()] = it.value(); #endif - m_pattern->removeValue( it.key() ); + m_pattern->removeValue( -it.key() ); } } @@ -2082,7 +2071,7 @@ void automationEditor::pasteValues( void ) for( timeMap::iterator it = m_valuesToCopy.begin(); it != m_valuesToCopy.end(); ++it ) { - m_pattern->putValue( it.key() + m_currentPosition, + m_pattern->putValue( -it.key() + m_currentPosition, #ifdef QT3 it.data() ); #else @@ -2116,7 +2105,7 @@ void automationEditor::deleteSelectedValues( void ) for( timeMap::iterator it = selected_values.begin(); it != selected_values.end(); ++it ) { - m_pattern->removeValue( it.key() ); + m_pattern->removeValue( -it.key() ); } if( update_after_delete == TRUE ) @@ -2241,18 +2230,23 @@ void automationEditor::updateTopBottomLevels( void ) -inline bool automationEditor::xVisible( int _x ) +inline bool automationEditor::inBBEditor( void ) { - return( _x >= 0 && _x <= width() - VALUES_WIDTH ); + return( m_pattern->getTrack()->getTrackContainer() + == eng()->getBBEditor() ); } -inline bool automationEditor::inBBEditor( void ) +void automationEditor::update( void ) { - return( m_pattern->getTrack()->getTrackContainer() - == eng()->getBBEditor() ); + QWidget::update(); + // Note detuning? + if( m_pattern && !m_pattern->getTrack() ) + { + eng()->getPianoRoll()->update(); + } } diff --git a/src/core/bb_editor.cpp b/src/core/bb_editor.cpp index 7aa76cc43..00a296147 100644 --- a/src/core/bb_editor.cpp +++ b/src/core/bb_editor.cpp @@ -462,6 +462,11 @@ void bbEditor::updateAfterTrackAdd( void ) void bbEditor::createTCOsForBB( csize _bb ) { + if( numOfBBs() == 0 ) + { + return; + } + trackVector tv = tracks(); for( trackVector::iterator it = tv.begin(); it != tv.end(); ++it ) { diff --git a/src/core/name_label.cpp b/src/core/name_label.cpp index cea2b832d..c8d6a02f6 100644 --- a/src/core/name_label.cpp +++ b/src/core/name_label.cpp @@ -83,16 +83,22 @@ void nameLabel::setPixmap( const QPixmap & _pixmap ) void nameLabel::setPixmapFile( const QString & _file ) { - m_pixmapFile = _file; - if( QFileInfo( m_pixmapFile ).isRelative() ) + QPixmap new_pixmap; + if( QFileInfo( _file ).isRelative() ) { - m_pixmap = QPixmap( configManager::inst()->trackIconsDir() + - m_pixmapFile ); + new_pixmap = QPixmap( configManager::inst()->trackIconsDir() + + _file ); } else { - m_pixmap = QPixmap( m_pixmapFile ); + new_pixmap = QPixmap( _file ); } + if( new_pixmap.isNull() ) + { + return; + } + m_pixmap = new_pixmap; + m_pixmapFile = _file; emit( pixmapChanged() ); update(); } diff --git a/src/core/note.cpp b/src/core/note.cpp index d9fec800b..7897605fb 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -342,4 +342,14 @@ void note::detachCurrentDetuning( void ) +bool note::hasDetuningInfo( void ) +{ + automationPattern::timeMap map = + m_detuning->getAutomationPattern()->getTimeMap(); + return( map.size() > 1 || map[0] != 0 ); +} + + + + #endif diff --git a/src/core/piano_roll.cpp b/src/core/piano_roll.cpp index 74748f7e0..e0fd35cd7 100644 --- a/src/core/piano_roll.cpp +++ b/src/core/piano_roll.cpp @@ -79,6 +79,9 @@ #include "piano_widget.h" +typedef automationPattern::timeMap timeMap; + + extern tones whiteKeys[]; // defined in piano_widget.cpp @@ -136,7 +139,6 @@ pianoRoll::pianoRoll( engine * _engine ) : QWidget( _engine->getMainWindow()->workspace() ), journallingObject( _engine ), m_paintPixmap(), - m_cursorInside( FALSE ), m_pattern( NULL ), m_currentPosition(), m_recording( FALSE ), @@ -148,7 +150,6 @@ pianoRoll::pianoRoll( engine * _engine ) : m_ppt( DEFAULT_PR_PPT ), m_lenOfNewNotes( midiTime( 0, 16 ) ), m_startKey( INITIAL_START_KEY ), - m_keyMouseOver( INITIAL_START_KEY ), m_lastKey( 0 ), m_editMode( DRAW ), m_scrollBack( FALSE ) @@ -870,6 +871,12 @@ void pianoRoll::updatePaintPixmap( void ) int y_base = height() - PR_BOTTOM_MARGIN - m_notesEditHeight - 1; if( validPattern() == TRUE ) { + QPainter p_detuning( &m_paintPixmap ); + p_detuning.setClipRect( WHITE_KEY_WIDTH, PR_TOP_MARGIN, + width() - WHITE_KEY_WIDTH, + height() - PR_TOP_MARGIN - PR_BOTTOM_MARGIN + - m_notesEditHeight ); + noteVector & notes = m_pattern->notes(); const int visible_keys = ( height() - PR_TOP_MARGIN - @@ -946,6 +953,13 @@ void pianoRoll::updatePaintPixmap( void ) ( *it )->getVolume() / 2, x + WHITE_KEY_WIDTH + 1, height() - PR_BOTTOM_MARGIN ); + + if( ( *it )->hasDetuningInfo() ) + { + drawDetuningInfo( p_detuning, *it, + x + WHITE_KEY_WIDTH, + y_base - key * KEY_LINE_HEIGHT ); + } } } else @@ -987,6 +1001,39 @@ void pianoRoll::updatePaintPixmap( void ) +inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, + Uint16 _y ) +{ + Uint16 middle_y = _y + KEY_LINE_HEIGHT / 2; + _p.setPen( QColor( 0xFF, 0xDF, 0x20 ) ); + + timeMap & map = _n->detuning()->getAutomationPattern()->getTimeMap(); + timeMap::iterator it = map.end(); + do + { + --it; + Sint32 pos_tact_64th = -it.key(); + if( pos_tact_64th > _n->length() ) + { + break; + } + Uint16 pos_x = _x + pos_tact_64th * m_ppt / 64; + +#ifdef QT3 + const int level = it.data(); +#else + const int level = it.value(); +#endif + Uint16 pos_y = middle_y - level * KEY_LINE_HEIGHT / 10; + + _p.drawLine( pos_x - 1, pos_y, pos_x + 1, pos_y ); + _p.drawLine( pos_x, pos_y - 1, pos_x, pos_y + 1 ); + } while( it != map.begin() ); +} + + + + void pianoRoll::removeSelection( void ) { m_selectStartTact64th = 0; @@ -1008,15 +1055,6 @@ void pianoRoll::closeEvent( QCloseEvent * _ce ) -void pianoRoll::enterEvent( QEvent * _e ) -{ - m_cursorInside = TRUE; - QWidget::enterEvent( _e ); -} - - - - void pianoRoll::keyPressEvent( QKeyEvent * _ke ) { if( validPattern() ) @@ -1215,7 +1253,6 @@ void pianoRoll::leaveEvent( QEvent * _e ) { QApplication::restoreOverrideCursor(); } - m_cursorInside = FALSE; QWidget::leaveEvent( _e ); } @@ -1455,6 +1492,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) if( play_note == TRUE && m_recording == FALSE && eng()->getSongEditor()->playing() == FALSE ) { + m_lastKey = key_num; m_pattern->getInstrumentTrack()->processInEvent( midiEvent( NOTE_ON, 0, key_num, vol * 127 / 100 ), @@ -1479,7 +1517,7 @@ void pianoRoll::mouseReleaseEvent( QMouseEvent * _me ) else { m_pattern->getInstrumentTrack()->processInEvent( - midiEvent( NOTE_OFF, 0, getKey( _me->y() ), 0 ), + midiEvent( NOTE_OFF, 0, m_lastKey, 0 ), midiTime() ); } } @@ -1505,22 +1543,18 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) return; } - // save current last-key-var - int released_key = m_lastKey; - if( _me->y() > PR_TOP_MARGIN ) { bool edit_note = ( _me->y() > height() - PR_BOTTOM_MARGIN - m_notesEditHeight ); int key_num = getKey( _me->y() ); - m_keyMouseOver = key_num; int x = _me->x(); // is the calculated key different from current key? // (could be the user just moved the cursor one pixel up/down // but is still on the same key) - if( key_num != released_key && + if( key_num != m_lastKey && m_action != CHANGE_NOTE_VOLUME && m_action != MOVE_SELECTION && edit_note == FALSE && @@ -1532,7 +1566,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) Qt::LeftButton ) { m_pattern->getInstrumentTrack()->processInEvent( - midiEvent( NOTE_OFF, 0, released_key, 0 ), + midiEvent( NOTE_OFF, 0, m_lastKey, 0 ), midiTime() ); if( #ifdef QT4 @@ -1547,6 +1581,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) m_recording == FALSE && eng()->getSongEditor()->playing() == FALSE ) { + m_lastKey = key_num; m_pattern->getInstrumentTrack()->processInEvent( midiEvent( NOTE_ON, 0, key_num, DEFAULT_VOLUME * 127 / 100 ), @@ -1886,15 +1921,11 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) int note_tact_64th = ( *it )->pos().getTact64th() + tact_64th_diff; - while( note_tact_64th < 0 ) + // ensure note_tact_64th range + if( note_tact_64th >> 6 ) { - --note_tact; - note_tact_64th += 64; - } - while( note_tact_64th > 64 ) - { - ++note_tact; - note_tact_64th -= 64; + note_tact += note_tact_64th >> 6; + note_tact_64th &= 63; } midiTime new_note_pos( note_tact, note_tact_64th ); @@ -2019,34 +2050,32 @@ void pianoRoll::paintEvent( QPaintEvent * ) #endif p.drawPixmap( 0, 0, m_paintPixmap ); - if( m_cursorInside == TRUE ) - { - p.setClipRect( WHITE_KEY_WIDTH, PR_TOP_MARGIN, width() - + p.setClipRect( WHITE_KEY_WIDTH, PR_TOP_MARGIN, width() - WHITE_KEY_WIDTH, height() - PR_TOP_MARGIN - m_notesEditHeight - PR_BOTTOM_MARGIN ); - if( validPattern() == TRUE ) - { - p.fillRect( 10, height() + 3 - PR_BOTTOM_MARGIN - + if( validPattern() == TRUE ) + { + int key_num = getKey( mapFromGlobal( QCursor::pos() ).y() ); + p.fillRect( 10, height() + 3 - PR_BOTTOM_MARGIN - m_notesEditHeight - KEY_LINE_HEIGHT * - ( m_keyMouseOver - m_startKey + 1 ), + ( key_num - m_startKey + 1 ), width() - 10, KEY_LINE_HEIGHT - 7, QColor( 64, 64, 64 ) ); - } - - const QPixmap * cursor = NULL; - // draw current edit-mode-icon below the cursor - switch( m_editMode ) - { - case DRAW: cursor = s_toolDraw; break; - case ERASE: cursor = s_toolErase; break; - case SELECT: cursor = s_toolSelect; break; - case MOVE: cursor = s_toolMove; break; - case OPEN: cursor = s_toolOpen; break; - } - p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), - *cursor ); } + const QPixmap * cursor = NULL; + // draw current edit-mode-icon below the cursor + switch( m_editMode ) + { + case DRAW: cursor = s_toolDraw; break; + case ERASE: cursor = s_toolErase; break; + case SELECT: cursor = s_toolSelect; break; + case MOVE: cursor = s_toolMove; break; + case OPEN: cursor = s_toolOpen; break; + } + p.drawPixmap( mapFromGlobal( QCursor::pos() ) + QPoint( 8, 8 ), + *cursor ); + #ifndef QT4 // and blit all the drawn stuff on the screen... bitBlt( this, rect().topLeft(), &draw_pm ); @@ -2152,7 +2181,7 @@ int pianoRoll::getKey( int _y ) key_num = NOTES_PER_OCTAVE * OCTAVES - 1; } - return( m_lastKey = key_num ); + return( key_num ); } diff --git a/src/core/setup_dialog.cpp b/src/core/setup_dialog.cpp index 3c0756570..15a738fd2 100644 --- a/src/core/setup_dialog.cpp +++ b/src/core/setup_dialog.cpp @@ -205,7 +205,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * disable_tooltips = new ledCheckBox( tr( "Disable tooltips (no spurious " "interrupts while playing)" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); disable_tooltips->move( 10, 18 ); disable_tooltips->setChecked( m_disableToolTips ); connect( disable_tooltips, SIGNAL( toggled( bool ) ), @@ -216,7 +216,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : tr( "Classical knob usability (move " "cursor around knob to change " "value)" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); classical_knob_usability->move( 10, 36 ); classical_knob_usability->setChecked( m_classicalKnobUsability ); connect( classical_knob_usability, SIGNAL( toggled( bool ) ), @@ -225,7 +225,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * gimp_like_windows = new ledCheckBox( tr( "GIMP-like windows (no MDI)" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); gimp_like_windows->move( 10, 54 ); gimp_like_windows->setChecked( m_gimpLikeWindows ); connect( gimp_like_windows, SIGNAL( toggled( bool ) ), @@ -234,7 +234,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * no_wizard = new ledCheckBox( tr( "Do not show wizard after up-/downgrade" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); no_wizard->move( 10, 72 ); no_wizard->setChecked( m_noWizard ); connect( no_wizard, SIGNAL( toggled( bool ) ), @@ -244,7 +244,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * no_msg = new ledCheckBox( tr( "Do not show message after " "closing this dialog" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); no_msg->move( 10, 90 ); no_msg->setChecked( m_noMsgAfterSetup ); connect( no_msg, SIGNAL( toggled( bool ) ), @@ -253,7 +253,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * dbv = new ledCheckBox( tr( "Display volume as dbV " ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); dbv->move( 10, 108 ); dbv->setChecked( m_displaydBV ); connect( dbv, SIGNAL( toggled( bool ) ), @@ -262,7 +262,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * no_mmpz = new ledCheckBox( tr( "Do not compress project files per default" ), - misc_tw, NULL, eng(), NULL ); + misc_tw, NULL, NULL, NULL ); no_mmpz->move( 10, 126 ); no_mmpz->setChecked( m_noMMPZ ); connect( no_mmpz, SIGNAL( toggled( bool ) ), @@ -436,7 +436,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * disable_ch_act_ind = new ledCheckBox( tr( "Disable channel activity indicators" ), - ui_fx_tw, NULL, eng(), NULL ); + ui_fx_tw, NULL, NULL, NULL ); disable_ch_act_ind->move( 10, 20 ); disable_ch_act_ind->setChecked( m_disableChActInd ); connect( disable_ch_act_ind, SIGNAL( toggled( bool ) ), @@ -445,7 +445,7 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : ledCheckBox * manual_ch_piano = new ledCheckBox( tr( "Only press keys on channel-piano manually" ), - ui_fx_tw, NULL, eng(), NULL ); + ui_fx_tw, NULL, NULL, NULL ); manual_ch_piano->move( 10, 40 ); manual_ch_piano->setChecked( m_manualChPiano ); connect( manual_ch_piano, SIGNAL( toggled( bool ) ), @@ -460,9 +460,8 @@ setupDialog::setupDialog( engine * _engine, configTabs _tab_to_open ) : QLabel * par_level_lbl = new QLabel( tr( "Parallelizing level" ), smp_supp_tw ); par_level_lbl->move( 10, 15 ); - lcdSpinBox * par_level = new lcdSpinBox( 1, 16, 2, smp_supp_tw, - tr( "SMP-level" ), - eng(), NULL ); + lcdSpinBox * par_level = new lcdSpinBox( 1, 16, 2, smp_supp_tw, NULL, + NULL, NULL ); par_level->setValue( m_parLevel ); connect( par_level, SIGNAL( valueChanged( int ) ), this, SLOT( setParallelizingLevel( int ) ) ); diff --git a/src/tracks/automation_pattern.cpp b/src/tracks/automation_pattern.cpp index 1e6d0f184..65867b5cc 100644 --- a/src/tracks/automation_pattern.cpp +++ b/src/tracks/automation_pattern.cpp @@ -145,7 +145,7 @@ midiTime automationPattern::length( void ) const it != m_time_map.end(); ++it ) { - max_length = tMax( max_length, it.key() ); + max_length = tMax( max_length, -it.key() ); } if( max_length % 64 == 0 ) { @@ -166,7 +166,7 @@ midiTime automationPattern::putValue( const midiTime & _time, const int _value, eng()->getAutomationEditor()->quantization() ) : _time; - m_time_map[new_time] = _value; + m_time_map[-new_time] = _value; return( new_time ); } @@ -178,7 +178,7 @@ void automationPattern::removeValue( const midiTime & _time ) { if( _time != 0 ) { - m_time_map.remove( _time ); + m_time_map.remove( -_time ); } } @@ -199,12 +199,7 @@ void automationPattern::clear( void ) int automationPattern::valueAt( const midiTime & _time ) { - if( m_time_map.contains( _time ) ) - { - return( m_time_map[_time] ); - } - //TODO: Return a better value!! - return( 0 ); + return( m_time_map.lowerBound( -_time ).value() ); } @@ -216,7 +211,7 @@ void automationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this ) ++it ) { QDomElement element = _doc.createElement( "time" ); - element.setAttribute( "pos", static_cast( it.key() ) ); + element.setAttribute( "pos", -it.key() ); element.setAttribute( "value", m_object->levelToLabel( it.value() ) ); _this.appendChild( element ); @@ -238,7 +233,7 @@ void automationPattern::loadSettings( const QDomElement & _this ) { continue; } - m_time_map[midiTime( element.attribute( "pos" ).toInt() )] + m_time_map[-element.attribute( "pos" ).toInt()] = m_object->labelToLevel( element.attribute( "value" ) ); } @@ -276,9 +271,9 @@ const QString automationPattern::name( void ) void automationPattern::processMidiTime( const midiTime & _time ) { - timeMap::iterator it = m_time_map.find( _time ); - if( it != m_time_map.end() ) + if( _time >= 0 ) { + timeMap::iterator it = m_time_map.lowerBound( -_time ); m_object->setLevel( it.value() ); } } diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index ff02271fe..6a54be35a 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -919,7 +919,7 @@ bool FASTCALL instrumentTrack::play( const midiTime & _start, trackContentObject * tco = getTCO( _tco_num ); tcos.push_back( tco ); bb_track = bbTrack::findBBTrack( _tco_num, eng() ); - if( bb_track != NULL && !( bb_track->automationDisabled( this ) + if( !( bb_track->automationDisabled( this ) || dynamic_cast( tco )->empty() ) ) { sendMidiTime( _start ); diff --git a/src/widgets/knob.cpp b/src/widgets/knob.cpp index d93555942..f9c45beef 100644 --- a/src/widgets/knob.cpp +++ b/src/widgets/knob.cpp @@ -432,8 +432,7 @@ void knob::mousePressEvent( QMouseEvent * _me ) eng()->getMainWindow()->isCtrlPressed() == FALSE && eng()->getMainWindow()->isShiftPressed() == FALSE ) { - setJournalling( FALSE ); - m_oldValue = value(); + prepareJournalEntryFromOldVal(); const QPoint & p = _me->pos(); m_origMousePos = p; @@ -509,7 +508,6 @@ void knob::mouseMoveEvent( QMouseEvent * _me ) //! Mouse Release Event handler void knob::mouseReleaseEvent( QMouseEvent * /* _me*/ ) { - setJournalling( TRUE ); addJournalEntryFromOldToCurVal(); if( m_buttonPressed ) diff --git a/src/widgets/lcd_spinbox.cpp b/src/widgets/lcd_spinbox.cpp index c494a1e43..78aa2259e 100644 --- a/src/widgets/lcd_spinbox.cpp +++ b/src/widgets/lcd_spinbox.cpp @@ -219,7 +219,7 @@ void lcdSpinBox::mousePressEvent( QMouseEvent * _me ) { m_origMousePos = _me->globalPos(); QApplication::setOverrideCursor( Qt::BlankCursor ); - m_oldValue = value(); + prepareJournalEntryFromOldVal(); } } diff --git a/src/widgets/tempo_sync_knob.cpp b/src/widgets/tempo_sync_knob.cpp index 8c343edb7..e68522bb1 100644 --- a/src/widgets/tempo_sync_knob.cpp +++ b/src/widgets/tempo_sync_knob.cpp @@ -316,8 +316,6 @@ void tempoSyncKnob::calculateTempoSyncTime( bpm_t _bpm ) "/" + QString::number( m_custom->getDenominator() ) + ")"; - m_tempoSyncIcon = embed::getIconPixmap( - "dont_know" ); conversionFactor = static_cast( m_custom->getDenominator() ) / static_cast( m_custom->getNumerator() ); @@ -325,73 +323,101 @@ void tempoSyncKnob::calculateTempoSyncTime( bpm_t _bpm ) case DOUBLE_WHOLE_NOTE: m_tempoSyncDescription = tr( "Synced to Eight Beats" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_double_whole" ); conversionFactor = 0.125; break; case WHOLE_NOTE: m_tempoSyncDescription = tr( "Synced to Whole Note" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_whole" ); conversionFactor = 0.25; break; case HALF_NOTE: m_tempoSyncDescription = tr( "Synced to Half Note" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_half" ); conversionFactor = 0.5; break; case QUARTER_NOTE: m_tempoSyncDescription = tr( "Synced to Quarter Note" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_quarter" ); conversionFactor = 1.0; break; case EIGHTH_NOTE: m_tempoSyncDescription = tr( "Synced to 8th Note" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_eighth" ); conversionFactor = 2.0; break; case SIXTEENTH_NOTE: m_tempoSyncDescription = tr( "Synced to 16th Note" ); - m_tempoSyncIcon = embed::getIconPixmap( - "note_sixteenth" ); conversionFactor = 4.0; break; case THIRTYSECOND_NOTE: m_tempoSyncDescription = tr( "Synced to 32nd Note" ); + conversionFactor = 8.0; + break; + default: ; + } + bool journalling = testAndSetJournalling( FALSE ); + setValue( 60000.0 / ( _bpm * conversionFactor * m_scale ) ); + setJournalling( journalling ); + } + else + { + m_tempoSyncDescription = tr( "Tempo Sync" ); + } + + if( m_tempoSyncMode != m_tempoLastSyncMode ) + { + switch( m_tempoSyncMode ) + { + case NO_SYNC: + m_tempoSyncIcon = embed::getIconPixmap( + "tempo_sync" ); + break; + case CUSTOM: + m_tempoSyncIcon = embed::getIconPixmap( + "dont_know" ); + break; + case DOUBLE_WHOLE_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_double_whole" ); + break; + case WHOLE_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_whole" ); + break; + case HALF_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_half" ); + break; + case QUARTER_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_quarter" ); + break; + case EIGHTH_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_eighth" ); + break; + case SIXTEENTH_NOTE: + m_tempoSyncIcon = embed::getIconPixmap( + "note_sixteenth" ); + break; + case THIRTYSECOND_NOTE: m_tempoSyncIcon = embed::getIconPixmap( "note_thirtysecond" ); - conversionFactor = 8.0; break; default: printf( "tempoSyncKnob::calculateTempoSyncTime" ": invalid tempoSyncMode" ); break; } - setValue( 60000.0 / ( _bpm * conversionFactor * m_scale ) ); - } - else - { - m_tempoSyncDescription = tr( "Tempo Sync" ); - m_tempoSyncIcon = embed::getIconPixmap( "tempo_sync" ); - } - - if( m_tempoSyncMode != m_tempoLastSyncMode ) - { + emit syncModeChanged( m_tempoSyncMode ); emit syncDescriptionChanged( m_tempoSyncDescription ); emit syncIconChanged(); + + m_tempoLastSyncMode = m_tempoSyncMode; } - - m_tempoLastSyncMode = m_tempoSyncMode; } diff --git a/src/widgets/volume_knob.cpp b/src/widgets/volume_knob.cpp index 57ed6511a..5ffcd6dc0 100644 --- a/src/widgets/volume_knob.cpp +++ b/src/widgets/volume_knob.cpp @@ -70,8 +70,7 @@ void volumeKnob::mousePressEvent( QMouseEvent * _me ) if( _me->button() == Qt::LeftButton && eng()->getMainWindow()->isCtrlPressed() == FALSE ) { - setJournalling( FALSE ); - m_oldValue = value(); + prepareJournalEntryFromOldVal(); const QPoint & p = _me->pos(); m_origMousePos = p;