diff --git a/ChangeLog b/ChangeLog index db756e042..ffbedbd57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2009-02-19 Tobias Doerffel + + * include/instrument_track.h: + * include/piano_roll.h: + * src/gui/piano_roll.cpp: + * src/gui/song_editor.cpp: + * src/tracks/instrument_track.cpp: + fixed various bugs regarding recording: + - once recording has been started, stop it as soon as playMode of song + changes or similiar things happen (closes #2486341) + - fixed broken record-accompany in most use-cases other than using + record-while-playing-song by also tracking NoteOn events and remember + current play position to use the correct note postitions on NoteOff + events (play position might have wrapped around in the meantime due + to looppoints or end of BB track) (closes #2486299, #2486203) + 2009-02-14 Andrew Kelley * src/gui/dialogs/about_dialog.ui: diff --git a/include/instrument_track.h b/include/instrument_track.h index e061a90e8..7b7fab9bf 100644 --- a/include/instrument_track.h +++ b/include/instrument_track.h @@ -2,7 +2,7 @@ * instrument_track.h - declaration of class instrumentTrack, a track + window * which holds an instrument-plugin * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2009 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -185,7 +185,8 @@ public: signals: void instrumentChanged( void ); void newNote( void ); - void noteDone( const note & _n ); + void noteOn( const note & _n ); + void noteOff( const note & _n ); void nameChanged( void ); diff --git a/include/piano_roll.h b/include/piano_roll.h index d29d245a5..a58f0c606 100644 --- a/include/piano_roll.h +++ b/include/piano_roll.h @@ -2,7 +2,7 @@ * piano_roll.h - declaration of class pianoRoll which is a window where you * can set and edit notes in an easy way * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2009 Tobias Doerffel * Copyright (c) 2008 Andrew Kelley * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net @@ -32,6 +32,7 @@ #include "serializing_object.h" #include "note.h" #include "lmms_basics.h" +#include "song.h" #include "fluiq/collapsible_widget.h" @@ -55,6 +56,11 @@ class pianoRoll : public FLUIQ::CollapsibleWidget, public serializingObject public: void setCurrentPattern( pattern * _new_pattern ); + inline void stopRecording( void ) + { + m_recording = false; + } + inline bool isRecording( void ) const { return m_recording; @@ -70,6 +76,8 @@ public: return m_pattern != NULL; } + song::PlayModes desiredPlayModeForAccompany( void ) const; + int quantization( void ) const; @@ -80,6 +88,8 @@ public: { return "pianoroll"; } + + public slots: void play( void ); void record( void ); @@ -109,8 +119,8 @@ protected: protected slots: - - void recordNote( const note & _n ); + void startRecordNote( const note & _n ); + void finishRecordNote( const note & _n ); void horScrolled( int _new_pos ); void verScrolled( int _new_pos ); @@ -241,6 +251,7 @@ private: midiTime m_currentPosition; bool m_recording; + QList m_recordingNotes; note * m_currentNote; Actions m_action; diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index b84e412e0..5828eb279 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -48,6 +48,7 @@ #include +#include "bb_track_container.h" #include "clipboard.h" #include "combobox.h" #include "debug.h" @@ -574,11 +575,12 @@ void pianoRoll::setCurrentPattern( pattern * _new_pattern ) // of start-notes and so on...) resizeEvent( NULL ); - // and now connect to noteDone()-signal of channel so that - // we receive note-off-events from it's midi-port for recording it connect( m_pattern->getInstrumentTrack(), - SIGNAL( noteDone( const note & ) ), - this, SLOT( recordNote( const note & ) ) ); + SIGNAL( noteOn( const note & ) ), + this, SLOT( startRecordNote( const note & ) ) ); + connect( m_pattern->getInstrumentTrack(), + SIGNAL( noteOff( const note & ) ), + this, SLOT( finishRecordNote( const note & ) ) ); setWindowTitle( tr( "Piano-Roll - %1" ).arg( m_pattern->name() ) ); @@ -2964,6 +2966,19 @@ int pianoRoll::getKey( int _y ) const +song::PlayModes pianoRoll::desiredPlayModeForAccompany( void ) const +{ + if( m_pattern->getTrack()->getTrackContainer() == + engine::getBBTrackContainer() ) + { + return song::Mode_PlayBB; + } + return song::Mode_PlaySong; +} + + + + void pianoRoll::play( void ) { engine::getMainWindow()->setPlaybackMode( PPM_PianoRoll ); @@ -3038,7 +3053,7 @@ void pianoRoll::recordAccompany( void ) } m_recording = true; - + if( m_pattern->getTrack()->getTrackContainer() == engine::getSong() ) { engine::getSong()->play(); @@ -3065,17 +3080,49 @@ void pianoRoll::stop( void ) -void pianoRoll::recordNote( const note & _n ) +void pianoRoll::startRecordNote( const note & _n ) { - if( m_recording == true && validPattern() == true ) + if( m_recording == true && validPattern() == true && + engine::getSong()->isPlaying() && + ( engine::getSong()->playMode() == + desiredPlayModeForAccompany() || + engine::getSong()->playMode() == + song::Mode_PlayPattern ) ) { - note n( _n.length(), engine::getSong()->getPlayPos( - engine::getSong()->playMode() ) - _n.length(), + note n( 1, engine::getSong()->getPlayPos( + engine::getSong()->playMode() ), _n.key(), _n.getVolume(), _n.getPanning() ); - n.quantizeLength( quantization() ); - m_pattern->addNote( n ); - update(); - engine::getSong()->setModified(); + m_recordingNotes << n; + } +} + + + + +void pianoRoll::finishRecordNote( const note & _n ) +{ + if( m_recording == true && validPattern() == true && + engine::getSong()->isPlaying() && + ( engine::getSong()->playMode() == + desiredPlayModeForAccompany() || + engine::getSong()->playMode() == + song::Mode_PlayPattern ) ) + { + for( QList::Iterator it = m_recordingNotes.begin(); + it != m_recordingNotes.end(); ++it ) + { + if( it->key() == _n.key() ) + { + note n( _n.length(), it->pos(), + it->key(), it->getVolume(), + it->getPanning() ); + n.quantizeLength( quantization() ); + m_pattern->addNote( n ); + update(); + m_recordingNotes.erase( it ); + break; + } + } } } diff --git a/src/gui/song_editor.cpp b/src/gui/song_editor.cpp index e77c6113d..158c48cb3 100644 --- a/src/gui/song_editor.cpp +++ b/src/gui/song_editor.cpp @@ -3,7 +3,7 @@ /* * song_editor.cpp - basic window for song-editing * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2009 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -47,6 +47,7 @@ #include "tool_button.h" #include "tooltip.h" #include "audio_device.h" +#include "piano_roll.h" @@ -280,6 +281,7 @@ void songEditor::play( void ) engine::getMainWindow()->setPlaybackMode( PPM_Song ); m_s->play(); + engine::getPianoRoll()->stopRecording(); if( m_s->playMode() == song::Mode_PlaySong ) { m_playButton->setIcon( embed::getIconPixmap( "pause" ) ); @@ -316,6 +318,7 @@ void songEditor::recordAccompany( void ) void songEditor::stop( void ) { m_s->stop(); + engine::getPianoRoll()->stopRecording(); m_playButton->setIcon( embed::getIconPixmap( "play" ) ); } diff --git a/src/tracks/instrument_track.cpp b/src/tracks/instrument_track.cpp index 32f191770..ef8c2a227 100644 --- a/src/tracks/instrument_track.cpp +++ b/src/tracks/instrument_track.cpp @@ -2,7 +2,7 @@ * instrument_track.cpp - implementation of instrument-track-class * (window + data-structures) * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2009 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -248,6 +248,8 @@ void instrumentTrack::processInEvent( const midiEvent & _me, { m_notes[_me.key()] = nph; } + + emit noteOn( n ); } break; } @@ -259,7 +261,7 @@ void instrumentTrack::processInEvent( const midiEvent & _me, { // create dummy-note which has the same length // as the played note for sending it later - // to all slots connected to signal noteDone() + // to all slots connected to signal noteOff() // this is for example needed by piano-roll for // recording notes into a pattern note done_note( @@ -274,7 +276,7 @@ void instrumentTrack::processInEvent( const midiEvent & _me, n->noteOff(); m_notes[_me.key()] = NULL; - emit noteDone( done_note ); + emit noteOff( done_note ); } break; } @@ -463,7 +465,7 @@ void instrumentTrack::deleteNotePluginData( notePlayHandle * _n ) _n->getVolume(), _n->getPanning() ); _n->noteOff(); m_notes[_n->key()] = NULL; - emit noteDone( done_note ); + emit noteOff( done_note ); } }