Commit 2cd5097c authored by Hugo Beauzee-Luyssen's avatar Hugo Beauzee-Luyssen

Working version of pause/unpause

This is really much cleaner than the old versions...
parent ad9a3174
......@@ -85,11 +85,11 @@ void MediaPlayer::callbacks( const libvlc_event_t* ev
switch ( event->type )
{
case libvlc_MediaPlayerPlaying:
qDebug() << "Media player playing";
// qDebug() << "Media player playing";
self->emit playing();
break;
case libvlc_MediaPlayerPaused:
qDebug() << "Media player paused";
// qDebug() << "Media player paused";
self->emit paused();
break;
case libvlc_MediaPlayerStopped:
......
......@@ -97,7 +97,9 @@ void ClipWorkflow::unlock( ClipWorkflow* cw )
cw->m_renderWaitCond->wake();
cw->emit renderComplete( cw );
qDebug() << "Entering condwait";
cw->m_waitCond->wait( cw->m_condMutex );
qDebug() << "Leaving condwait";
cw->m_stateLock->lockForWrite();
cw->m_state = Rendering;
cw->m_stateLock->unlock();
......@@ -130,6 +132,7 @@ void ClipWorkflow::setVmem()
void ClipWorkflow::initialize()
{
qDebug() << "Initialize";
setState( Initializing );
m_vlcMedia = new LibVLCpp::Media( m_clip->getParent()->getFileInfo()->absoluteFilePath() );
setVmem();
......@@ -138,31 +141,37 @@ void ClipWorkflow::initialize()
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ), Qt::DirectConnection );
connect( m_mediaPlayer, SIGNAL( endReached() ), this, SLOT( clipEndReached() ), Qt::DirectConnection );
connect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( pausedMediaPlayer() ), Qt::DirectConnection );
m_mediaPlayer->play();
qDebug() << "playback required";
}
void ClipWorkflow::setPositionAfterPlayback()
{
disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( setPositionAfterPlayback() ) );
connect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( pauseAfterPlaybackStarted() ), Qt::DirectConnection );
m_mediaPlayer->setPosition( m_clip->getBegin() );
qDebug() << "Set position";
}
void ClipWorkflow::pauseAfterPlaybackStarted()
{
qDebug() << "pauseAfterPlaybackStarted();";
disconnect( m_mediaPlayer, SIGNAL( positionChanged() ), this, SLOT( pauseAfterPlaybackStarted() ) );
//FIXME: it seems that this signal is never connected :o
disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( pauseAfterPlaybackStarted() ) );
connect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( initializedMediaPlayer() ), Qt::DirectConnection );
m_mediaPlayer->pause();
m_mediaPlayer->pause();
}
void ClipWorkflow::initializedMediaPlayer()
{
qDebug() << "initializedMediaPlayer();";
disconnect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( initializedMediaPlayer() ) );
connect( m_mediaPlayer, SIGNAL( paused() ), this, SLOT( pausedMediaPlayer() ), Qt::DirectConnection );
setState( Ready );
qDebug() << "Ready";
}
bool ClipWorkflow::isReady() const
......@@ -300,6 +309,7 @@ void ClipWorkflow::pause()
void ClipWorkflow::unpause()
{
queryStateChange( ClipWorkflow::Rendering );
connect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( unpausedMediaPlayer() ), Qt::DirectConnection );
m_mediaPlayer->pause();
}
......@@ -328,4 +338,11 @@ LibVLCpp::MediaPlayer* ClipWorkflow::getMediaPlayer()
void ClipWorkflow::pausedMediaPlayer()
{
setState( Paused );
emit paused();
}
void ClipWorkflow::unpausedMediaPlayer()
{
disconnect( m_mediaPlayer, SIGNAL( playing() ), this, SLOT( unpausedMediaPlayer() ) );
emit unpaused();
}
......@@ -211,12 +211,15 @@ class ClipWorkflow : public QObject
void initializedMediaPlayer();
void setPositionAfterPlayback();
void pausedMediaPlayer();
void unpausedMediaPlayer();
public slots:
void clipEndReached();
signals:
void renderComplete( ClipWorkflow* );
void paused();
void unpaused();
};
#endif // CLIPWORKFLOW_H
......@@ -46,6 +46,7 @@ MainWorkflow::MainWorkflow( int trackCount ) :
m_tracks[i].setPtr( new TrackWorkflow( i ) );
connect( m_tracks[i], SIGNAL( trackEndReached( unsigned int ) ), this, SLOT( trackEndReached(unsigned int) ) );
connect( m_tracks[i], SIGNAL( trackPaused() ), this, SLOT( trackPaused() ) );
connect( m_tracks[i], SIGNAL( trackUnpaused() ), this, SLOT( trackUnpaused() ) );
connect( m_tracks[i], SIGNAL( renderCompleted( unsigned int ) ), this, SLOT( tracksRenderCompleted( unsigned int ) ), Qt::QueuedConnection );
}
m_renderStartedLock = new QReadWriteLock;
......@@ -148,6 +149,21 @@ void MainWorkflow::pause()
}
}
void MainWorkflow::unpause()
{
QMutexLocker lock( m_renderMutex );
m_nbTracksToUnpause = 0;
for ( unsigned int i = 0; i < m_trackCount; ++i )
{
if ( m_tracks[i].activated() == true )
{
m_nbTracksToUnpause.fetchAndAddAcquire( 1 );
m_tracks[i]->unpause();
}
}
}
void MainWorkflow::nextFrame()
{
// qDebug() << "Going to the next frame";
......@@ -258,15 +274,22 @@ void MainWorkflow::clipMoved( QUuid clipUuid, int oldTrack, int newTra
void MainWorkflow::trackPaused()
{
// qDebug() << "Track pausing finished...";
m_nbTracksToPause.fetchAndAddAcquire( -1 );
if ( m_nbTracksToPause <= 0 )
{
// qDebug() << "\t\t...MainWorkflow is paused";
emit mainWorkflowPaused();
}
}
void MainWorkflow::trackUnpaused()
{
m_nbTracksToUnpause.fetchAndAddAcquire( -1 );
if ( m_nbTracksToUnpause <= 0 )
{
emit mainWorkflowUnpaused();
}
}
void MainWorkflow::tracksRenderCompleted( unsigned int trackId )
{
m_nbTracksToRender.fetchAndAddAcquire( -1 );
......
......@@ -71,6 +71,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
* Pause the main workflow and all its sub-workflows
*/
void pause();
void unpause();
static unsigned char* blackOutput;
void nextFrame();
......@@ -87,7 +88,6 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
private:
static MainWorkflow* m_instance;
// QAtomicInt m_oneFrameOnly;
private:
void computeLength();
......@@ -105,6 +105,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
QMutex* m_renderMutex;
QAtomicInt m_nbTracksToPause;
QAtomicInt m_nbTracksToUnpause;
QAtomicInt m_nbTracksToRender;
QMutex* m_highestTrackNumberMutex;
unsigned int m_highestTrackNumber;
......@@ -118,6 +119,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
private slots:
void trackEndReached( unsigned int trackId );
void trackPaused();
void trackUnpaused();
void tracksRenderCompleted( unsigned int trackId );
signals:
......@@ -132,6 +134,7 @@ class MainWorkflow : public QObject, public Singleton<MainWorkflow>
void mainWorkflowEndReached();
void mainWorkflowPaused();
void mainWorkflowUnpaused();
};
#endif // MAINWORKFLOW_H
......@@ -61,6 +61,8 @@ void TrackWorkflow::addClip( ClipWorkflow* cw, qint64 start )
{
QWriteLocker lock( m_clipsLock );
connect( cw, SIGNAL( renderComplete( ClipWorkflow* ) ), this, SLOT( clipWorkflowRenderCompleted( ClipWorkflow* ) ), Qt::DirectConnection );
connect( cw, SIGNAL( paused() ), this, SLOT( clipWorkflowPaused() ) );
connect( cw, SIGNAL( unpaused() ), this, SLOT( clipWorkflowUnpaused() ) );
m_clips.insert( start, cw );
computeLength();
}
......@@ -130,6 +132,7 @@ void TrackWorkflow::renderClip( ClipWorkflow* cw, qint64 currentFrame,
//Otherwise, it will start directly.
cw->getStateLock()->unlock();
cw->startRender();
if ( needRepositioning == true )
{
float pos = ( (float)( currentFrame - start ) / (float)(cw->getClip()->getLength()) );
......@@ -292,24 +295,6 @@ bool TrackWorkflow::getOutput( qint64 currentFrame )
return hasRendered;
}
void TrackWorkflow::pauseClipWorkflow( ClipWorkflow* cw )
{
cw->getStateLock()->lockForRead();
if ( cw->getState() == ClipWorkflow::Stopped )
{
cw->getStateLock()->unlock();
return ;
}
if ( cw->getState() != ClipWorkflow::Paused )
{
//TODO (redo actually...) :)
Q_ASSERT( false );
}
else
cw->getStateLock()->unlock();
}
void TrackWorkflow::pause()
{
QReadLocker lock( m_clipsLock );
......@@ -317,7 +302,6 @@ void TrackWorkflow::pause()
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
//FIXME: it's probably bad to iterate over every clip workflows.
m_nbClipToPause = 0;
for ( ; it != end; ++it )
{
......@@ -333,7 +317,7 @@ void TrackWorkflow::pause()
{
cw->getStateLock()->unlock();
m_nbClipToPause.fetchAndAddAcquire( 1 );
pauseClipWorkflow( cw );
cw->pause();
}
else
{
......@@ -343,8 +327,6 @@ void TrackWorkflow::pause()
}
}
m_paused = !m_paused;
if ( m_paused == true )
emit trackPaused();
}
void TrackWorkflow::moveClip( const QUuid& id, qint64 startingFrame )
......@@ -415,3 +397,49 @@ unsigned char* TrackWorkflow::getSynchroneOutput()
{
return m_synchroneRenderBuffer;
}
void TrackWorkflow::clipWorkflowPaused()
{
m_nbClipToPause.fetchAndAddAcquire( -1 );
if ( m_nbClipToPause <= 0 )
{
emit trackPaused();
}
}
void TrackWorkflow::unpause()
{
QReadLocker lock( m_clipsLock );
QMap<qint64, ClipWorkflow*>::iterator it = m_clips.begin();
QMap<qint64, ClipWorkflow*>::iterator end = m_clips.end();
m_nbClipToUnpause = 0;
for ( ; it != end; ++it )
{
ClipWorkflow* cw = it.value();
cw->getStateLock()->lockForRead();
if ( cw->getState() == ClipWorkflow::Paused )
{
cw->getStateLock()->unlock();
m_nbClipToUnpause.fetchAndAddAcquire( 1 );
cw->unpause();
}
else
{
cw->getStateLock()->unlock();
}
}
m_paused = !m_paused;
}
void TrackWorkflow::clipWorkflowUnpaused()
{
m_nbClipToUnpause.fetchAndAddAcquire( -1 );
if ( m_nbClipToUnpause <= 0 )
{
qDebug() << "Track unpaused";
emit trackUnpaused();
}
}
......@@ -52,11 +52,8 @@ class TrackWorkflow : public QObject
bool getOutput( qint64 currentFrame );
qint64 getLength() const;
void stop();
/**
* Will pause all the track's ClipWorkflow.
* This method *is synchrone*, and will not return until all of the ClipWorkflow's thread are asleep
*/
void pause();
void unpause();
void moveClip( const QUuid& id, qint64 startingFrame );
Clip* removeClip( const QUuid& id );
void addClip( Clip*, qint64 start );
......@@ -75,7 +72,6 @@ class TrackWorkflow : public QObject
qint64 start, bool needRepositioning );
void preloadClip( ClipWorkflow* cw );
void stopClipWorkflow( ClipWorkflow* cw );
void pauseClipWorkflow( ClipWorkflow* cw );
bool checkEnd( qint64 currentFrame ) const;
private:
......@@ -100,17 +96,20 @@ class TrackWorkflow : public QObject
bool m_paused;
QAtomicInt m_nbClipToPause;
QAtomicInt m_nbClipToUnpause;
QAtomicInt m_nbClipToRender;
unsigned char* m_synchroneRenderBuffer;
private slots:
// void clipWorkflowPaused();
void clipWorkflowPaused();
void clipWorkflowUnpaused();
void clipWorkflowRenderCompleted( ClipWorkflow* );
signals:
void trackEndReached( unsigned int );
void trackPaused();
void trackUnpaused();
void renderCompleted( unsigned int );
};
......
......@@ -30,6 +30,7 @@
WorkflowRenderer::WorkflowRenderer( MainWorkflow* mainWorkflow ) :
m_mainWorkflow( mainWorkflow ),
m_pauseAsked( false ),
m_unpauseAsked( false ),
m_pausedMediaPlayer( false )
{
char buffer[64];
......@@ -93,8 +94,6 @@ void* WorkflowRenderer::lock( void* datas )
void WorkflowRenderer::unlock( void* datas )
{
WorkflowRenderer* self = reinterpret_cast<WorkflowRenderer*>( datas );
self->internalPlayPause( true );
self->checkActions();
}
......@@ -136,8 +135,9 @@ void WorkflowRenderer::startPreview()
char buff[128];
connect( m_mainWorkflow, SIGNAL( frameChanged(qint64) ),
Timeline::getInstance()->tracksView()->tracksCursor(), SLOT( updateCursorPos( qint64 ) ) );
Timeline::getInstance()->tracksView()->tracksCursor(), SLOT( updateCursorPos( qint64 ) ) );
connect( m_mainWorkflow, SIGNAL( mainWorkflowPaused() ), this, SLOT( mainWorkflowPaused() ) );
connect( m_mainWorkflow, SIGNAL( mainWorkflowUnpaused() ), this, SLOT( mainWorkflowUnpaused() ) );
m_mainWorkflow->startRender();
sprintf( buff, ":fake-duration=%lli", m_mainWorkflow->getLength() / FPS * 1000 );
m_media->addOption( buff );
......@@ -168,6 +168,15 @@ void WorkflowRenderer::pauseMainWorkflow()
m_mainWorkflow->pause();
}
void WorkflowRenderer::unpauseMainWorkflow()
{
qDebug() << "unpauseMainWorkflow();";
if ( m_paused == false )
return ;
m_pausedMediaPlayer = false;
m_mainWorkflow->unpause();
}
void WorkflowRenderer::mainWorkflowPaused()
{
m_paused = true;
......@@ -175,6 +184,14 @@ void WorkflowRenderer::mainWorkflowPaused()
emit paused();
}
void WorkflowRenderer::mainWorkflowUnpaused()
{
qDebug() << "Emmiting signal playing";
m_paused = false;
m_unpauseAsked = false;
emit playing();
}
void WorkflowRenderer::togglePlayPause( bool forcePause )
{
if ( m_isRendering == false && forcePause == false )
......@@ -190,8 +207,11 @@ void WorkflowRenderer::internalPlayPause( bool forcePause )
{
if ( m_paused == true && forcePause == false )
{
//This will automaticly unpause the ClipWorkflow... no worries
m_mediaPlayer->play();
if ( m_paused == true )
{
m_unpauseAsked = true;
m_mediaPlayer->play();
}
}
else
{
......@@ -236,14 +256,21 @@ void WorkflowRenderer::__positionChanged( float pos )
void WorkflowRenderer::__videoPaused()
{
pauseMainWorkflow();
if ( m_pauseAsked == true )
pauseMainWorkflow();
}
void WorkflowRenderer::__videoPlaying()
{
emit playing();
m_pausedMediaPlayer = false;
m_paused = false;
if ( m_unpauseAsked == true )
unpauseMainWorkflow();
else
{
qDebug() << "Emmiting signal playing without mainworkflow";
m_paused = false;
m_pausedMediaPlayer = false;
emit playing();
}
}
void WorkflowRenderer::__videoStopped()
......
......@@ -40,7 +40,7 @@ class WorkflowRenderer : public GenericRenderer
enum Actions
{
Pause,
Unpause,
//Unpause,
};
WorkflowRenderer( MainWorkflow* mainWorkflow );
~WorkflowRenderer();
......@@ -65,6 +65,7 @@ class WorkflowRenderer : public GenericRenderer
private:
void internalPlayPause( bool forcePause );
void pauseMainWorkflow();
void unpauseMainWorkflow();
virtual void startPreview();
void checkActions();
......@@ -75,6 +76,7 @@ class WorkflowRenderer : public GenericRenderer
QStack<Actions> m_actions;
QReadWriteLock* m_actionsLock;
bool m_pauseAsked;
bool m_unpauseAsked;
/**
* \brief This flag is used to avoid using libvlc function from the media player thread,
......@@ -87,6 +89,7 @@ class WorkflowRenderer : public GenericRenderer
void mediaUnloaded( const QUuid& ) {}
void mainWorkflowPaused();
void mainWorkflowUnpaused();
void __positionChanged();
void __positionChanged( float pos );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment