diff --git a/ChangeLog b/ChangeLog index 40bb5ad9d..81245bd07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2008-06-28 Tobias Doerffel + + * include/automation_editor.h: + fixed node-name + + * Makefile.am: + * include/automation_pattern.h: + * include/detuning_helper.h: + * include/inline_automation.h: + * include/note_play_handle.h: + * src/core/automation_pattern.cpp: + * src/core/inline_automation.cpp: + * src/core/note.cpp: + * src/core/note_play_handle.cpp: + * src/core/track.cpp: + * src/gui/piano_roll.cpp: + made note-detuning-automation work by making automationPatterns also + work without a parent-track and writing a generic inlineAutomation-class + + * src/gui/file_browser.cpp: + fixed crash when encountering invalid samplePlayHandle while + previewing (closes #2004875) + 2008-06-27 Tobias Doerffel * include/instrument_track.h: diff --git a/Makefile.am b/Makefile.am index 77c6766df..1b9a6b1ca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,7 +82,7 @@ man1_MANS = lmms.1 lmms_MOC = \ ./about_dialog.moc \ ./automatable_model.moc \ - ./automatable_model_view.moc \ + ./automatable_model_view.moc \ ./automatable_button.moc \ ./automatable_slider.moc \ ./automation_editor.moc \ @@ -220,6 +220,7 @@ lmms_SOURCES = \ $(srcdir)/src/core/instrument_sound_shaping.cpp \ $(srcdir)/src/core/fx_mixer.cpp \ $(srcdir)/src/core/import_filter.cpp \ + $(srcdir)/src/core/inline_automation.cpp \ $(srcdir)/src/core/instrument.cpp \ $(srcdir)/src/core/instrument_functions.cpp \ $(srcdir)/src/core/journalling_object.cpp \ @@ -359,6 +360,7 @@ lmms_SOURCES = \ $(srcdir)/include/lmms_style.h \ $(srcdir)/include/mixer.h \ $(srcdir)/include/pattern.h \ + $(srcdir)/include/inline_automation.h \ $(srcdir)/include/instrument_track.h \ $(srcdir)/include/note.h \ $(srcdir)/include/volume.h \ diff --git a/include/automation_pattern.h b/include/automation_pattern.h index 433ba0176..848363738 100644 --- a/include/automation_pattern.h +++ b/include/automation_pattern.h @@ -49,6 +49,10 @@ public: automationPattern( const automationPattern & _pat_to_copy ); virtual ~automationPattern(); + inline void addObject( automatableModel * _obj ) + { + m_objects += _obj; + } const automatableModel * firstObject( void ); diff --git a/include/detuning_helper.h b/include/detuning_helper.h index 01a0afae2..a301244ef 100644 --- a/include/detuning_helper.h +++ b/include/detuning_helper.h @@ -2,6 +2,7 @@ * detuning_helper.h - detuning automation helper * * Copyright (c) 2007 Javier Serrano Polo + * Copyright (c) 2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -26,29 +27,32 @@ #ifndef _DETUNING_HELPER_H #define _DETUNING_HELPER_H - -#include "automatable_model.h" -#include "shared_object.h" -#include "automation_editor.h" +#include "inline_automation.h" -class detuningHelper : public floatModel, public sharedObject +class detuningHelper : public inlineAutomation { public: detuningHelper( void ) : - floatModel(), - sharedObject() + inlineAutomation() + { + } + + virtual ~detuningHelper() { } virtual QString displayName( void ) const { - return( automationEditor::tr( "Note detuning" ) ); + return( tr( "Note detuning" ) ); + } + + inline virtual QString nodeName( void ) const + { + return( "detuning" ); } } ; - - #endif diff --git a/include/inline_automation.h b/include/inline_automation.h new file mode 100644 index 000000000..1730d1803 --- /dev/null +++ b/include/inline_automation.h @@ -0,0 +1,73 @@ +/* + * inline_automation.h - class for automating something "inline" + * + * Copyright (c) 2008 Tobias Doerffel + * + * 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 _INLINE_AUTOMATION_H +#define _INLINE_AUTOMATION_H + +#include "automation_pattern.h" +#include "shared_object.h" + + +class inlineAutomation : public floatModel, public sharedObject +{ +public: + inlineAutomation( void ) : + floatModel(), + sharedObject(), + m_autoPattern( NULL ) + { + } + + virtual ~inlineAutomation() + { + delete m_autoPattern; + } + + inline bool hasAutomationPattern( void ) const + { + return( m_autoPattern != NULL ); + } + + automationPattern * getAutomationPattern( void ) + { + if( m_autoPattern == NULL ) + { + m_autoPattern = new automationPattern( NULL ); + m_autoPattern->addObject( this ); + } + return( m_autoPattern ); + } + + virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); + + +private: + automationPattern * m_autoPattern; + +} ; + + +#endif diff --git a/include/note_play_handle.h b/include/note_play_handle.h index 482750bfb..3b630c872 100644 --- a/include/note_play_handle.h +++ b/include/note_play_handle.h @@ -319,7 +319,7 @@ private: float m_frequency; - baseDetuning * m_base_detuning; + baseDetuning * m_baseDetuning; } ; diff --git a/src/core/automation_pattern.cpp b/src/core/automation_pattern.cpp index 77b48251e..b721a03fe 100644 --- a/src/core/automation_pattern.cpp +++ b/src/core/automation_pattern.cpp @@ -141,7 +141,7 @@ midiTime automationPattern::putValue( const midiTime & _time, m_dynamic = TRUE; } - if( getTrack()->type() == track::HiddenAutomationTrack ) + if( getTrack() && getTrack()->type() == track::HiddenAutomationTrack ) { changeLength( length() ); } @@ -177,7 +177,8 @@ void automationPattern::removeValue( const midiTime & _time ) } } - if( getTrack()->type() == track::HiddenAutomationTrack ) + if( getTrack() && + getTrack()->type() == track::HiddenAutomationTrack ) { changeLength( length() ); } diff --git a/src/core/inline_automation.cpp b/src/core/inline_automation.cpp new file mode 100644 index 000000000..ccfd2e1d9 --- /dev/null +++ b/src/core/inline_automation.cpp @@ -0,0 +1,61 @@ +/* + * inline_automation.cpp - class for automating something "inline" + * + * Copyright (c) 2008 Tobias Doerffel + * + * 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 + +#include "inline_automation.h" + + +void inlineAutomation::saveSettings( QDomDocument & _doc, + QDomElement & _parent ) +{ + if( hasAutomationPattern() ) + { + QDomElement ap = _doc.createElement( + automationPattern::classNodeName() ); + QDomElement v = _doc.createElement( nodeName() ); + getAutomationPattern()->saveSettings( _doc, v ); + ap.appendChild( v ); + _parent.appendChild( ap ); + } +} + + + + +void inlineAutomation::loadSettings( const QDomElement & _this ) +{ + QDomNode node = _this.namedItem( automationPattern::classNodeName() ); + if( node.isElement() ) + { + node = node.namedItem( nodeName() ); + if( node.isElement() ) + { + getAutomationPattern()->loadSettings( + node.toElement() ); + } + } +} + diff --git a/src/core/note.cpp b/src/core/note.cpp index aa804e851..d2253fb35 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -175,7 +175,7 @@ void note::saveSettings( QDomDocument & _doc, QDomElement & _this ) _this.setAttribute( "pos", m_pos ); if( m_length > 0 ) { - m_detuning->saveSettings( _doc, _this, "detuning" ); + m_detuning->saveSettings( _doc, _this ); } } @@ -191,7 +191,10 @@ void note::loadSettings( const QDomElement & _this ) m_panning = _this.attribute( "pan" ).toInt(); m_length = _this.attribute( "len" ).toInt(); m_pos = _this.attribute( "pos" ).toInt(); - m_detuning->loadSettings( _this, "detuning" ); + if( _this.hasChildNodes() ) + { + m_detuning->loadSettings( _this ); + } } @@ -239,8 +242,7 @@ void note::redoStep( journalEntry & _je ) void note::editDetuningPattern( void ) { -#warning: TODO -// m_detuning->getAutomationPattern()->openInAutomationEditor(); + m_detuning->getAutomationPattern()->openInAutomationEditor(); } @@ -248,9 +250,8 @@ void note::editDetuningPattern( void ) void note::createDetuning( void ) { -#warning: TODO m_detuning = new detuningHelper; -// m_detuning->initAutomationPattern(); + (void) m_detuning->getAutomationPattern(); m_detuning->setRange( -MaxDetuning, MaxDetuning, 0.1f ); } @@ -259,10 +260,12 @@ void note::createDetuning( void ) bool note::hasDetuningInfo( void ) { -#warning: TODO -/* automationPattern::timeMap map = + if( m_detuning->hasAutomationPattern() ) + { + const automationPattern::timeMap & map = m_detuning->getAutomationPattern()->getTimeMap(); - return( map.size() > 1 || map[0] != 0 );*/ + return( map.size() > 1 || map[0] != 0 ); + } return( FALSE ); } diff --git a/src/core/note_play_handle.cpp b/src/core/note_play_handle.cpp index e31dc7b3b..51235f0a8 100644 --- a/src/core/note_play_handle.cpp +++ b/src/core/note_play_handle.cpp @@ -39,7 +39,7 @@ inline notePlayHandle::baseDetuning::baseDetuning( detuningHelper * _detuning ) : m_detuning( _detuning ), - m_value( /*m_detuning->getAutomationPattern()->valueAt( 0 )*/ 0 ) + m_value( m_detuning->getAutomationPattern()->valueAt( 0 ) ) { } @@ -77,12 +77,12 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it, { if( m_baseNote ) { - m_base_detuning = new baseDetuning( detuning() ); + m_baseDetuning = new baseDetuning( detuning() ); m_instrumentTrack->m_processHandles.push_back( this ); } else { - m_base_detuning = _parent->m_base_detuning; + m_baseDetuning = _parent->m_baseDetuning; _parent->m_subNotes.push_back( this ); // if there was an arp-note added and parent is a base-note @@ -123,7 +123,7 @@ notePlayHandle::~notePlayHandle() if( m_baseNote ) { - delete m_base_detuning; + delete m_baseDetuning; m_instrumentTrack->m_processHandles.removeAll( this ); } @@ -268,7 +268,8 @@ f_cnt_t notePlayHandle::framesLeft( void ) const } else if( m_released && actualReleaseFramesToDo() >= m_releaseFramesDone ) { - return( m_framesBeforeRelease + actualReleaseFramesToDo() - m_releaseFramesDone ); + return( m_framesBeforeRelease + actualReleaseFramesToDo() - + m_releaseFramesDone ); } return( m_frames+actualReleaseFramesToDo()-m_totalFramesPlayed ); } @@ -433,7 +434,7 @@ void notePlayHandle::updateFrequency( void ) const float pitch = (float)( key() % KeysPerOctave - base_tone + engine::getSong()->masterPitch() ) / 12.0f + (float)( key() / KeysPerOctave - base_octave ) + - m_base_detuning->value() / 12.0f + + m_baseDetuning->value() / 12.0f + m_instrumentTrack->m_pitchModel.value() / ( 100 * 12.0 ); m_frequency = BaseFreq * powf( 2.0f, pitch ); @@ -451,14 +452,13 @@ void notePlayHandle::processMidiTime( const midiTime & _time ) { if( _time >= pos() ) { -#warning: TODO -/* float v = detuning()->getAutomationPattern()->valueAt( _time - + float v = detuning()->getAutomationPattern()->valueAt( _time - pos() ); - if( v != m_base_detuning->value() ) + if( v != m_baseDetuning->value() ) { - m_base_detuning->setValue( v ); + m_baseDetuning->setValue( v ); updateFrequency(); - }*/ + } } } diff --git a/src/core/track.cpp b/src/core/track.cpp index 3157cfe3e..5c2739b2a 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -114,7 +114,10 @@ trackContentObject::trackContentObject( track * _track ) : m_length(), m_mutedModel( FALSE, this ) { - m_track->addTCO( this ); + if( getTrack() ) + { + getTrack()->addTCO( this ); + } setJournalling( FALSE ); movePosition( 0 ); changeLength( 0 ); @@ -137,7 +140,10 @@ trackContentObject::~trackContentObject() */ emit destroyed(); - m_track->removeTCO( this ); + if( getTrack() ) + { + getTrack()->removeTCO( this ); + } } @@ -1904,7 +1910,6 @@ void track::getTCOsInRange( tcoVector & _tco_v, const midiTime & _start, */ void track::swapPositionOfTCOs( int _tco_num1, int _tco_num2 ) { - // TODO: range-checking qSwap( m_trackContentObjects[_tco_num1], m_trackContentObjects[_tco_num2] ); diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index ad013e8d8..7d31a0e2e 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -602,13 +602,10 @@ inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, int _x, int middle_y = _y + KEY_LINE_HEIGHT / 2; _p.setPen( QColor( 0xFF, 0xDF, 0x20 ) ); -#warning BLAH -/* timeMap & map = _n->detuning()->getAutomationPattern()->getTimeMap(); - timeMap::iterator it = map.end(); - do + timeMap & map = _n->detuning()->getAutomationPattern()->getTimeMap(); + for( timeMap::const_iterator it = map.begin(); it != map.end(); ++it ) { - --it; - Sint32 pos_ticks = -it.key(); + Sint32 pos_ticks = it.key(); if( pos_ticks > _n->length() ) { break; @@ -621,7 +618,7 @@ inline void pianoRoll::drawDetuningInfo( QPainter & _p, note * _n, int _x, _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() );*/ + } }