From f7b1f74da9db5e8753451c1cd188df6fbf5536c3 Mon Sep 17 00:00:00 2001 From: Julien Hery Date: Mon, 30 Mar 2026 18:02:13 -0400 Subject: [PATCH] Fix annotation export crash when viewed container is a Subset The annotations exporter accessed the playhead via session.viewed_container.playhead, which assumes the viewed container is always a Playlist. When media is loaded by a Python plugin (e.g. rdo_browser) that sets the viewer to a Subset, this crashes with "'Subset' object has no attribute 'playhead'" because the Subset class does not expose a playhead property. Replace all 5 call sites with self.current_playhead(), which is provided by PluginBase and returns the active playhead regardless of the viewed container type. --- .../annotations_exporter/annotations_exporter.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugin/python_plugins/annotations_exporter/annotations_exporter.py b/src/plugin/python_plugins/annotations_exporter/annotations_exporter.py index 2523e19a5..94b4fca43 100644 --- a/src/plugin/python_plugins/annotations_exporter/annotations_exporter.py +++ b/src/plugin/python_plugins/annotations_exporter/annotations_exporter.py @@ -159,7 +159,7 @@ def attribute_changed(self, attr, role): if attr == self.scope: if self.scope.value() in ["Current Media", "Current Frame"]: self.user_name.set_value( - self.connection.api.session.viewed_container.playhead.on_screen_media.name + self.current_playhead().on_screen_media.name ) elif self.scope.value() == "Current Playlist / Timeline": self.user_name.set_value( @@ -232,7 +232,7 @@ def do_export(self, scope, export_type, user_name, output_folder, file_type, res elif scope == "Current Media": self.export_media_annotations( - self.connection.api.session.viewed_container.playhead.on_screen_media + self.current_playhead().on_screen_media ) elif scope == "Current Playlist / Timeline": @@ -254,7 +254,7 @@ def do_export(self, scope, export_type, user_name, output_folder, file_type, res gp_file_path = self.__output_folder + "/greasePencil.xml" self.make_greaspencil_xml_file( gp_file_path, - self.connection.api.session.viewed_container.playhead.on_screen_media.media_source().rate.fps() + self.current_playhead().on_screen_media.media_source().rate.fps() ) # now we zip the folder final_name = shutil.make_archive(self.__output_folder + "/" + self.user_name.value(), 'zip', __tmp_folder) @@ -314,8 +314,8 @@ def export_frame(self, idx, frame, duration, bookmark, media): def export_bookmark_on_current_frame(self): - m = self.connection.api.session.viewed_container.playhead.on_screen_media - current_frame = self.connection.api.session.viewed_container.playhead.attributes['Media Logical Frame'].value() + m = self.current_playhead().on_screen_media + current_frame = self.current_playhead().attributes['Media Logical Frame'].value() bookmarks = m.ordered_bookmarks() bookmark = None for bm in bookmarks: