AutomationEditor: thread-safe handling of AutomationPattern pointer

It was not possible to call any of the functions of AutomationEditor
from threads other than the main GUI thread as the m_pattern pointer
was not protected by a mutex. It is however desired to be able to call
for example AutomationEditor::setCurrentPattern(...) from different
threads (mainly required when deleting AutomationPatterns in other
threads). Thus made this method and all accesses to the m_pattern
pointer thread-safe.
(cherry picked from commit afba8a7ad4)
This commit is contained in:
Tobias Doerffel
2010-05-21 12:52:57 +02:00
parent 566a3334aa
commit aa992e8e1b
2 changed files with 78 additions and 46 deletions

View File

@@ -23,10 +23,10 @@
*
*/
#ifndef _AUTOMATION_EDITOR_H
#define _AUTOMATION_EDITOR_H
#include <QtCore/QMutex>
#include <QtGui/QWidget>
#include "lmms_basics.h"
@@ -75,6 +75,7 @@ public:
public slots:
void update();
void updateAfterPatternChange();
protected:
@@ -187,6 +188,7 @@ private:
ComboBoxModel m_zoomingYModel;
ComboBoxModel m_quantizeModel;
QMutex m_patternMutex;
automationPattern * m_pattern;
float m_minLevel;
float m_maxLevel;
@@ -239,6 +241,7 @@ private:
signals:
void currentPatternChanged();
void positionChanged( const midiTime & );
} ;

View File

@@ -24,10 +24,8 @@
*
*/
#include "automation_editor.h"
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QKeyEvent>
@@ -77,6 +75,7 @@ automationEditor::automationEditor() :
m_zoomingXModel(),
m_zoomingYModel(),
m_quantizeModel(),
m_patternMutex( QMutex::Recursive ),
m_pattern( NULL ),
m_minLevel( 0 ),
m_maxLevel( 0 ),
@@ -94,6 +93,10 @@ automationEditor::automationEditor() :
m_editMode( DRAW ),
m_scrollBack( FALSE )
{
connect( this, SIGNAL( currentPatternChanged() ),
this, SLOT( updateAfterPatternChange() ),
Qt::QueuedConnection );
// init pixmaps
if( s_toolDraw == NULL )
{
@@ -375,6 +378,8 @@ automationEditor::automationEditor() :
automationEditor::~automationEditor()
{
m_zoomingXModel.disconnect();
m_zoomingYModel.disconnect();
}
@@ -382,10 +387,39 @@ automationEditor::~automationEditor()
void automationEditor::setCurrentPattern( automationPattern * _new_pattern )
{
m_patternMutex.lock();
m_pattern = _new_pattern;
m_patternMutex.unlock();
emit currentPatternChanged();
}
void automationEditor::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
MainWindow::saveWidgetState( this, _this );
}
void automationEditor::loadSettings( const QDomElement & _this )
{
MainWindow::restoreWidgetState( this, _this );
}
void automationEditor::updateAfterPatternChange()
{
QMutexLocker m( &m_patternMutex );
m_currentPosition = 0;
if( validPattern() == FALSE )
if( !validPattern() )
{
setWindowTitle( tr( "Automation Editor - no pattern" ) );
m_minLevel = m_maxLevel = m_scrollLevel = 0;
@@ -403,8 +437,7 @@ void automationEditor::setCurrentPattern( automationPattern * _new_pattern )
// of levels and so on...)
resizeEvent( NULL );
setWindowTitle( tr( "Automation Editor - %1" ).arg(
m_pattern->name() ) );
setWindowTitle( tr( "Automation Editor - %1" ).arg( m_pattern->name() ) );
update();
}
@@ -412,17 +445,16 @@ void automationEditor::setCurrentPattern( automationPattern * _new_pattern )
void automationEditor::saveSettings( QDomDocument & _doc, QDomElement & _this )
void automationEditor::update()
{
MainWindow::saveWidgetState( this, _this );
}
QWidget::update();
void automationEditor::loadSettings( const QDomElement & _this )
{
MainWindow::restoreWidgetState( this, _this );
QMutexLocker m( &m_patternMutex );
// Note detuning?
if( m_pattern && !m_pattern->getTrack() )
{
engine::getPianoRoll()->update();
}
}
@@ -691,7 +723,8 @@ void automationEditor::drawLine( int _x0, float _y0, int _x1, float _y1 )
void automationEditor::mousePressEvent( QMouseEvent * _me )
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -854,7 +887,8 @@ void automationEditor::mouseReleaseEvent( QMouseEvent * _me )
void automationEditor::mouseMoveEvent( QMouseEvent * _me )
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
update();
return;
@@ -1228,6 +1262,8 @@ inline void automationEditor::drawCross( QPainter & _p )
void automationEditor::paintEvent( QPaintEvent * _pe )
{
QMutexLocker m( &m_patternMutex );
QStyleOption opt;
opt.initFrom( this );
QPainter p( this );
@@ -1249,7 +1285,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
Qt::Alignment text_flags =
(Qt::Alignment)( Qt::AlignRight | Qt::AlignVCenter );
if( m_pattern )
if( validPattern() )
{
if( m_y_auto )
{
@@ -1398,7 +1434,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
qSwap<float>( selLevel_start, selLevel_end );
}
if( validPattern() == TRUE )
if( validPattern() )
{
timeMap & time_map = m_pattern->getTimeMap();
timeMap::iterator it = time_map.begin();
@@ -1534,7 +1570,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
p.drawRect( x + VALUES_WIDTH, y, w, h );
// TODO: Get this out of paint event
int l = ( validPattern() == TRUE )? (int) m_pattern->length() : 0;
int l = validPattern() ? (int) m_pattern->length() : 0;
// reset scroll-range
if( m_leftRightScroll->maximum() != l )
@@ -1543,7 +1579,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
m_leftRightScroll->setPageStep( l );
}
if( validPattern() == TRUE )
if( validPattern() )
{
drawCross( p );
}
@@ -1672,7 +1708,9 @@ float automationEditor::getLevel( int _y )
inline bool automationEditor::inBBEditor()
{
return( m_pattern->getTrack()->getTrackContainer()
QMutexLocker m( &m_patternMutex );
return( validPattern() &&
m_pattern->getTrack()->getTrackContainer()
== engine::getBBTrackContainer() );
}
@@ -1681,7 +1719,9 @@ inline bool automationEditor::inBBEditor()
void automationEditor::play()
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1755,6 +1795,8 @@ void automationEditor::play()
void automationEditor::stop()
{
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
@@ -1838,7 +1880,8 @@ void automationEditor::moveButtonToggled()
void automationEditor::selectAll()
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1876,7 +1919,8 @@ void automationEditor::selectAll()
// returns vector with pointers to all selected values
void automationEditor::getSelectedValues( timeMap & _selected_values )
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1944,7 +1988,8 @@ void automationEditor::copySelectedValues()
void automationEditor::cutSelectedValues()
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1975,12 +2020,8 @@ void automationEditor::cutSelectedValues()
void automationEditor::pasteValues()
{
if( validPattern() == FALSE )
{
return;
}
if( !m_valuesToCopy.isEmpty() )
QMutexLocker m( &m_patternMutex );
if( validPattern() && !m_valuesToCopy.isEmpty() )
{
for( timeMap::iterator it = m_valuesToCopy.begin();
it != m_valuesToCopy.end(); ++it )
@@ -2002,7 +2043,8 @@ void automationEditor::pasteValues()
void automationEditor::deleteSelectedValues()
{
if( validPattern() == FALSE )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -2146,19 +2188,6 @@ void automationEditor::updateTopBottomLevels()
void automationEditor::update()
{
QWidget::update();
// Note detuning?
if( m_pattern && !m_pattern->getTrack() )
{
engine::getPianoRoll()->update();
}
}
#include "moc_automation_editor.cxx"