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.
This commit is contained in:
Tobias Doerffel
2010-05-21 12:52:57 +02:00
parent ace2266529
commit afba8a7ad4
2 changed files with 78 additions and 46 deletions

View File

@@ -24,10 +24,10 @@
*
*/
#ifndef _AUTOMATION_EDITOR_H
#define _AUTOMATION_EDITOR_H
#include <QtCore/QMutex>
#include <QtGui/QWidget>
#include "lmms_basics.h"
@@ -76,6 +76,7 @@ public:
public slots:
void update();
void updateAfterPatternChange();
protected:
@@ -190,6 +191,7 @@ private:
ComboBoxModel m_zoomingYModel;
ComboBoxModel m_quantizeModel;
QMutex m_patternMutex;
automationPattern * m_pattern;
float m_minLevel;
float m_maxLevel;
@@ -242,6 +244,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( ModeDraw ),
m_scrollBack( false )
{
connect( this, SIGNAL( currentPatternChanged() ),
this, SLOT( updateAfterPatternChange() ),
Qt::QueuedConnection );
// init pixmaps
if( s_toolDraw == NULL )
{
@@ -373,6 +376,8 @@ automationEditor::automationEditor() :
automationEditor::~automationEditor()
{
m_zoomingXModel.disconnect();
m_zoomingYModel.disconnect();
}
@@ -380,10 +385,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;
@@ -401,8 +435,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();
}
@@ -410,17 +443,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();
}
}
@@ -684,7 +716,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;
}
@@ -847,7 +880,8 @@ void automationEditor::mouseReleaseEvent( QMouseEvent * _me )
void automationEditor::mouseMoveEvent( QMouseEvent * _me )
{
if( validPattern() == false )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
update();
return;
@@ -1221,6 +1255,8 @@ inline void automationEditor::drawCross( QPainter & _p )
void automationEditor::paintEvent( QPaintEvent * _pe )
{
QMutexLocker m( &m_patternMutex );
QStyleOption opt;
opt.initFrom( this );
QPainter p( this );
@@ -1242,7 +1278,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 )
{
@@ -1391,7 +1427,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();
@@ -1528,7 +1564,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
p.drawRect( x + ValuesWidth, 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 )
@@ -1537,7 +1573,7 @@ void automationEditor::paintEvent( QPaintEvent * _pe )
m_leftRightScroll->setPageStep( l );
}
if( validPattern() == true )
if( validPattern() )
{
drawCross( p );
}
@@ -1666,7 +1702,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() );
}
@@ -1675,7 +1713,9 @@ inline bool automationEditor::inBBEditor()
void automationEditor::play()
{
if( validPattern() == false )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1749,6 +1789,8 @@ void automationEditor::play()
void automationEditor::stop()
{
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
@@ -1832,7 +1874,8 @@ void automationEditor::moveButtonToggled()
void automationEditor::selectAll()
{
if( validPattern() == false )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1870,7 +1913,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;
}
@@ -1938,7 +1982,8 @@ void automationEditor::copySelectedValues()
void automationEditor::cutSelectedValues()
{
if( validPattern() == false )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -1969,12 +2014,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 )
@@ -1996,7 +2037,8 @@ void automationEditor::pasteValues()
void automationEditor::deleteSelectedValues()
{
if( validPattern() == false )
QMutexLocker m( &m_patternMutex );
if( !validPattern() )
{
return;
}
@@ -2140,19 +2182,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"