diff --git a/src/audio/audio_jack.cpp b/src/audio/audio_jack.cpp index 325e24093f..55708eec45 100644 --- a/src/audio/audio_jack.cpp +++ b/src/audio/audio_jack.cpp @@ -66,7 +66,6 @@ audioJACK::audioJACK( const sample_rate_t _sample_rate, bool & _success_ful, _mixer ), m_client( NULL ), m_active( FALSE ), -// m_processCallbackMutex(), m_stop_semaphore( 1 ), m_outBuf( new surroundSampleFrame[getMixer()->framesPerAudioBuffer()] ), m_framesDoneInCurBuf( 0 ), @@ -286,7 +285,6 @@ void audioJACK::registerPort( audioPort * _port ) const QString name[2] = { _port->name() + " L", _port->name() + " R" } ; - m_processCallbackMutex.lock(); for( Uint8 ch = 0; ch < DEFAULT_CHANNELS; ++ch ) { m_portMap[_port].ports[ch] = jack_port_register( m_client, @@ -298,8 +296,7 @@ void audioJACK::registerPort( audioPort * _port ) #endif JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); - } - m_processCallbackMutex.unlock();*/ + }*/ } @@ -310,7 +307,6 @@ void audioJACK::unregisterPort( audioPort * _port ) return; /* if( m_portMap.contains( _port ) ) { - m_processCallbackMutex.lock(); for( Uint8 ch = 0; ch < DEFAULT_CHANNELS; ++ch ) { if( m_portMap[_port].ports[ch] != NULL ) @@ -320,7 +316,6 @@ void audioJACK::unregisterPort( audioPort * _port ) } } m_portMap.erase( m_portMap.find( _port ) ); - m_processCallbackMutex.unlock(); }*/ } @@ -354,7 +349,6 @@ void audioJACK::renamePort( audioPort * _port ) int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata ) { audioJACK * _this = static_cast( _udata ); -// _this->m_processCallbackMutex.lock(); /* printf( "%f\n", jack_cpu_load( _this->m_client ) );*/ @@ -444,8 +438,6 @@ int audioJACK::processCallback( jack_nframes_t _nframes, void * _udata ) } } -// _this->m_processCallbackMutex.unlock(); - return( 0 ); } diff --git a/src/audio/audio_port.cpp b/src/audio/audio_port.cpp index fe9b484df7..4906921ba9 100644 --- a/src/audio/audio_port.cpp +++ b/src/audio/audio_port.cpp @@ -64,6 +64,7 @@ audioPort::~audioPort() } delete[] m_firstBuffer; delete[] m_secondBuffer; + delete m_effects; } diff --git a/src/core/arp_and_chords_tab_widget.cpp b/src/core/arp_and_chords_tab_widget.cpp index 94aaee54b9..4290217f79 100644 --- a/src/core/arp_and_chords_tab_widget.cpp +++ b/src/core/arp_and_chords_tab_widget.cpp @@ -42,25 +42,21 @@ #endif -/*#ifdef HAVE_STDLIB_H*/ -#include -/*#endif*/ - - #include "arp_and_chords_tab_widget.h" +#include "combobox.h" #include "embed.h" +#include "engine.h" +#include "group_box.h" +#include "gui_templates.h" +#include "instrument_track.h" +#include "knob.h" +#include "led_checkbox.h" #include "note_play_handle.h" #include "song_editor.h" -#include "group_box.h" #include "pixmap_button.h" -#include "knob.h" -#include "tooltip.h" -#include "gui_templates.h" -#include "tempo_sync_knob.h" -#include "instrument_track.h" -#include "led_checkbox.h" #include "preset_preview_play_handle.h" -#include "combobox.h" +#include "tempo_sync_knob.h" +#include "tooltip.h" @@ -469,21 +465,12 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n ) _n->getVolume(), _n->getPanning(), _n->detuning() ); - // duplicate note-play-handle, only note is + // create sub-note-play-handle, only note is // different - notePlayHandle * note_play_handle = - new notePlayHandle( - _n->getInstrumentTrack(), - _n->framesAhead(), - _n->frames(), note_copy ); - note_play_handle->setBBTrackFrom( _n ); -#if SINGERBOT_SUPPORT - note_play_handle->setPatternIndex( - _n->patternIndex() ); -#endif - // add sub-note to base-note, now all stuff is - // done by notePlayHandle::play_note() - _n->addSubNote( note_play_handle ); + new notePlayHandle( _n->getInstrumentTrack(), + _n->framesAhead(), + _n->frames(), note_copy, + _n ); } } } @@ -631,26 +618,16 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n ) vol_level ), _n->getPanning(), _n->detuning() ); - // duplicate note-play-handle, only ptr to note is different + // create sub-note-play-handle, only ptr to note is different // and is_arp_note=TRUE - notePlayHandle * note_play_handle = new notePlayHandle( - _n->getInstrumentTrack(), - ( ( m_arpModeComboBox->value() != - FREE ) ? + new notePlayHandle( _n->getInstrumentTrack(), + ( ( m_arpModeComboBox->value() != FREE ) ? cnphv.first()->framesAhead() : _n->framesAhead() ) + frames_processed, gated_frames, new_note, - TRUE ); - note_play_handle->setBBTrackFrom( _n ); -#if SINGERBOT_SUPPORT - note_play_handle->setPatternIndex( _n->patternIndex() ); -#endif - - // add sub-note to base-note - now all stuff is done by - // notePlayHandle::playNote() - _n->addSubNote( note_play_handle ); + _n, TRUE ); // update counters frames_processed += arp_frames; @@ -698,21 +675,9 @@ void arpAndChordsTabWidget::loadSettings( const QDomElement & _this ) m_arpRangeKnob->loadSettings( _this, "arprange" ); m_arpTimeKnob->loadSettings( _this, "arptime" ); m_arpGateKnob->loadSettings( _this, "arpgate" ); - if( _this.hasAttribute( "arpdir" ) ) - { - m_arpDirectionBtnGrp->setInitValue( - _this.attribute( "arpdir" ).toInt() - 1 ); - m_arpGroupBox->setState( - _this.attribute( "arpdir" ).toInt() != OFF && - !_this.attribute( "arpdisabled" ).toInt() ); - } - else - { - m_arpDirectionBtnGrp->loadSettings( _this, "arpdir" ); - m_arpGroupBox->setState( - !_this.attribute( "arpdisabled" ).toInt() ); - } - + m_arpDirectionBtnGrp->loadSettings( _this, "arpdir" ); + m_arpGroupBox->setState( !_this.attribute( "arpdisabled" ).toInt() ); + // Keep compatibility with version 2.1 file format if( _this.hasAttribute( "arpsyncmode" ) ) { diff --git a/src/core/automation_editor.cpp b/src/core/automation_editor.cpp index 35ecd3e8b3..2b7a6fda3f 100644 --- a/src/core/automation_editor.cpp +++ b/src/core/automation_editor.cpp @@ -89,7 +89,6 @@ QPixmap * automationEditor::s_toolMove = NULL; automationEditor::automationEditor( void ) : QWidget( engine::getMainWindow()->workspace() ), - m_paintPixmap(), m_pattern( NULL ), m_min_level( 0 ), m_max_level( 0 ), @@ -502,14 +501,10 @@ inline void automationEditor::drawValueRect( QPainter & _p, -void automationEditor::updatePaintPixmap( void ) +void automationEditor::updatePaintPixmap( QPixmap & _p ) { - if( m_paintPixmap.isNull() == TRUE || m_paintPixmap.size() != size() ) - { - m_paintPixmap = QPixmap( size() ); - } - m_paintPixmap.fill( QColor( 0, 0, 0 ) ); - QPainter p( &m_paintPixmap ); + _p.fill( QColor( 0, 0, 0 ) ); + QPainter p( &_p ); // set font-size to 8 p.setFont( pointSize<8>( p.font() ) ); @@ -1562,9 +1557,30 @@ void automationEditor::mouseMoveEvent( QMouseEvent * _me ) +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 ); +} + + + + void automationEditor::paintEvent( QPaintEvent * ) { - updatePaintPixmap(); + QPixmap paintPixmap( size() ); + updatePaintPixmap( paintPixmap ); #ifdef QT4 QPainter p( this ); #else @@ -1573,7 +1589,7 @@ void automationEditor::paintEvent( QPaintEvent * ) QPainter p( &draw_pm, this ); #endif - p.drawPixmap( 0, 0, m_paintPixmap ); + p.drawPixmap( 0, 0, paintPixmap ); p.setClipRect( VALUES_WIDTH, TOP_MARGIN, width() - VALUES_WIDTH, height() - TOP_MARGIN - SCROLLBAR_SIZE ); @@ -1604,26 +1620,6 @@ 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 * ) { @@ -1737,6 +1733,15 @@ int automationEditor::getLevel( int _y ) +inline bool automationEditor::inBBEditor( void ) +{ + return( m_pattern->getTrack()->getTrackContainer() + == engine::getBBEditor() ); +} + + + + void automationEditor::play( void ) { if( validPattern() == FALSE ) @@ -2226,15 +2231,6 @@ void automationEditor::updateTopBottomLevels( void ) -inline bool automationEditor::inBBEditor( void ) -{ - return( m_pattern->getTrack()->getTrackContainer() - == engine::getBBEditor() ); -} - - - - void automationEditor::update( void ) { QWidget::update(); diff --git a/src/core/automation_pattern.cpp b/src/core/automation_pattern.cpp new file mode 100644 index 0000000000..f2761fd68e --- /dev/null +++ b/src/core/automation_pattern.cpp @@ -0,0 +1,302 @@ +#ifndef SINGLE_SOURCE_COMPILE + +/* + * automation_pattern.cpp - implementation of class automationPattern which + * holds dynamic values + * + * Copyright (c) 2006-2007 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. + * + */ + + +#include "qt3support.h" + +#ifdef QT4 + +#include + +#else + +#include +#define value data + +#endif + + +#include "automation_pattern.h" +#include "automation_editor.h" +#include "engine.h" +#include "level_object.h" +#include "note.h" +#include "templates.h" +#include "track.h" + + + + +automationPattern::automationPattern( track * _track, levelObject * _object ) : + m_track( _track ), + m_object( _object ), + m_update_first( TRUE ), + m_dynamic( FALSE ) +{ +} + + + + +automationPattern::automationPattern( const automationPattern & _pat_to_copy ) : + QObject(), + journallingObject(), + m_track( _pat_to_copy.m_track ), + m_object( _pat_to_copy.m_object ), + m_update_first( _pat_to_copy.m_update_first ), + m_dynamic( _pat_to_copy.m_dynamic ) +{ + for( timeMap::const_iterator it = _pat_to_copy.m_time_map.begin(); + it != _pat_to_copy.m_time_map.end(); ++it ) + { + m_time_map[it.key()] = it.value(); + } + + if( m_dynamic && m_track ) + { + m_track->addAutomationPattern( this ); + } +} + + + + +automationPattern::automationPattern( const automationPattern & _pat_to_copy, + levelObject * _object ) : + m_track( _pat_to_copy.m_track ), + m_object( _object ), + m_update_first( _pat_to_copy.m_update_first ), + m_dynamic( _pat_to_copy.m_dynamic ) +{ + for( timeMap::const_iterator it = _pat_to_copy.m_time_map.begin(); + it != _pat_to_copy.m_time_map.end(); ++it ) + { + m_time_map[it.key()] = it.value(); + } + + if( m_dynamic && m_track ) + { + m_track->addAutomationPattern( this ); + } +} + + + + +automationPattern::~automationPattern() +{ + if( m_dynamic && m_track ) + { + m_track->removeAutomationPattern( this ); + } + + if( engine::getAutomationEditor() + && engine::getAutomationEditor()->currentPattern() == this ) + { + engine::getAutomationEditor()->setCurrentPattern( NULL ); + } +} + + + + +//TODO: Improve this +midiTime automationPattern::length( void ) const +{ + Sint32 max_length = 0; + + for( timeMap::const_iterator it = m_time_map.begin(); + it != m_time_map.end(); + ++it ) + { + max_length = tMax( max_length, -it.key() ); + } + if( max_length % 64 == 0 ) + { + return( midiTime( tMax( max_length, 64 ) ) ); + } + return( midiTime( tMax( midiTime( max_length ).getTact() + 1, 1 ), + 0 ) ); +} + + + + +midiTime automationPattern::putValue( const midiTime & _time, const int _value, + const bool _quant_pos ) +{ + midiTime new_time = _quant_pos ? + note::quantized( _time, + engine::getAutomationEditor()->quantization() ) : + _time; + + m_time_map[-new_time] = _value; + + if( !m_dynamic && new_time != 0 ) + { + m_dynamic = TRUE; + if( m_track ) + { + m_track->addAutomationPattern( this ); + } + } + + return( new_time ); +} + + + + +void automationPattern::removeValue( const midiTime & _time ) +{ + if( _time != 0 ) + { + m_time_map.remove( -_time ); + + if( m_time_map.size() == 1 ) + { + m_dynamic = FALSE; + m_object->setLevel( m_time_map[0] ); + if( m_track ) + { + m_track->removeAutomationPattern( this ); + } + } + } +} + + + + +void automationPattern::clear( void ) +{ + m_time_map.clear(); + if( engine::getAutomationEditor()->currentPattern() == this ) + { + engine::getAutomationEditor()->update(); + } +} + + + + +int automationPattern::valueAt( const midiTime & _time ) +{ + return( m_time_map.lowerBound( -_time ).value() ); +} + + + + +void automationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + for( timeMap::iterator it = m_time_map.begin(); it != m_time_map.end(); + ++it ) + { + QDomElement element = _doc.createElement( "time" ); + element.setAttribute( "pos", -it.key() ); + element.setAttribute( "value", m_object->levelToLabel( + it.value() ) ); + _this.appendChild( element ); + } +} + + + + +void automationPattern::loadSettings( const QDomElement & _this ) +{ + clear(); + + for( QDomNode node = _this.firstChild(); !node.isNull(); + node = node.nextSibling() ) + { + QDomElement element = node.toElement(); + if( element.isNull() || element.tagName() != "time" ) + { + continue; + } + m_time_map[-element.attribute( "pos" ).toInt()] + = m_object->labelToLevel( + element.attribute( "value" ) ); + } + + if( !m_dynamic ) + { + m_dynamic = TRUE; + if( m_track ) + { + m_track->addAutomationPattern( this ); + } + } +} + + + + +void automationPattern::openInAutomationEditor( void ) +{ + engine::getAutomationEditor()->setCurrentPattern( this ); + engine::getAutomationEditor()->show(); + engine::getAutomationEditor()->setFocus(); +} + + + + +const QString automationPattern::name( void ) +{ + if( m_track ) + { + QString widget_name = dynamic_cast( m_object ) + ->accessibleName(); + return( m_track->name() + " - " + widget_name ); + } + else + { + return( m_object->displayName() ); + } +} + + + + +void automationPattern::processMidiTime( const midiTime & _time ) +{ + if( _time >= 0 ) + { + m_object->setLevel( m_time_map.lowerBound( -_time ).value() ); + } +} + + +#undef value + +#include "automation_pattern.moc" + + +#endif diff --git a/src/core/config_mgr.cpp b/src/core/config_mgr.cpp index 571a7c1df2..698cbd0cc2 100644 --- a/src/core/config_mgr.cpp +++ b/src/core/config_mgr.cpp @@ -661,7 +661,11 @@ void configManager::nextButtonClicked( void ) void configManager::switchPage( csize _pg ) { +#ifdef QT4 if( m_currentPage >= 0 && m_currentPage < m_pages.size() ) +#else + if( m_currentPage < m_pages.size() ) +#endif { m_pages[m_currentPage].first->hide(); #ifdef QT4 diff --git a/src/core/effect.cpp b/src/core/effect.cpp index 071198adfc..37b9ac3f90 100644 --- a/src/core/effect.cpp +++ b/src/core/effect.cpp @@ -77,10 +77,8 @@ bool FASTCALL effect::processAudioBuffer( surroundSampleFrame * _buf, void FASTCALL effect::setGate( float _level ) { - m_processLock.lock(); m_gate = _level * _level * m_processors * engine::getMixer()->framesPerAudioBuffer(); - m_processLock.unlock(); } diff --git a/src/core/effect_chain.cpp b/src/core/effect_chain.cpp index 693b13fb90..daead98556 100644 --- a/src/core/effect_chain.cpp +++ b/src/core/effect_chain.cpp @@ -26,6 +26,10 @@ #include "effect_chain.h" +#include "engine.h" + + + effectChain::effectChain( void ) : m_bypassed( TRUE ) @@ -35,15 +39,13 @@ effectChain::effectChain( void ) : -effectChain::~ effectChain() +effectChain::~effectChain() { - m_processLock.lock(); - for( Uint32 eff = 0; eff < m_effects.count(); eff++ ) + for( effect_list_t::size_type eff = 0; eff < m_effects.count(); eff++ ) { - free( m_effects[eff] ); + delete m_effects[eff]; } m_effects.clear(); - m_processLock.unlock(); } @@ -51,33 +53,18 @@ effectChain::~ effectChain() void FASTCALL effectChain::appendEffect( effect * _effect ) { - m_processLock.lock(); + engine::getMixer()->lock(); m_effects.append( _effect ); - m_processLock.unlock(); + engine::getMixer()->unlock(); } -void FASTCALL effectChain::deleteEffect( effect * _effect ) +void FASTCALL effectChain::removeEffect( effect * _effect ) { - m_processLock.lock(); - effect_list_t::iterator which = NULL; - for( effect_list_t::iterator it = m_effects.begin(); - it != m_effects.end(); it++ ) - { - if( (*it) == _effect ) - { - which = it; - break; - } - } - - if( which != NULL ) - { - m_effects.erase( which ); - } - - m_processLock.unlock(); + engine::getMixer()->lock(); + m_effects.erase( qFind( m_effects.begin(), m_effects.end(), _effect ) ); + engine::getMixer()->unlock(); } @@ -85,8 +72,6 @@ void FASTCALL effectChain::deleteEffect( effect * _effect ) void FASTCALL effectChain::moveDown( effect * _effect ) { - m_processLock.lock(); - if( _effect != m_effects.last() ) { int i = 0; @@ -103,8 +88,6 @@ void FASTCALL effectChain::moveDown( effect * _effect ) m_effects[i + 1] = _effect; m_effects[i] = temp; } - - m_processLock.unlock(); } @@ -112,8 +95,6 @@ void FASTCALL effectChain::moveDown( effect * _effect ) void FASTCALL effectChain::moveUp( effect * _effect ) { - m_processLock.lock(); - if( _effect != m_effects.first() ) { int i = 0; @@ -130,8 +111,6 @@ void FASTCALL effectChain::moveUp( effect * _effect ) m_effects[i - 1] = _effect; m_effects[i] = temp; } - - m_processLock.unlock(); } @@ -140,7 +119,7 @@ void FASTCALL effectChain::moveUp( effect * _effect ) bool FASTCALL effectChain::processAudioBuffer( surroundSampleFrame * _buf, const fpab_t _frames ) { - if( m_bypassed || ! m_processLock.tryLock() ) + if( m_bypassed ) { return( FALSE ); } @@ -150,7 +129,6 @@ bool FASTCALL effectChain::processAudioBuffer( surroundSampleFrame * _buf, { more_effects |= (*it)->processAudioBuffer( _buf, _frames ); } - m_processLock.unlock(); return( more_effects ); } diff --git a/src/core/effect_control_dialog.cpp b/src/core/effect_control_dialog.cpp index 8b784f4f46..910a97a8b0 100644 --- a/src/core/effect_control_dialog.cpp +++ b/src/core/effect_control_dialog.cpp @@ -40,6 +40,7 @@ #endif #include "effect_control_dialog.h" +#include "effect.h" effectControlDialog::effectControlDialog( QWidget * _parent, effect * _eff ) : diff --git a/src/core/effect_tab_widget.cpp b/src/core/effect_tab_widget.cpp index a6a4e13396..a9a1f9ab1d 100644 --- a/src/core/effect_tab_widget.cpp +++ b/src/core/effect_tab_widget.cpp @@ -52,6 +52,7 @@ #include "embed.h" #include "effect_select_dialog.h" #include "rack_plugin.h" +#include "rack_view.h" #include "audio_port.h" diff --git a/src/core/engine.cpp b/src/core/engine.cpp index 2d8a344939..ffd730a353 100644 --- a/src/core/engine.cpp +++ b/src/core/engine.cpp @@ -104,6 +104,10 @@ void engine::destroy( void ) delete s_automationEditor; s_automationEditor = NULL; +#ifdef LADSPA_SUPPORT + delete s_ladspaManager; +#endif + presetPreviewPlayHandle::cleanUp(); // now we can clean up all allocated buffer diff --git a/src/core/envelope_and_lfo_widget.cpp b/src/core/envelope_and_lfo_widget.cpp index ecb14a41f9..5732af03a4 100644 --- a/src/core/envelope_and_lfo_widget.cpp +++ b/src/core/envelope_and_lfo_widget.cpp @@ -121,14 +121,7 @@ envelopeAndLFOWidget::envelopeAndLFOWidget( float _value_for_zero_amount, m_lfoFrame( 0 ), m_lfoAmountIsZero( FALSE ), m_lfoShapeData( NULL ), - m_lfoShape( SIN ), - m_busyMutex( -#ifdef QT3 - TRUE -#else - QMutex::Recursive -#endif - ) + m_lfoShape( SIN ) { if( s_envGraph == NULL ) { @@ -511,15 +504,44 @@ envelopeAndLFOWidget::~envelopeAndLFOWidget() +inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpab_t _frame_offset ) +{ + f_cnt_t frame = ( m_lfoFrame + _frame_offset ) % m_lfoOscillationFrames; + const float phase = frame / static_cast( + m_lfoOscillationFrames ); + sample_t shape_sample; + switch( m_lfoShape ) + { + case TRIANGLE: + shape_sample = oscillator::triangleSample( phase ); + break; + case SQUARE: + shape_sample = oscillator::squareSample( phase ); + break; + case SAW: + shape_sample = oscillator::sawSample( phase ); + break; + case USER: + shape_sample = m_userWave.userWaveSample( phase ); + break; + case SIN: + default: + shape_sample = oscillator::sinSample( phase ); + break; + } + return( shape_sample * m_lfoAmount ); +} + + + + void envelopeAndLFOWidget::updateLFOShapeData( void ) { const fpab_t frames = engine::getMixer()->framesPerAudioBuffer(); - m_userWave.lock(); for( fpab_t offset = 0; offset < frames; ++offset ) { m_lfoShapeData[offset] = lfoShapeSample( offset ); } - m_userWave.unlock(); m_bad_lfoShapeData = FALSE; } @@ -655,8 +677,6 @@ void envelopeAndLFOWidget::saveSettings( QDomDocument & _doc, void envelopeAndLFOWidget::loadSettings( const QDomElement & _this ) { - m_busyMutex.lock(); - m_predelayKnob->loadSettings( _this, "pdel" ); m_attackKnob->loadSettings( _this, "att" ); m_holdKnob->loadSettings( _this, "hold" ); @@ -682,8 +702,6 @@ void envelopeAndLFOWidget::loadSettings( const QDomElement & _this ) m_userWave.setAudioFile( _this.attribute( "userwavefile" ) ); - m_busyMutex.unlock(); - updateSampleVars(); } @@ -939,10 +957,11 @@ void envelopeAndLFOWidget::paintEvent( QPaintEvent * ) void envelopeAndLFOWidget::updateSampleVars( void ) { - m_busyMutex.lock(); + engine::getMixer()->lock(); const float frames_per_env_seg = SECS_PER_ENV_SEGMENT * engine::getMixer()->sampleRate(); + // TODO: Remove the expKnobVals, time should be linear const f_cnt_t predelay_frames = static_cast( frames_per_env_seg * expKnobVal( m_predelayKnob->value() ) ); @@ -979,46 +998,43 @@ void envelopeAndLFOWidget::updateSampleVars( void ) m_rFrames = 0; } - sample_t * new_pahd_env = new sample_t[m_pahdFrames]; - sample_t * new_r_env = new sample_t[m_rFrames]; + delete[] m_pahdEnv; + delete[] m_rEnv; + + m_pahdEnv = new sample_t[m_pahdFrames]; + m_rEnv = new sample_t[m_rFrames]; for( f_cnt_t i = 0; i < predelay_frames; ++i ) { - new_pahd_env[i] = m_amountAdd; + m_pahdEnv[i] = m_amountAdd; } f_cnt_t add = predelay_frames; for( f_cnt_t i = 0; i < attack_frames; ++i ) { - new_pahd_env[add+i] = ( (float)i / attack_frames ) * + m_pahdEnv[add + i] = ( (float)i / attack_frames ) * m_amount + m_amountAdd; } add += attack_frames; for( f_cnt_t i = 0; i < hold_frames; ++i ) { - new_pahd_env[add+i] = m_amount + m_amountAdd; + m_pahdEnv[add + i] = m_amount + m_amountAdd; } add += hold_frames; for( f_cnt_t i = 0; i < decay_frames; ++i ) { - new_pahd_env[add+i] = ( m_sustainLevel + ( 1.0f - + m_pahdEnv[add + i] = ( m_sustainLevel + ( 1.0f - (float)i / decay_frames ) * ( 1.0f - m_sustainLevel ) ) * m_amount + m_amountAdd; } - delete[] m_pahdEnv; - delete[] m_rEnv; - - m_pahdEnv = new_pahd_env; - m_rEnv = new_r_env; - for( f_cnt_t i = 0; i < m_rFrames; ++i ) { - new_r_env[i] = ( (float)( m_rFrames - i ) / m_rFrames + m_rEnv[i] = ( (float)( m_rFrames - i ) / m_rFrames // * m_sustainLevel ) * m_amount; } @@ -1058,40 +1074,9 @@ void envelopeAndLFOWidget::updateSampleVars( void ) m_bad_lfoShapeData = TRUE; - m_busyMutex.unlock(); - update(); -} - - - -inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpab_t _frame_offset ) -{ - f_cnt_t frame = ( m_lfoFrame + _frame_offset ) % m_lfoOscillationFrames; - const float phase = frame / static_cast( - m_lfoOscillationFrames ); - sample_t shape_sample; - switch( m_lfoShape ) - { - case TRIANGLE: - shape_sample = oscillator::triangleSample( phase ); - break; - case SQUARE: - shape_sample = oscillator::squareSample( phase ); - break; - case SAW: - shape_sample = oscillator::sawSample( phase ); - break; - case USER: - shape_sample = m_userWave.userWaveSample( phase ); - break; - case SIN: - default: - shape_sample = oscillator::sinSample( phase ); - break; - } - return( shape_sample * m_lfoAmount ); + engine::getMixer()->unlock(); } diff --git a/src/core/envelope_tab_widget.cpp b/src/core/envelope_tab_widget.cpp index 72051d1197..b60114519b 100644 --- a/src/core/envelope_tab_widget.cpp +++ b/src/core/envelope_tab_widget.cpp @@ -41,16 +41,17 @@ #include "envelope_tab_widget.h" -#include "envelope_and_lfo_widget.h" -#include "note_play_handle.h" -#include "knob.h" -#include "pixmap_button.h" -#include "group_box.h" -#include "tab_widget.h" +#include "combobox.h" #include "embed.h" +#include "engine.h" +#include "envelope_and_lfo_widget.h" +#include "group_box.h" #include "gui_templates.h" #include "instrument_track.h" -#include "combobox.h" +#include "knob.h" +#include "note_play_handle.h" +#include "pixmap_button.h" +#include "tab_widget.h" @@ -238,10 +239,8 @@ float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n, } float volume_level; - m_envLFOWidgets[VOLUME]->lock(); m_envLFOWidgets[VOLUME]->fillLevel( &volume_level, _frame, release_begin, 1 ); - m_envLFOWidgets[VOLUME]->unlock(); return( volume_level ); } @@ -285,9 +284,6 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, float * cut_buf = NULL; float * res_buf = NULL; - m_envLFOWidgets[CUT]->lock(); - m_envLFOWidgets[RES]->lock(); - if( m_envLFOWidgets[CUT]->used() ) { cut_buf = new float[_frames]; @@ -377,14 +373,10 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } } - m_envLFOWidgets[RES]->unlock(); - m_envLFOWidgets[CUT]->unlock(); - delete[] cut_buf; delete[] res_buf; } - m_envLFOWidgets[VOLUME]->lock(); if( m_envLFOWidgets[VOLUME]->used() ) { float * vol_buf = new float[_frames]; @@ -403,7 +395,6 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab, } delete[] vol_buf; } - m_envLFOWidgets[VOLUME]->unlock(); /* else if( m_envLFOWidgets[VOLUME]->used() == FALSE && m_envLFOWidgets[PANNING]->used() ) { diff --git a/src/core/file_browser.cpp b/src/core/file_browser.cpp index cf3bbc89c0..5c1b46752a 100644 --- a/src/core/file_browser.cpp +++ b/src/core/file_browser.cpp @@ -48,20 +48,21 @@ #include "file_browser.h" -#include "song_editor.h" #include "bb_editor.h" +#include "config_mgr.h" +#include "debug.h" #include "embed.h" +#include "engine.h" +#include "gui_templates.h" +#include "instrument.h" #include "instrument_track.h" +#include "main_window.h" #include "mmp.h" #include "preset_preview_play_handle.h" #include "sample_play_handle.h" -#include "debug.h" -#include "gui_templates.h" -#include "instrument.h" -#include "text_float.h" +#include "song_editor.h" #include "string_pair_drag.h" -#include "main_window.h" -#include "config_mgr.h" +#include "text_float.h" @@ -297,67 +298,67 @@ void fileBrowser::contextMenuRequest( QListViewItem * i, const QPoint &, int ) void fileBrowser::sendToActiveInstrumentTrack( void ) { - if( engine::getMainWindow()->workspace() != NULL ) + if( engine::getMainWindow()->workspace() == NULL ) { - // get all windows opened in the workspace - QWidgetList pl = - engine::getMainWindow()->workspace()->windowList( + return; + } + + // get all windows opened in the workspace + QWidgetList pl = engine::getMainWindow()->workspace()->windowList( #if QT_VERSION >= 0x030200 QWorkspace::StackingOrder #endif ); #ifdef QT4 - QListIterator w( pl ); - w.toBack(); - // now we travel through the window-list until we find an - // instrument-track - while( w.hasPrevious() ) - { - instrumentTrack * ct = dynamic_cast( + QListIterator w( pl ); + w.toBack(); + // now we travel through the window-list until we find an + // instrument-track + while( w.hasPrevious() ) + { + instrumentTrack * ct = dynamic_cast( w.previous() ); #else - QWidget * w = pl.last(); - // now we travel through the window-list until we find an - // instrument-track - while( w != NULL ) - { - instrumentTrack * ct = - dynamic_cast( w ); + QWidget * w = pl.last(); + // now we travel through the window-list until we find an + // instrument-track + while( w != NULL ) + { + instrumentTrack * ct = dynamic_cast( w ); #endif - if( ct != NULL && ct->isHidden() == FALSE ) + if( ct != NULL && ct->isHidden() == FALSE ) + { + // ok, it's an instrument-track, so we can apply the + // sample or the preset + engine::getMixer()->lock(); + if( m_contextMenuItem->type() == fileItem::SAMPLE_FILE ) { - // ok, it's an instrument-track, so we can apply - // the sample or the preset - if( m_contextMenuItem->type() == - fileItem::SAMPLE_FILE ) - { - instrument * afp = ct->loadInstrument( + instrument * afp = ct->loadInstrument( engine::sampleExtensions() [m_contextMenuItem ->extension()] ); - if( afp != NULL ) - { - afp->setParameter( "samplefile", - m_contextMenuItem->fullName() ); - } - } - else if( m_contextMenuItem->type() == - fileItem::PRESET_FILE ) + if( afp != NULL ) { - multimediaProject mmp( + afp->setParameter( "samplefile", m_contextMenuItem->fullName() ); - ct->loadTrackSpecificSettings( - mmp.content(). + } + } + else if( m_contextMenuItem->type() == + fileItem::PRESET_FILE ) + { + multimediaProject mmp( + m_contextMenuItem->fullName() ); + ct->loadTrackSpecificSettings( mmp.content(). firstChild(). toElement() ); - } - ct->toggledInstrumentTrackButton( TRUE ); - break; } -#ifndef QT4 - w = pl.prev(); -#endif + ct->toggledInstrumentTrackButton( TRUE ); + engine::getMixer()->unlock(); + break; } +#ifndef QT4 + w = pl.prev(); +#endif } } @@ -366,6 +367,7 @@ void fileBrowser::sendToActiveInstrumentTrack( void ) void fileBrowser::openInNewInstrumentTrack( trackContainer * _tc ) { + engine::getMixer()->lock(); if( m_contextMenuItem->type() == fileItem::SAMPLE_FILE ) { instrumentTrack * ct = dynamic_cast( @@ -397,6 +399,7 @@ void fileBrowser::openInNewInstrumentTrack( trackContainer * _tc ) ct->toggledInstrumentTrackButton( TRUE ); } } + engine::getMixer()->unlock(); } @@ -451,50 +454,53 @@ void listView::contentsMouseDoubleClickEvent( QMouseEvent * _me ) Q3ListView::contentsMouseDoubleClickEvent( _me ); fileItem * f = dynamic_cast( itemAt( contentsToViewport( _me->pos() ) ) ); - if( f != NULL ) + if( f == NULL ) { - if( f->type() == fileItem::SAMPLE_FILE ) - { - // samples are per default opened in bb-editor because - // they're likely drum-samples etc. - instrumentTrack * it = dynamic_cast( + return; + } + + if( f->type() == fileItem::SAMPLE_FILE ) + { + // samples are per default opened in bb-editor because they're + // likely drum-samples etc. + engine::getMixer()->lock(); + instrumentTrack * it = dynamic_cast( track::create( track::INSTRUMENT_TRACK, engine::getBBEditor() ) ); #ifdef LMMS_DEBUG - assert( it != NULL ); + assert( it != NULL ); #endif - instrument * afp = it->loadInstrument( + instrument * afp = it->loadInstrument( engine::sampleExtensions()[f->extension()] ); - if( afp != NULL ) - { - afp->setParameter( "samplefile", - f->fullName() ); - } - it->toggledInstrumentTrackButton( TRUE ); - } - else if( f->type() == fileItem::PRESET_FILE ) + if( afp != NULL ) { - // presets are per default opened in bb-editor - multimediaProject mmp( f->fullName() ); - track * t = track::create( track::INSTRUMENT_TRACK, - engine::getBBEditor() ); - instrumentTrack * it = dynamic_cast( - t ); - if( it != NULL ) - { - it->loadTrackSpecificSettings( mmp.content(). + afp->setParameter( "samplefile", f->fullName() ); + } + it->toggledInstrumentTrackButton( TRUE ); + engine::getMixer()->unlock(); + } + else if( f->type() == fileItem::PRESET_FILE ) + { + // presets are per default opened in bb-editor + multimediaProject mmp( f->fullName() ); + engine::getMixer()->lock(); + instrumentTrack * it = dynamic_cast( + track::create( track::INSTRUMENT_TRACK, + engine::getBBEditor() ) ); + if( it != NULL ) + { + it->loadTrackSpecificSettings( mmp.content(). firstChild(). toElement() ); - it->toggledInstrumentTrackButton( TRUE ); - } + it->toggledInstrumentTrackButton( TRUE ); } - else if( f->type() == fileItem::PROJECT_FILE ) + engine::getMixer()->unlock(); + } + else if( f->type() == fileItem::PROJECT_FILE ) + { + if( engine::getSongEditor()->mayChangeProject() ) { - if( engine::getSongEditor()->mayChangeProject() ) - { - engine::getSongEditor()->loadProject( - f->fullName() ); - } + engine::getSongEditor()->loadProject( f->fullName() ); } } } diff --git a/src/core/instrument.cpp b/src/core/instrument.cpp index 82585744cb..44b665ae94 100644 --- a/src/core/instrument.cpp +++ b/src/core/instrument.cpp @@ -34,8 +34,7 @@ instrument::instrument( instrumentTrack * _instrument_track, const descriptor * _descriptor ) : QWidget( _instrument_track->tabWidgetParent() ), plugin( _descriptor ), - m_instrumentTrack( _instrument_track ), - m_valid( TRUE ) + m_instrumentTrack( _instrument_track ) { setFixedSize( 250, 250 ); m_instrumentTrack->setWindowIcon( *getDescriptor()->logo ); @@ -46,7 +45,6 @@ instrument::instrument( instrumentTrack * _instrument_track, instrument::~instrument() { - invalidate(); } @@ -98,4 +96,14 @@ instrument * instrument::instantiate( const QString & _plugin_name, } + + +bool instrument::isFromTrack( const track * _track ) const +{ + return( m_instrumentTrack == _track ); +} + + + + #endif diff --git a/src/core/midi_tab_widget.cpp b/src/core/midi_tab_widget.cpp index 1e9f9446be..1e87149dbf 100644 --- a/src/core/midi_tab_widget.cpp +++ b/src/core/midi_tab_widget.cpp @@ -48,15 +48,17 @@ #include "midi_tab_widget.h" +#include "embed.h" +#include "engine.h" +#include "gui_templates.h" #include "instrument_track.h" +#include "midi_client.h" #include "midi_port.h" -#include "tab_widget.h" #include "led_checkbox.h" #include "lcd_spinbox.h" -#include "tooltip.h" #include "song_editor.h" -#include "midi_client.h" -#include "embed.h" +#include "tab_widget.h" +#include "tooltip.h" @@ -81,6 +83,7 @@ midiTabWidget::midiTabWidget( instrumentTrack * _instrument_track, m_inputChannelSpinBox->setValue( m_midiPort->inputChannel() + 1 ); m_inputChannelSpinBox->setLabel( tr( "CHANNEL" ) ); m_inputChannelSpinBox->move( 28, 52 ); + m_inputChannelSpinBox->setEnabled( FALSE ); connect( m_inputChannelSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( inputChannelChanged( int ) ) ); inputChannelChanged( m_inputChannelSpinBox->value() ); @@ -93,6 +96,7 @@ midiTabWidget::midiTabWidget( instrumentTrack * _instrument_track, //m_outputChannelSpinBox->addTextForValue( 0, "---" ); m_outputChannelSpinBox->setLabel( tr( "CHANNEL" ) ); m_outputChannelSpinBox->move( 28, 132 ); + m_outputChannelSpinBox->setEnabled( FALSE ); connect( m_outputChannelSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( outputChannelChanged( int ) ) ); outputChannelChanged( m_outputChannelSpinBox->value() ); diff --git a/src/core/mixer.cpp b/src/core/mixer.cpp index 8fe921353a..2e2ef7e1b5 100644 --- a/src/core/mixer.cpp +++ b/src/core/mixer.cpp @@ -71,8 +71,11 @@ mixer::mixer( void ) : m_masterGain( 1.0f ), m_audioDev( NULL ), m_oldAudioDev( NULL ), - m_mixMutex(), - m_mixMutexLockLevel( 0 ) +#ifndef QT3 + m_mixMutex( QMutex::Recursive ) +#else + m_mixMutex( TRUE ) +#endif { if( configManager::inst()->value( "mixer", "framesperaudiobuffer" ).toInt() >= 32 ) @@ -250,23 +253,19 @@ const surroundSampleFrame * mixer::renderNextBuffer( void ) // remove all play-handles that have to be deleted and delete // them if they still exist... // maybe this algorithm could be optimized... - while( !m_playHandlesToRemove.empty() ) + constPlayHandleVector::iterator it_rem = m_playHandlesToRemove.begin(); + while( it_rem != m_playHandlesToRemove.end() ) { - playHandleVector::iterator it = m_playHandles.begin(); + playHandleVector::iterator it = qFind( m_playHandles.begin(), + m_playHandles.end(), *it_rem ); - while( it != m_playHandles.end() ) + if( it != m_playHandles.end() ) { - if( *it == m_playHandlesToRemove.front() ) - { - delete *it; - m_playHandles.erase( it ); - //delete m_playHandlesToRemove.front(); - break; - } - ++it; + delete *it; + m_playHandles.erase( it ); } - m_playHandlesToRemove.erase( m_playHandlesToRemove.begin() ); + m_playHandlesToRemove.erase( it_rem ); } // now swap the buffers... current buffer becomes next (last) @@ -395,18 +394,15 @@ const surroundSampleFrame * mixer::renderNextBuffer( void ) // removes all play-handles. this is neccessary, when the song is stopped -> // all remaining notes etc. would be played until their end -void mixer::clear( bool _everything ) +void mixer::clear( void ) { // TODO: m_midiClient->noteOffAll(); for( playHandleVector::iterator it = m_playHandles.begin(); it != m_playHandles.end(); ++it ) { // we must not delete instrument-play-handles as they exist - // during the whole lifetime of an instrument - exception if - // parameter _everything is true (which is the case when - // clearing song for example) - if( _everything == TRUE || - ( *it )->type() != playHandle::InstrumentPlayHandle ) + // during the whole lifetime of an instrument + if( ( *it )->type() != playHandle::InstrumentPlayHandle ) { m_playHandlesToRemove.push_back( *it ); } @@ -556,13 +552,20 @@ void mixer::restoreAudioDevice( void ) -void mixer::checkValidityOfPlayHandles( void ) +void mixer::removePlayHandles( track * _track ) { playHandleVector::iterator it = m_playHandles.begin(); while( it != m_playHandles.end() ) { - ( *it )->checkValidity(); - ++it; + if( ( *it )->isFromTrack( _track ) ) + { + delete *it; + m_playHandles.erase( it ); + } + else + { + ++it; + } } } diff --git a/src/core/note.cpp b/src/core/note.cpp index 4b749cc6cd..2a2c4f4302 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -41,7 +41,7 @@ #include "note.h" #include "automatable_object_templates.h" -#include "knob.h" +#include "detuning_helper.h" #include "templates.h" @@ -52,7 +52,7 @@ const float note::MAX_DETUNING = 4 * 12.0f; note::note( const midiTime & _length, const midiTime & _pos, tones _tone, octaves _octave, volume _volume, - panning _panning, knob * _detuning ) : + panning _panning, detuningHelper * _detuning ) : m_tone( C ), m_octave( DEFAULT_OCTAVE ), m_volume( DEFAULT_VOLUME ), @@ -70,7 +70,7 @@ note::note( const midiTime & _length, const midiTime & _pos, if( _detuning ) { - setDetuning( _detuning ); + m_detuning = sharedObject::ref( _detuning ); } else { @@ -91,7 +91,7 @@ note::note( const note & _note ) : m_length( _note.m_length ), m_pos( _note.m_pos ) { - setDetuning( _note.m_detuning ); + m_detuning = sharedObject::ref( _note.m_detuning ); } @@ -99,18 +99,7 @@ note::note( const note & _note ) : note::~note() { - if( m_detuning ) - { - knob::autoObj * o = dynamic_cast( m_detuning ); - if( o->data().toInt() ) - { - o->setData( o->data().toInt() - 1 ); - } - else - { - delete m_detuning; - } - } + sharedObject::unref( m_detuning ); } @@ -229,7 +218,7 @@ void note::saveSettings( QDomDocument & _doc, QDomElement & _this ) _this.setAttribute( "pan", m_panning ); _this.setAttribute( "len", m_length ); _this.setAttribute( "pos", m_pos ); - if( m_length > 0 && m_detuning ) + if( m_length > 0 ) { m_detuning->saveSettings( _doc, _this, "detuning" ); } @@ -300,26 +289,10 @@ void note::editDetuningPattern( void ) -void note::setDetuning( knob * _detuning ) -{ - m_detuning = _detuning; - if( m_detuning ) - { - knob::autoObj * o = dynamic_cast( m_detuning ); - o->setData( o->data().toInt() + 1 ); - } -} - - - - void note::createDetuning( void ) { - m_detuning = new knob( knobDark_28, NULL, - QObject::tr( "Note detuning" ), - NULL ); + m_detuning = new detuningHelper; m_detuning->initAutomationPattern(); - m_detuning->setData( 0 ); m_detuning->setRange( -MAX_DETUNING, MAX_DETUNING, 0.1f ); } @@ -328,17 +301,12 @@ void note::createDetuning( void ) void note::detachCurrentDetuning( void ) { - knob::autoObj * o = dynamic_cast( m_detuning ); - if( o->data().toInt() ) - { - o->setData( o->data().toInt() - 1 ); - - QDomDocument doc; - QDomElement parent = doc.createElement( "clone" ); - m_detuning->saveSettings( doc, parent ); - createDetuning(); - m_detuning->loadSettings( parent ); - } + QDomDocument doc; + QDomElement parent = doc.createElement( "clone" ); + m_detuning->saveSettings( doc, parent ); + sharedObject::unref( m_detuning ); + createDetuning(); + m_detuning->loadSettings( parent ); } @@ -346,10 +314,6 @@ void note::detachCurrentDetuning( void ) bool note::hasDetuningInfo( void ) { - if( m_detuning == NULL ) - { - return( FALSE ); - } automationPattern::timeMap map = m_detuning->getAutomationPattern()->getTimeMap(); return( map.size() > 1 || map[0] != 0 ); diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index 563d6cdb40..728b840559 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -28,20 +28,43 @@ #include "note_play_handle.h" #include "automatable_object_templates.h" -#include "instrument_track.h" +#include "config_mgr.h" +#include "detuning_helper.h" #include "envelope_tab_widget.h" -#include "midi.h" +#include "instrument_track.h" #include "midi_port.h" #include "song_editor.h" -#include "piano_widget.h" -#include "config_mgr.h" -#include "project_journal.h" + + +inline notePlayHandle::baseDetuning::baseDetuning( + detuningHelper * _detuning ) : + m_detuning( _detuning ) +{ + m_level = m_detuning->getAutomationPattern()->valueAt( 0 ); + m_value = m_detuning->value( m_level ); +} + + + + +inline void notePlayHandle::baseDetuning::setLevel( int _level ) +{ + m_level = _level; + m_value = m_detuning->value( m_level ); +} + + + + + + notePlayHandle::notePlayHandle( instrumentTrack * _it, const f_cnt_t _frames_ahead, const f_cnt_t _frames, const note & _n, + notePlayHandle * _parent, const bool _arp_note ) : playHandle( NotePlayHandle ), note( _n.length(), _n.pos(), _n.tone(), _n.octave(), @@ -56,7 +79,7 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it, m_releaseFramesToDo( 0 ), m_releaseFramesDone( 0 ), m_released( FALSE ), - m_baseNote( TRUE ), + m_baseNote( _parent == NULL ), m_arpNote( _arp_note ), m_muted( FALSE ), m_bbTrack( NULL ), @@ -65,23 +88,30 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it, #endif m_orig_bpm( engine::getSongEditor()->getTempo() ) { - if( detuning() ) + if( m_baseNote ) { - processMidiTime( pos() ); + m_base_detuning = new baseDetuning( detuning() ); m_instrumentTrack->m_processHandles.push_back( this ); - connect( detuning(), SIGNAL( valueChanged( float ) ), - this, SLOT( updateFrequency() ) ); } - connect( m_instrumentTrack, SIGNAL( baseNoteChanged() ), - this, SLOT( updateFrequency() ) ); + else + { + m_base_detuning = _parent->m_base_detuning; + + _parent->m_subNotes.push_back( this ); + // if there was an arp-note added and parent is a base-note + // we set arp-note-flag for indicating that parent is an + // arpeggio-base-note + _parent->m_arpNote = arpNote() && _parent->baseNote(); + + m_bbTrack = _parent->m_bbTrack; +#if SINGERBOT_SUPPORT + m_patternIndex = _parent->m_patternIndex; +#endif + } + updateFrequency(); setFrames( _frames ); - if( !configManager::inst()->value( "ui", - "manualchannelpiano" ).toInt() ) - { - m_instrumentTrack->m_pianoWidget->setKeyState( key(), TRUE ); - } // send MIDI-note-on-event m_instrumentTrack->processOutEvent( midiEvent( NOTE_ON, m_instrumentTrack->m_midiPort->outputChannel(), @@ -104,16 +134,15 @@ notePlayHandle::~notePlayHandle() noteOff( 0 ); } - if( m_instrumentTrack != NULL ) + if( m_baseNote ) { - if( detuning() ) - { - m_instrumentTrack->m_processHandles.removeAll( this ); - } - if( m_pluginData != NULL ) - { - m_instrumentTrack->deleteNotePluginData( this ); - } + delete m_base_detuning; + m_instrumentTrack->m_processHandles.removeAll( this ); + } + + if( m_pluginData != NULL ) + { + m_instrumentTrack->deleteNotePluginData( this ); } for( notePlayHandleVector::iterator it = m_subNotes.begin(); @@ -131,7 +160,7 @@ notePlayHandle::~notePlayHandle() void notePlayHandle::play( bool _try_parallelizing ) { - if( m_muted == TRUE || m_instrumentTrack == NULL ) + if( m_muted == TRUE ) { return; } @@ -232,30 +261,9 @@ void notePlayHandle::play( bool _try_parallelizing ) -void notePlayHandle::checkValidity( void ) +bool notePlayHandle::isFromTrack( const track * _track ) const { - if( m_instrumentTrack != NULL && - m_instrumentTrack->type() == track::NULL_TRACK ) - { - // track-type being track::NULL_TRACK indicates a track whose - // removal is in progress, so we have to invalidate ourself - if( m_released == FALSE ) - { - noteOff( 0 ); - } - if( m_pluginData ) - { - m_instrumentTrack->deleteNotePluginData( this ); - } - m_instrumentTrack = NULL; - } - // sub-notes might not be registered at mixer (for example arpeggio- - // notes), so they wouldn't invalidate them-selves - for( notePlayHandleVector::iterator it = m_subNotes.begin(); - it != m_subNotes.end(); ++it ) - { - ( *it )->checkValidity(); - } + return( m_instrumentTrack == _track || m_bbTrack == _track ); } @@ -272,27 +280,14 @@ void notePlayHandle::noteOff( const f_cnt_t _s ) // then set some variables indicating release-state m_framesBeforeRelease = _s; - if( m_instrumentTrack != NULL ) - { - m_releaseFramesToDo = tMax( 10, + m_releaseFramesToDo = tMax( 10, m_instrumentTrack->m_envWidget->releaseFrames() ); - if( !configManager::inst()->value( "ui", - "manualchannelpiano" ).toInt() ) - { - m_instrumentTrack->m_pianoWidget->setKeyState( key(), - FALSE ); - } - // send MIDI-note-off-event - m_instrumentTrack->processOutEvent( midiEvent( NOTE_OFF, + // send MIDI-note-off-event + m_instrumentTrack->processOutEvent( midiEvent( NOTE_OFF, m_instrumentTrack->m_midiPort->outputChannel(), key(), 0 ), midiTime::fromFrames( m_framesBeforeRelease, engine::framesPerTact64th() ) ); - } - else - { - m_releaseFramesToDo = 10; - } m_released = TRUE; } @@ -302,9 +297,8 @@ void notePlayHandle::noteOff( const f_cnt_t _s ) f_cnt_t notePlayHandle::actualReleaseFramesToDo( void ) const { - return( ( m_instrumentTrack != NULL ) ? - m_instrumentTrack->m_envWidget->releaseFrames( - arpBaseNote() ) : 0 ); + return( m_instrumentTrack->m_envWidget->releaseFrames( + arpBaseNote() ) ); } @@ -313,7 +307,7 @@ f_cnt_t notePlayHandle::actualReleaseFramesToDo( void ) const void notePlayHandle::setFrames( const f_cnt_t _frames ) { m_frames = _frames; - if( m_frames == 0 && m_instrumentTrack != NULL ) + if( m_frames == 0 ) { m_frames = m_instrumentTrack->beatLen( this ); } @@ -325,10 +319,7 @@ void notePlayHandle::setFrames( const f_cnt_t _frames ) float notePlayHandle::volumeLevel( const f_cnt_t _frame ) { - return( ( m_instrumentTrack != NULL ) ? - m_instrumentTrack->m_envWidget->volumeLevel( this, _frame ) - : - 0 ); + return( m_instrumentTrack->m_envWidget->volumeLevel( this, _frame ) ); } @@ -420,7 +411,17 @@ bool notePlayHandle::operator==( const notePlayHandle & _nph ) const void notePlayHandle::updateFrequency( void ) { - m_frequency = m_instrumentTrack->frequency( this ); + float pitch = (float)( tone() - m_instrumentTrack->baseTone() + + engine::getSongEditor()->masterPitch() ) / 12.0f + + (float)( octave() - m_instrumentTrack->baseOctave() ) + + m_base_detuning->value() / 12.0f; + m_frequency = BASE_FREQ * powf( 2.0f, pitch ); + + for( notePlayHandleVector::iterator it = m_subNotes.begin(); + it != m_subNotes.end(); ++it ) + { + ( *it )->updateFrequency(); + } } @@ -428,7 +429,16 @@ void notePlayHandle::updateFrequency( void ) void notePlayHandle::processMidiTime( const midiTime & _time ) { - detuning()->getAutomationPattern()->processMidiTime( _time - pos() ); + if( _time >= pos() ) + { + int level = detuning()->getAutomationPattern()->valueAt( _time - + pos() ); + if( level != m_base_detuning->level() ) + { + m_base_detuning->setLevel( level ); + updateFrequency(); + } + } } @@ -451,7 +461,4 @@ void notePlayHandle::resize( const bpm_t _new_bpm ) -#include "note_play_handle.moc" - - #endif diff --git a/src/core/piano_roll.cpp b/src/core/piano_roll.cpp index 48f435cf0c..62a49cacaa 100644 --- a/src/core/piano_roll.cpp +++ b/src/core/piano_roll.cpp @@ -63,22 +63,23 @@ #include "piano_roll.h" #include "automatable_object_templates.h" -#include "song_editor.h" -#include "main_window.h" -#include "pattern.h" -#include "embed.h" -#include "pixmap_button.h" -#include "templates.h" -#include "gui_templates.h" -#include "timeline.h" -#include "instrument_track.h" -#include "tooltip.h" -#include "midi.h" -#include "tool_button.h" -#include "text_float.h" #include "combobox.h" -#include "piano_widget.h" #include "debug.h" +#include "detuning_helper.h" +#include "embed.h" +#include "gui_templates.h" +#include "instrument_track.h" +#include "main_window.h" +#include "midi.h" +#include "pattern.h" +#include "piano_widget.h" +#include "pixmap_button.h" +#include "song_editor.h" +#include "templates.h" +#include "text_float.h" +#include "timeline.h" +#include "tool_button.h" +#include "tooltip.h" typedef automationPattern::timeMap timeMap; @@ -139,7 +140,6 @@ const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DEFAULT_STEPS_PER_TACT; pianoRoll::pianoRoll( void ) : QWidget( engine::getMainWindow()->workspace() ), - m_paintPixmap(), m_pattern( NULL ), m_currentPosition(), m_recording( FALSE ), @@ -524,13 +524,13 @@ void pianoRoll::setCurrentPattern( pattern * _new_pattern ) } - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); int central_key = 0; if( notes.empty() == FALSE ) { // determine the central key so that we can scroll to it int total_notes = 0; - for( noteVector::iterator it = notes.begin(); + for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it ) { if( ( *it )->length() > 0 ) @@ -634,14 +634,43 @@ inline void pianoRoll::drawNoteRect( QPainter & _p, Uint16 _x, Uint16 _y, -void pianoRoll::updatePaintPixmap( void ) +inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, Uint16 _x, + Uint16 _y ) { - if( m_paintPixmap.isNull() == TRUE || m_paintPixmap.size() != size() ) + 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 { - m_paintPixmap = QPixmap( size() ); - } - m_paintPixmap.fill( QColor( 0, 0, 0 ) ); - QPainter p( &m_paintPixmap ); + --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::updatePaintPixmap( QPixmap & _p ) +{ + _p.fill( QColor( 0, 0, 0 ) ); + QPainter p( &_p ); // set font-size to 8 p.setFont( pointSize<8>( p.font() ) ); @@ -871,20 +900,20 @@ void pianoRoll::updatePaintPixmap( void ) int y_base = height() - PR_BOTTOM_MARGIN - m_notesEditHeight - 1; if( validPattern() == TRUE ) { - QPainter p_detuning( &m_paintPixmap ); + QPainter p_detuning( &_p ); 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 noteVector & notes = m_pattern->notes(); const int visible_keys = ( height() - PR_TOP_MARGIN - PR_BOTTOM_MARGIN - m_notesEditHeight ) / KEY_LINE_HEIGHT + 2; - for( noteVector::iterator it = notes.begin(); it != notes.end(); - ++it ) + for( noteVector::const_iterator it = notes.begin(); + it != notes.end(); ++it ) { Sint32 len_tact_64th = ( *it )->length(); @@ -1001,39 +1030,6 @@ 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; @@ -1296,10 +1292,10 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) m_currentPosition; // get note-vector of current pattern - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); // will be our iterator in the following loop - noteVector::iterator it = notes.begin(); + noteVector::const_iterator it = notes.begin(); // loop through whole note-vector... while( it != notes.end() ) @@ -1680,10 +1676,10 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) m_currentPosition; // get note-vector of current pattern - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); // will be our iterator in the following loop - noteVector::iterator it = notes.begin(); + noteVector::const_iterator it = notes.begin(); // loop through whole note-vector... while( it != notes.end() ) @@ -2038,7 +2034,8 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) void pianoRoll::paintEvent( QPaintEvent * ) { - updatePaintPixmap(); + QPixmap paintPixmap( size() ); + updatePaintPixmap( paintPixmap ); #ifdef QT4 QPainter p( this ); #else @@ -2047,7 +2044,7 @@ void pianoRoll::paintEvent( QPaintEvent * ) QPainter p( &draw_pm, this ); #endif - p.drawPixmap( 0, 0, m_paintPixmap ); + p.drawPixmap( 0, 0, paintPixmap ); p.setClipRect( WHITE_KEY_WIDTH, PR_TOP_MARGIN, width() - WHITE_KEY_WIDTH, height() - PR_TOP_MARGIN - @@ -2263,14 +2260,8 @@ void pianoRoll::recordNote( const note & _n ) _n.tone(), _n.octave(), _n.getVolume(), _n.getPanning() ); n.quantizeLength( quantization() ); -#ifndef QT4 - qApp->lock(); -#endif m_pattern->addNote( n ); update(); -#ifndef QT4 - qApp->unlock(); -#endif engine::getSongEditor()->setModified(); } } @@ -2347,12 +2338,13 @@ void pianoRoll::selectAll( void ) return; } - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); // if first_time = TRUE, we HAVE to set the vars for select bool first_time = TRUE; - for( noteVector::iterator it = notes.begin(); it != notes.end(); ++it ) + for( noteVector::const_iterator it = notes.begin(); it != notes.end(); + ++it ) { Uint32 len_tact_64th = ( *it )->length(); @@ -2419,9 +2411,10 @@ void pianoRoll::getSelectedNotes( noteVector & _selected_notes ) qSwap( sel_key_start, sel_key_end ); } - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); - for( noteVector::iterator it = notes.begin(); it != notes.end(); ++it ) + for( noteVector::const_iterator it = notes.begin(); it != notes.end(); + ++it ) { Sint32 len_tact_64th = ( *it )->length(); @@ -2661,12 +2654,12 @@ note * pianoRoll::noteUnderMouse( void ) -noteVector::iterator pianoRoll::noteIteratorUnderMouse( void ) +noteVector::const_iterator pianoRoll::noteIteratorUnderMouse( void ) { QPoint pos = mapFromGlobal( QCursor::pos() ); // get note-vector of current pattern - noteVector & notes = m_pattern->notes(); + const noteVector & notes = m_pattern->notes(); if( pos.x() <= WHITE_KEY_WIDTH || pos.x() > width() - SCROLLBAR_SIZE || pos.y() < PR_TOP_MARGIN @@ -2680,7 +2673,7 @@ noteVector::iterator pianoRoll::noteIteratorUnderMouse( void ) + m_currentPosition; // will be our iterator in the following loop - noteVector::iterator it = notes.begin(); + noteVector::const_iterator it = notes.begin(); // loop through whole note-vector... while( it != notes.end() ) diff --git a/src/core/piano_widget.cpp b/src/core/piano_widget.cpp index afe66b31a9..1e95ac4132 100644 --- a/src/core/piano_widget.cpp +++ b/src/core/piano_widget.cpp @@ -49,10 +49,13 @@ #include "piano_widget.h" #include "automatable_object_templates.h" +#include "embed.h" +#include "gui_templates.h" #include "instrument_track.h" +#include "knob.h" #include "midi.h" #include "templates.h" -#include "embed.h" +#include "update_event.h" #ifdef Q_WS_X11 @@ -483,6 +486,28 @@ void pianoWidget::keyReleaseEvent( QKeyEvent * _ke ) +void pianoWidget::setKeyState( int _key, bool _on ) +{ + m_pressedKeys[tLimit( _key, 0, NOTES_PER_OCTAVE * OCTAVES - 1 )] = _on; + QApplication::postEvent( this, new updateEvent() ); +} + + + + + +#ifndef QT3 +void pianoWidget::customEvent( QEvent * ) +#else +void pianoWidget::customEvent( QCustomEvent * ) +#endif +{ + update(); +} + + + + void pianoWidget::focusOutEvent( QFocusEvent * ) { // if we loose focus, we HAVE to note off all running notes because diff --git a/src/core/plugin.cpp b/src/core/plugin.cpp index 90b70f67c8..c0e761fb5b 100644 --- a/src/core/plugin.cpp +++ b/src/core/plugin.cpp @@ -32,12 +32,14 @@ #include #include #include +#include #else #include #include #include +#include #endif @@ -58,6 +60,7 @@ static plugin::descriptor dummy_plugin_descriptor = "Tobias Doerffel ", 0x0100, plugin::Undefined, + NULL, NULL } ; diff --git a/src/core/preset_preview_play_handle.cpp b/src/core/preset_preview_play_handle.cpp index 85a47568a9..b948588632 100644 --- a/src/core/preset_preview_play_handle.cpp +++ b/src/core/preset_preview_play_handle.cpp @@ -41,13 +41,14 @@ #include "preset_preview_play_handle.h" -#include "note_play_handle.h" -#include "instrument_track.h" -#include "track_container.h" -#include "mmp.h" #include "debug.h" +#include "engine.h" +#include "instrument_track.h" #include "midi_port.h" +#include "mmp.h" +#include "note_play_handle.h" #include "project_journal.h" +#include "track_container.h" @@ -204,6 +205,14 @@ bool presetPreviewPlayHandle::done( void ) const +bool presetPreviewPlayHandle::isFromTrack( const track * _track ) const +{ + return( s_previewTC->previewInstrumentTrack() == _track ); +} + + + + void presetPreviewPlayHandle::cleanUp( void ) { delete s_previewTC; diff --git a/src/core/sample_play_handle.cpp b/src/core/sample_play_handle.cpp index 3dbb18eb49..aa7c65c845 100644 --- a/src/core/sample_play_handle.cpp +++ b/src/core/sample_play_handle.cpp @@ -26,12 +26,13 @@ #include "sample_play_handle.h" +#include "audio_port.h" #include "bb_track.h" +#include "engine.h" #include "instrument_track.h" #include "pattern.h" #include "sample_buffer.h" #include "sample_track.h" -#include "audio_port.h" @@ -158,6 +159,14 @@ bool samplePlayHandle::done( void ) const +bool samplePlayHandle::isFromTrack( const track * _track ) const +{ + return( m_track == _track || m_bbTrack == _track ); +} + + + + f_cnt_t samplePlayHandle::totalFrames( void ) const { return( ( m_sampleBuffer->endFrame() - m_sampleBuffer->startFrame() ) * diff --git a/src/core/song_editor.cpp b/src/core/song_editor.cpp index df6bf77cd9..659162aa46 100644 --- a/src/core/song_editor.cpp +++ b/src/core/song_editor.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,6 @@ #else -#include #include #include #include @@ -114,8 +112,7 @@ songEditor::songEditor( void ) : m_trackToPlay( NULL ), m_patternToPlay( NULL ), m_loopPattern( FALSE ), - m_scrollBack( FALSE ), - m_destroyed( FALSE ) + m_scrollBack( FALSE ) { setWindowTitle( tr( "Song-Editor" ) ); setWindowIcon( embed::getIconPixmap( "songeditor" ) ); @@ -453,8 +450,8 @@ songEditor::songEditor( void ) : songEditor::~songEditor() { + m_playing = FALSE; delete m_automation_track; - m_destroyed = TRUE; } @@ -1239,10 +1236,6 @@ void songEditor::updateTimeLinePosition( void ) void songEditor::stop( void ) { - if( m_destroyed ) - { - return; - } m_actions.push_back( ACT_STOP_PLAY ); #ifdef QT4 m_playButton->setIcon( embed::getIconPixmap( "play" ) ); @@ -1420,24 +1413,10 @@ void songEditor::clearProject( void ) if( m_playing ) { - // stop play, because it's dangerous that play-routines try to - // access non existing data (as you can see in the next lines, - // all data is cleared!) stop(); } - // make sure all running notes are cleared, otherwise the whole - // thing will end up in a SIGSEGV... - engine::getMixer()->clear( TRUE ); - while( engine::getMixer()->haveNoRunningNotes() == FALSE ) - { -#ifdef QT4 - QApplication::processEvents( QEventLoop::AllEvents ); -#else - qApp->processEvents(); -#endif - } - + engine::getMixer()->lock(); clearAllTracks(); engine::getAutomationEditor()->setCurrentPattern( NULL ); @@ -1446,6 +1425,7 @@ void songEditor::clearProject( void ) m_masterPitchSlider->clearAutomationValues(); engine::getBBEditor()->clearAllTracks(); + engine::getMixer()->unlock(); engine::getProjectNotes()->clear(); @@ -1545,52 +1525,11 @@ void FASTCALL songEditor::loadProject( const QString & _file_name ) } // get the header information from the DOM - QDomNode node = mmp.head().firstChild(); - while( !node.isNull() ) - { - if( node.isElement() ) - { - if( node.nodeName() == "bpm" && - node.toElement().attribute( "value" ).toInt() > 0 ) - { - m_bpmSpinBox->setInitValue( node.toElement() - .attribute( "value" ).toInt() ); - } - else if( node.nodeName() == "mastervol" ) - { - if( node.toElement().attribute( "value" - ).toInt() > 0 ) - { - m_masterVolumeSlider->setInitValue( - node.toElement().attribute( - "value" ).toInt() ); - } - else - { - m_masterVolumeSlider->setInitValue( - DEFAULT_VOLUME ); - } - } - else if( node.nodeName() == "masterpitch" ) - { - m_masterPitchSlider->setInitValue( - -node.toElement().attribute( "value" - ).toInt() ); - } - else if( node.nodeName() - == automationPattern::classNodeName() ) - { - m_bpmSpinBox->loadSettings( mmp.head(), "bpm" ); - m_masterVolumeSlider->loadSettings( mmp.head(), - "mastervol" ); - m_masterPitchSlider->loadSettings( mmp.head(), - "masterpitch" ); - } - } - node = node.nextSibling(); - } + m_bpmSpinBox->loadSettings( mmp.head(), "bpm" ); + m_masterVolumeSlider->loadSettings( mmp.head(), "mastervol" ); + m_masterPitchSlider->loadSettings( mmp.head(), "masterpitch" ); - node = mmp.content().firstChild(); + QDomNode node = mmp.content().firstChild(); while( !node.isNull() ) { if( node.isElement() ) diff --git a/src/core/surround_area.cpp b/src/core/surround_area.cpp index f90d87c057..26a82a4ab1 100644 --- a/src/core/surround_area.cpp +++ b/src/core/surround_area.cpp @@ -54,6 +54,7 @@ #include "surround_area.h" #include "automatable_object_templates.h" #include "embed.h" +#include "knob.h" #include "templates.h" #include "tooltip.h" diff --git a/src/core/timeline.cpp b/src/core/timeline.cpp index bb721b1778..8c63b5a1c9 100644 --- a/src/core/timeline.cpp +++ b/src/core/timeline.cpp @@ -128,7 +128,10 @@ timeLine::timeLine( const int _xoff, const int _yoff, const float _ppt, timeLine::~timeLine() { - m_pos.m_timeLine = NULL; + if( engine::getSongEditor() ) + { + m_pos.m_timeLine = NULL; + } delete m_hint; } diff --git a/src/core/track.cpp b/src/core/track.cpp index cb698c99d6..f3f1e733a5 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #endif @@ -61,6 +60,8 @@ #include "templates.h" #include "clipboard.h" #include "embed.h" +#include "engine.h" +#include "gui_templates.h" #include "pixmap_button.h" #include "debug.h" #include "tooltip.h" @@ -1141,8 +1142,9 @@ void trackOperationsWidget::paintEvent( QPaintEvent * _pe ) void trackOperationsWidget::cloneTrack( void ) { - m_trackWidget->getTrack()->getTrackContainer()->cloneTrack( - m_trackWidget->getTrack() ); + engine::getMixer()->lock(); + m_trackWidget->getTrack()->clone(); + engine::getMixer()->unlock(); } @@ -1150,21 +1152,10 @@ void trackOperationsWidget::cloneTrack( void ) void trackOperationsWidget::removeTrack( void ) { -#ifdef QT3 - QTimer::singleShot( 10, this, SLOT( removeTrackTimer() ) ); -#else -//#warning fixme - removeTrackTimer(); -#endif -} - - - - -void trackOperationsWidget::removeTrackTimer( void ) -{ + engine::getMixer()->lock(); m_trackWidget->getTrack()->getTrackContainer()->removeTrack( m_trackWidget->getTrack() ); + engine::getMixer()->unlock(); } @@ -1648,10 +1639,6 @@ track::~track() track * track::create( trackTypes _tt, trackContainer * _tc ) { - // while adding track, pause mixer for not getting into any trouble - // because of track being not created completely so far - engine::getMixer()->pause(); - track * t = NULL; switch( _tt ) @@ -1669,33 +1656,27 @@ track * track::create( trackTypes _tt, trackContainer * _tc ) assert( t != NULL ); #endif - // allow mixer to continue - engine::getMixer()->play(); - return( t ); } -track * track::create( const QDomElement & _this, trackContainer * _tc ) +void track::create( const QDomElement & _this, trackContainer * _tc ) { - track * t = create( static_cast( _this.attribute( - "type" ).toInt() ), _tc ); - t->restoreState( _this ); - return( t ); + create( static_cast( _this.attribute( "type" ).toInt() ), + _tc )->restoreState( _this ); } -track * track::clone( track * _track ) +void track::clone( void ) { QDomDocument doc; QDomElement parent = doc.createElement( "clone" ); - _track->saveState( doc, parent ); - QDomElement e = parent.firstChild().toElement(); - return( create( e, _track->getTrackContainer() ) ); + saveState( doc, parent ); + create( parent.firstChild().toElement(), m_trackContainer ); } diff --git a/src/core/track_container.cpp b/src/core/track_container.cpp index 1812a07e33..2ec1e93c9e 100644 --- a/src/core/track_container.cpp +++ b/src/core/track_container.cpp @@ -48,22 +48,23 @@ #include "track_container.h" -#include "track.h" -#include "templates.h" #include "bb_track.h" -#include "main_window.h" -#include "mixer.h" -#include "song_editor.h" -#include "string_pair_drag.h" -#include "instrument_track.h" -#include "mmp.h" #include "config_mgr.h" +#include "debug.h" +#include "engine.h" +#include "file_browser.h" #include "import_filter.h" #include "instrument.h" -#include "rubberband.h" +#include "instrument_track.h" +#include "main_window.h" +#include "mixer.h" +#include "mmp.h" #include "project_journal.h" -#include "debug.h" -#include "file_browser.h" +#include "rubberband.h" +#include "song_editor.h" +#include "string_pair_drag.h" +#include "templates.h" +#include "track.h" trackContainer::trackContainer( void ) : @@ -195,16 +196,6 @@ void trackContainer::loadSettings( const QDomElement & _this ) -void trackContainer::cloneTrack( track * _track ) -{ - engine::getMixer()->pause(); - track::clone( _track ); - engine::getMixer()->play(); -} - - - - void trackContainer::addTrack( track * _track ) { QMap map; @@ -237,7 +228,6 @@ void trackContainer::removeTrack( track * _track ) map["state"] = mmp.toString(); addJournalEntry( journalEntry( REMOVE_TRACK, map ) ); - engine::getMixer()->pause(); #ifndef QT4 m_scrollArea->removeChild( _track->getTrackWidget() ); #endif @@ -245,8 +235,6 @@ void trackContainer::removeTrack( track * _track ) delete _track; - engine::getMixer()->play(); - realignTracks(); if( engine::getSongEditor() ) { @@ -334,7 +322,7 @@ void trackContainer::realignTracks( bool _complete_update ) void trackContainer::clearAllTracks( void ) { - while( m_trackWidgets.size() ) + while( !m_trackWidgets.empty() ) { removeTrack( m_trackWidgets.front()->getTrack() ); } @@ -513,6 +501,7 @@ void trackContainer::dropEvent( QDropEvent * _de ) { QString type = stringPairDrag::decodeKey( _de ); QString value = stringPairDrag::decodeValue( _de ); + engine::getMixer()->lock(); if( type == "instrument" ) { instrumentTrack * it = dynamic_cast( @@ -560,6 +549,7 @@ void trackContainer::dropEvent( QDropEvent * _de ) updateAfterTrackAdd(); _de->accept(); } + engine::getMixer()->unlock(); }