diff --git a/.gitignore b/.gitignore index f9f086a9..144e8529 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,6 @@ compile_commands.json **/.python-version cmake-*/* -build/* -_build/* +/*build*/ _install/* .venv/* diff --git a/src/lib/app/RvCommon/RvPreferences.cpp b/src/lib/app/RvCommon/RvPreferences.cpp index 3cfece36..c637be68 100644 --- a/src/lib/app/RvCommon/RvPreferences.cpp +++ b/src/lib/app/RvCommon/RvPreferences.cpp @@ -3593,6 +3593,10 @@ RvPreferences::videoFormatChanged(int v) settings.setValue("videoFormat", v); settings.endGroup(); + // The user has set a new video format which overrides the video format + // specified on the command line if any + Rv::Options::sharedOptions().presentFormat=nullptr; + updateVideoDataFormat(d); updateVideoSync(d); updateVideoSyncSource(d); @@ -3651,6 +3655,10 @@ RvPreferences::videoDataFormatChanged(int v) settings.setValue("dataFormat", v); settings.endGroup(); + // The user has set a new video data format which overrides the video + // data format specified on the command line if any + Rv::Options::sharedOptions().presentData=nullptr; + updateVideoSync(d); updateVideoSyncSource(d); updateVideoProfiles(d); @@ -3711,6 +3719,9 @@ RvPreferences::videoAudioCheckBoxChanged(int v) settings.beginGroup(QString::fromUtf8(str.str().c_str())); settings.setValue("useAsAudioDevice", checked); settings.endGroup(); + + // This user action overrides the presentAudio command line option if any + Rv::Options::sharedOptions().presentAudio=-1; } } diff --git a/src/lib/ip/IPBaseNodes/FileSourceIPNode.cpp b/src/lib/ip/IPBaseNodes/FileSourceIPNode.cpp index 6a5bc413..a61a3f58 100644 --- a/src/lib/ip/IPBaseNodes/FileSourceIPNode.cpp +++ b/src/lib/ip/IPBaseNodes/FileSourceIPNode.cpp @@ -634,14 +634,8 @@ namespace IPCore // e.g. propagateMediaChange() might occurs before those two. if( m_workItemID ) { - // We make a copy of workItemID because it can be clear - // before the lamda is finished. - // It is used by the graph to indicate the start and end loading - // of a graph. - int workItemID = m_workItemID; addDispatchJob( Application::instance()->dispatchToMainThread( - [this, sharedMedia, proxySharedMedia, - workItemID]( Application::DispatchID dispatchID ) + [this, sharedMedia, proxySharedMedia]( Application::DispatchID dispatchID ) { { LockGuard dispatchGuard( m_dispatchIDCancelRequestedMutex ); @@ -2756,13 +2750,54 @@ namespace IPCore } mov = openProxyMovie( errMsg.str(), 0.0, filename, defaultFPS ); - setMediaActive( false ); ostringstream str; str << name() << ";;" << file << ";;" << mediaRepName(); - TwkApp::GenericStringEvent event( "source-media-unavailable", graph(), - str.str() ); - graph()->sendEvent( event ); + TwkApp::GenericStringEvent event( "source-media-unavailable", graph(), str.str() ); + + // The following instructions can only be executed on the main thread. + // Dispatch to main thread only when using async loading. + if (!m_workItemID) + { + // We are not using async loading: we can safely execute the following instructions + setMediaActive( false ); + graph()->sendEvent( event ); + } + else + { + // We are using async loading: Dispatch to main thread + addDispatchJob( Application::instance()->dispatchToMainThread( + [this, event]( Application::DispatchID dispatchID ) + { + { + LockGuard dispatchGuard( m_dispatchIDCancelRequestedMutex ); + + bool isCanceled = + ( m_dispatchIDCancelRequestedSet.count( dispatchID ) >= 1 ); + if( isCanceled ) + { + m_dispatchIDCancelRequestedSet.erase( dispatchID ); + return; + } + } + + setMediaActive( false ); + graph()->sendEvent( event ); + + { + LockGuard dispatchGuard( m_dispatchIDCancelRequestedMutex ); + bool isCanceled = + ( m_dispatchIDCancelRequestedSet.count( dispatchID ) >= 1 ); + if( isCanceled ) + { + m_dispatchIDCancelRequestedSet.erase( dispatchID ); + return; + } + } + + removeDispatchJob( dispatchID ); + } ) ); + } } SharedMediaPointer sharedMedia( diff --git a/src/plugins/rv-packages/otio_reader/annotation_hook.py b/src/plugins/rv-packages/otio_reader/annotation_hook.py index bc7668d9..f7ed89c1 100644 --- a/src/plugins/rv-packages/otio_reader/annotation_hook.py +++ b/src/plugins/rv-packages/otio_reader/annotation_hook.py @@ -46,7 +46,7 @@ def hook_function(in_timeline, argument_map=None) -> None: "join": 3, "cap": 2, "splat": 1, - "mode": 0 if layer.type.lower() == "color" else 1, + "mode": 0 if layer.type == "COLOR" else 1, }, ) @@ -67,11 +67,20 @@ def hook_function(in_timeline, argument_map=None) -> None: commands.newProperty(width_property, commands.FloatType, 1) global_width = 2 / 15 # 0.133333... + for point in layer.points: - commands.insertFloatProperty( - points_property, - [point.x * global_scale.x, point.y * global_scale.y], - ) - commands.insertFloatProperty( - width_property, [point.width * global_width] - ) + points = commands.getFloatProperty(points_property) + if ( + len(points) > 1 + and points[-1] == point.y * global_scale.y + and points[-2] == point.x * global_scale.x + ): + pass + else: + commands.insertFloatProperty( + points_property, + [point.x * global_scale.x, point.y * global_scale.y], + ) + commands.insertFloatProperty( + width_property, [point.width * global_width] + )