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:
@@ -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 & );
|
||||
|
||||
} ;
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user