Skip to content

Media panel scroll features.#280

Closed
kenmcgaugh wants to merge 27 commits into
AcademySoftwareFoundation:developfrom
kenmcgaugh:scroll_features
Closed

Media panel scroll features.#280
kenmcgaugh wants to merge 27 commits into
AcademySoftwareFoundation:developfrom
kenmcgaugh:scroll_features

Conversation

@kenmcgaugh

Copy link
Copy Markdown
Contributor

This adds a feature to the media panels such that they now remember their scroll position for each container.

This also adds a 'F' hotkey for "framing" on the selected media.

MrFruitDude and others added 27 commits May 20, 2026 18:48
…ySoftwareFoundation#244)

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.
…tion#247)

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ken McGaugh <ken@wetafx.co.nz>
New self-contained viewport overlay plugin that displays annotations from
neighboring frames as semi-transparent, color-tinted overlays on the
current frame. Enables reviewers and animators to see annotation
progression across frames without scrubbing.

Architecture:
- HUDPluginBase subclass with configurable frames before/after, opacity
  falloff, and separate past/future tint colours
- Opacity and tint baked directly into copied Canvas items (strokes,
  captions, shapes), rendered via standard render_canvas() path
- Stack order 1.5 (below current annotations at 2.0, above image)
- Plugin-local bookmark cache built from frame.bookmarks() during
  playback — zero core data structure changes
- Canvas accessed via public AnnotationBase::user_data() API, no
  dependency on annotations plugin internals

Also adds set_opacity()/set_colour() setters to Stroke, matching the
pattern already established by Caption.

Signed-off-by: Julien Hery <jhery@rodeofx.com>
Co-Authored-By: Nicolas Felix <nfelix@rodeofx.com>
* Add numpy to pip installed packages

Signed-off-by: Ted Waine <ted.waine@gmail.com>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Tweak for set video range action

Signed-off-by: Ted Waine <ted.waine@gmail.com>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Handle missing Decklink hardware when drivers are installed (AcademySoftwareFoundation#238)

Signed-off-by: xShirae <xshiraayuki@gmail.com>
Signed-off-by: Ted Waine <ted.waine@gmail.com>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Initial checkin of filesystem_plugin prior to refactor.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* A ffmpeg constant changed, I believe the older one FF_PROFILE_UNKOWN has been obsolete for a while.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Cleanup GUI
Better filtering, got progress bar working, and version and date filtering.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding fileseq for the python libraries for the FileSystem Browser.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Got the progress bar to work correctly.
Also added a separate timing test where you can specify an output directory, not really for unit testing, but good for testing against real directories.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Fix for color scheme for right click menu.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Add readme.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding copyright/license info.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding (c).

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Dont be quite so agressive updating the UI, only do it every 5 secs or so.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Swapped file-browser with a history view.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Updated readme.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Fixing QML issue.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Demo of widget as a floating window.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Filtering fixes.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Switched to a tree-view with some "smart" collapsing of directories.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Fixed the file-loading issue, it was trying to load a relative path.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Double clicking on a directory changes the overall search window path.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Make the search case insensitive.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding different types of tree view. and recursion depths.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Minor tweak to prune empty folders if we are filtering.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding a directory view.

The directory view allows a more obvious browsing of the tree. For the very top of the directory tree we dont auto-scan for media, once you get down to 4 levels it will start scanning.
We have also made a config.json file to store configurations of things like the auto_scan_threashold, along with adding a list of folders that need to be ignored.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Filtering all the time.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* GUI update:
   * Fixed auto-complete
   * Tree view opens to node when path is entered in path dialog.
   * Added a refresh button
   * Tree view now persistent, with a nicer sidebar label.
   * Smart scan button now visible.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Added a preview mode, so when you click on a clip, it will automatically load it into the player
   * double click will load it into your target
   * Cursor keys will allow you to move through the results loading as you go (left right for icon view, up down for list view)
   * Enter will do the same as double click.
   * Preview playlist will be deleted on Enter.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Updated to have a common style, and synced style with xstudio.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* More style fixes, and also making menu options consistent between icon and list view:
* Adding Append menu option
* Adding copy path menu option
* Add compare menu option

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Adding a show-in-finder menu option.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* MInor bug fixes, cleaning threading.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Some code refactoring to simplify it, in particular the dispatch table.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Setup a interface class, so that if you want to change the back end you have a centralized area to do that.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Removed some debug output and removed an un-necesary header.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Fixed a padding issue.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

* Added ability to set the directory root.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

---------

Signed-off-by: Ted Waine <ted.waine@gmail.com>
Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: xShirae <xshiraayuki@gmail.com>
Signed-off-by: tedwaine <59868698+tedwaine@users.noreply.github.com>
Co-authored-by: Ted Waine <ted.waine@gmail.com>
Co-authored-by: xShirae <83482842+xShirae@users.noreply.github.com>
Co-authored-by: tedwaine <59868698+tedwaine@users.noreply.github.com>
…s, cross-platform docs (AcademySoftwareFoundation#246)

* Build system improvements: OTIO vcpkg migration, Windows fixes, cross-platform docs

Core build system
-----------------
- Migrate OpenTimelineIO from git submodule to vcpkg overlay port
  (cmake/vcpkg_overlay_ports/opentimelineio/). Removes extern/otio,
  .gitmodules, cmake/otio_patch.diff, and the OTIO_SUBMODULE option.
- OTIO portfile: on Windows, move .dll files from lib/ to bin/ (vcpkg
  convention for applocal.ps1 discovery) and rewrite generated
  Targets-*.cmake files so IMPORTED_LOCATION resolves correctly.
- Pin python3 to 3.11.11 in vcpkg.json.
- Lower CMake minimum from 3.28 to 3.26 for broader distro compatibility.
- Work around Qt 6.5/6.8 FindWrapOpenGL.cmake AGL bug on macOS by
  pre-creating WrapOpenGL::WrapOpenGL so Qt's find-module early-returns.
  Fixed upstream in Qt 6.9+; workaround can be removed once minimum
  supported Qt >= 6.9.

CMakePresets
------------
- Remove hardcoded Qt6_DIR from the default preset. Users now supply it
  via the Qt6_DIR environment variable, a CMakeUserPresets.json, or a
  one-off -D flag (documented in each build guide).
- Add VCPKG_OVERLAY_PORTS path so the new OTIO overlay is picked up.
- Add Ninja generator presets for macOS (arm / intel) and Linux — Release,
  RelWithDebInfo and Debug variants. Aligns with existing Windows Ninja
  presets.
- Un-hide WinDebug preset.
- Add VCPKG_OVERLAY_TRIPLETS to the Linux base preset.

Windows build fixes
-------------------
- Fix scripts/qt_install to use install(SCRIPT) + configure_file instead
  of install(CODE), so ${CMAKE_INSTALL_PREFIX} resolves at install time.
  Previously the configure-time prefix was baked in, which broke the
  CPack package target because CPack uses a different (staging) prefix.
- Remove the redundant early windeployqt call in src/launch/xstudio/src.
  The late call in scripts/qt_install now covers everything and runs
  after all other install rules have populated the install tree.
- In cmake/macros.cmake (default_options_qt), add RUNTIME_OUTPUT_DIRECTORY
  alongside LIBRARY_OUTPUT_DIRECTORY so *_qml.dll files land in build/bin
  on Windows (Windows uses RUNTIME for .dll, not LIBRARY).
- Fix Windows python install path mismatch in python/CMakeLists.txt:
  the build produces lib/python3.11/site-packages (Unix layout, because
  vcpkg's Python uses that layout on Windows), not Lib/site-packages.

Dev workflow
------------
- Generate build/run_xstudio.bat — a dev launcher that puts Qt's bin
  directory on PATH and forwards arguments to xstudio.exe, so xstudio
  can be run straight from the build tree without a windeployqt pass.

Documentation
-------------
- downloading_qt.md: add aqtinstall instructions (command-line, no Qt
  account required) as a recommended alternative to the GUI installer.
  Covers Linux, macOS and Windows.
- index.rst: add "Choosing a guide" section explaining the split between
  vcpkg-based guides (recommended) and distro-native guides (advanced).
- linux_generic.md: restructured around the new Qt6_DIR / user-preset
  workflow, removed submodule instructions, added optional Ninja section.
- macos.md: minor updates to reflect current dependency list and Qt
  workaround now handled in CMakeLists.txt.
- windows.md: full rewrite — unified "Set up the build environment"
  section using Enter-VsDevShell with -SkipAutomaticLocation, separate
  build sections for Visual Studio and Ninja generators, corrected Qt
  path example (C:/Qt not C:/Qt6), user-preset examples for both
  generators, note on run_xstudio.bat dev launcher.

Signed-off-by: Olaf Razzoli <olaf.razzoli@gmail.com>

* docs: simplify build guides and pin vcpkg

- Require Ninja as the CMake generator on all platforms; remove the
  "Faster builds with Ninja (optional)" sections and the Visual Studio
  generator option on Windows.
- Pin vcpkg to commit c2aeddd80357b17592e59ad965d2adf65a19b22f in all
  three guides for reproducible dependency builds.
- Document CMakeUserPresets.json as the single way to point CMake at
  the local Qt 6.5.3 install; drop the Qt6_DIR env-var and one-off
  -DQt6_DIR command-line paths.
- Note that --target package on Windows is slow and recommend a plain
  cmake --build build for dev iteration.
- Remove docs/reference/build_guides/developer_tips.md and the link
  to it from windows.md.

Signed-off-by: Olaf Razzoli <olaf.razzoli@gmail.com>

---------

Signed-off-by: Olaf Razzoli <olaf.razzoli@gmail.com>
* Merge updates from DNEG internal repo

Signed-off-by: Ted Waine <ted.waine@gmail.com>

* Re-sync to DNEG internal repo

Signed-off-by: Ted Waine <ted.waine@gmail.com>

* Win build compatibility tweaks

Signed-off-by: Ted Waine <ted.waine@gmail.com>

* Update docs and release notes

Signed-off-by: Ted Waine <ted.waine@gmail.com>

---------

Signed-off-by: Ted Waine <ted.waine@gmail.com>
…Foundation#257)

* Fix Windows file-URL handling in pathFromURL and Reveal Source

pathFromURL on Windows returned url.toString() - the full file URL
string with scheme, authority and URL-encoded reserved characters.
That string then flowed unchanged through every QML caller to
user-visible text (window title, clipboard, dialog text fields) and
to external process arguments (ffmpeg), producing artefacts like
"file:///Z:/path/foo.xst" in the window title and ffmpeg output
filenames such as "file:///Z:/foo.%23%23%23%23.%04d.jpg".

Replace the pathFromURL Windows branch with a delegation to
QUrl::toLocalFile() after patching the one URL shape Qt can't handle
on its own: xstudio constructs URLs as file://localhost//<drive>:/...,
which toLocalFile() interprets as a UNC \\localhost\<drive>:\... path.
Strip the localhost authority and collapse the doubled leading slash;
Qt's conversion then yields a clean drive-letter path. Standard file
URLs and real UNC URLs are handled by toLocalFile() unchanged.

Implement the previously-empty Windows branch of showURIS using
explorer.exe /select,<native-path>, calling pathFromURL to obtain the
clean drive-letter path. explorer.exe /select takes a single target
per invocation (unlike macOS open -R and Linux ShowItems, which
accept a list), so the Windows branch reveals only the first URL in
the input.

The pathFromURL non-Windows branch (`return url.path().replace("//",
"/")`) is unchanged; Linux and macOS behaviour is preserved.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>

* VideoRendererDialog: handle user-typed hash pattern in choose_output

choose_output had three intended branches over the regex matches:

  - filename contains a numeric frame range (foo.0001.jpg): replace
    digits with #### and set audio output to <prefix>.aiff
  - filename has neither a frame number nor hashes (foo.jpg): inject
    #### and set audio output to <prefix>.aiff
  - filename already contains hashes (foo.####.jpg): no branch

The third case had no handler. Previously this was masked because Qt
URL-encoded the # characters to %23 when serializing the file dialog
URL, and the with_hashes regex matched the literal # character only.
The encoded form failed the regex, the third branch was indistin-
guishable from the second, and audio output auto-filled by accident
via the !with_hashes branch.

With the previous commit applying QUrl::toLocalFile() in pathFromURL
the path is fully decoded before the regex runs, with_hashes
correctly matches the literal ####, and the missing case surfaces as
audio output not auto-filling when the user types ####. Add the
explicit `else if (with_hashes)` branch: keep the path as the user
wrote it and set the audio filename via the same ext[1] + "aiff"
prefix used by the other two branches.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>

---------

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…ation#258)

Windows clones with the default core.autocrlf=true convert .patch
files to CRLF on checkout. git apply (used by vcpkg overlay ports)
rejects CRLF in diff hunk headers ("corrupt patch at line N"),
breaking vcpkg builds. Forcing eol=lf on *.patch and *.diff makes
the working-tree files LF regardless of host autocrlf setting,
so the patch step works on every platform without per-developer
git config.

See hydralab issue AcademySoftwareFoundation#36.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
… from FF_PROFILE_UNKNOWN to AV_PROFILE_UNKNOWN (AcademySoftwareFoundation#263)

(cherry picked from commit 31c30bc202d2af31bfdf11b0e4ffe2fd9c4f29da)

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…demySoftwareFoundation#259)

run_xstudio.bat now sets PATH, XSTUDIO_ROOT, XSTUDIO_PLUGIN_PATH,
XSTUDIO_PYTHONHOME and PYTHONPATH so xstudio.exe launches from the
build tree without a fresh `cmake --install`. Required follow-on
fixes to the build-tree staging of several resources:

- cmake/macros.cmake: stage preferences to bin/preference on Windows
  (was share/xstudio/preference). Removes the Win32 special case so
  Windows now matches Linux, which already staged there.

- src/embedded_python/src/embedded_python.cpp: Windows now honors an
  optional XSTUDIO_PYTHONHOME env var, overriding the install-layout-
  derived path (xstudio_root/../../bin/python3) which is wrong when
  XSTUDIO_ROOT points at the build tree. Unset = previous behavior.

- python/CMakeLists.txt: Windows uses `cmake -E copy_directory` to
  merge the source xstudio package with the .pyd in site-packages.
  `setup.py install --prefix=C:/...` mangles forward-slash absolute
  paths on Windows (drive letter dropped, rest treated as relative
  to CWD), leaving site-packages with only the .pyd. New elseif(WIN32)
  branch; the Linux else() block is the same as before.

- extern/quickfuture: add RUNTIME_OUTPUT_DIRECTORY so quickfuture.dll
  lands next to its qmldir at build time. LIBRARY_OUTPUT_DIRECTORY
  only controls the .lib on Windows; the DLL was going to
  extern/quickfuture/ where Qt couldn't find it when loading the QML
  module. RUNTIME_OUTPUT_DIRECTORY is a no-op for Linux shared libs.

- extern/quickpromise: same DLL-next-to-qmldir fix, Win32-gated.

All changes are Win32-gated or default to the old behavior when the
new env var is unset. Linux and macOS builds unchanged. Install and
package behavior unchanged.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…SoftwareFoundation#260)

In default_plugin_options, make_directory share/xstudio/plugin before
copying the plugin DLL into it. Under parallel builds the copy step
can race and create share/xstudio/plugin as a file, after which every
later QML copy_directory under it fails and the build aborts.

In python/CMakeLists.txt, restore the two Windows install rules that
put the xstudio Python module into the installer: one installs the
merged build-tree site-packages/xstudio under bin/python3, the other
installs the source .py tree under python/xstudio. Without either,
the NSIS installer only bundled __pybind_xstudio.pyd in core/,
missing __init__.py and every other submodule.

Both rules existed at v1.2.0; dropped in 8e36d12.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…ftwareFoundation#264)

Register get_annotation_atom, annotation_data_atom and
build_annotation_atom in py_atoms.cpp. Add three accessors to
Bookmark: has_annotation (bool property), annotation_data (read-only
serialise-based property returning the canvas dict), and
set_annotation() which constructs a JsonStore payload and sends it
via add_annotation_atom. Bypasses the AnnotationsCore undo stack
intentionally, which is correct for sync/remote-write use cases.


(cherry picked from commit 964d1e294374b0bed9df8881b3a205b16513100b)

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
Signed-off-by: Ted Waine <ted.waine@gmail.com>
…dation#267)

Add it to not_sequence_ext_set. Maya writes lowercase .webm files.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
* Use platform-aware process liveness check for remote session files

/proc/<pid> is Linux-only, so on Windows and macOS every session file looked dead and got deleted. Use OpenProcess on Windows, kill(pid, 0) on macOS, /proc unchanged on Linux.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>

* Bump try_reuse_session connect timeout to 3s

CAF's BASP loopback handshake takes ~2030 ms on my test systems; the 2s budget was always missed. I hope an extra second is ok.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>

---------

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…ademySoftwareFoundation#269)

caf::make_uri accepts "Z:/foo" as scheme=Z (RFC 3986: single ALPHA is a valid scheme), then uri_to_posix_path drops the drive. On Windows, require "://" before treating it as a URI. Non-Windows behavior unchanged.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
* Create playlist if its not there.
Wrapped inspected_container in a try/except — it raises RuntimeError: invalid_argument on an empty session rather than returning None, so the if not target_playlist: create-playlist branch was never reached.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
(cherry picked from commit 5ff490a0ad77db737c79b8a90361b149dcaa3a6a)

* Fix for missing variable...

Changed playlist.playhead.playing = True → target_playlist.playhead.playing = True on the last line — playlist was an undefined name that would have thrown a NameError on any successful load.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
(cherry picked from commit 15f596c4e53cf21b017f257b132372f62750d4a7)

* Support for adding media to timelines.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
(cherry picked from commit efa65fd01acec0970f6e8f30c70a2f79711ad9ff)

* Need to grab the right parameter.

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>

---------

Signed-off-by: Sam.Richards@taurich.org <Sam.Richards@taurich.org>
…SoftwareFoundation#274)

The Mac (__OPENGL_4_1__) path assigned the glMapBuffer result to
mapped_address_, so the cache check at the top of map_buffer_for_upload
(if (!resize(buffer_size) && mapped_address_) return mapped_address_;)
short-circuited on subsequent calls. The non-Mac path returned the
glMapNamedBuffer result directly without storing it, so mapped_address_
stayed null and the check never fired. Every prepare-for-upload re-ran
glNamedBufferData + glMapNamedBuffer on the same PBO.

NVIDIA accepts this re-orphan-and-map pattern. Intel doesn't: the remap
returns NULL once the buffer has been used as a GL_PIXEL_UNPACK_BUFFER
source, which logs 'Failed to map buffer for frame' during normal
playback.

Fix: assign the map result to mapped_address_ so the cache check fires.
Clear it after glUnmapNamedBuffer in __bind, and after the buffer
deletion in resize(), so we don't return a stale pointer.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…reFoundation#272)

The leftover-options check came from fftools/ffprobe.c (~line 3890),
where it's a `while av_dict_iterate` loop that logs a warning for each
option the demuxer didn't consume. Reasonable in a CLI: tell the user
the `-foo` they typed didn't apply.

The port turned that warning into a throw, and kept a stale error
string ("Option scan_all_pmts not found") that doesn't describe what's
actually being detected.

It only stays quiet for mov/mp4 because xstudio seeds `export_all=1`
above, and the mov demuxer consumes it. Matroska/webm doesn't know
the option, leaves it in the dict, the throw fires, the catch resets
the result, and probe_file returns {} — so webm media shows no codec,
resolution, etc. in the media view.

This check is not needed.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
…tion#273)

Fixes HTTP source playback on Windows. scan_posix_path already has an
http handler in its trailing else branch, but on Windows it was
unreachable: fs::is_directory(p) for a string like
"http://host/path.mov" raises std::filesystem_error ("The specified
path is invalid"), the outer catch swallows it, and the function
returns an empty vector — the caller sees no media.

Linux behaves differently. POSIX stat() doesn't reject URL strings as
syntactically invalid; it just returns ENOENT. The throwing
fs::is_directory translates that into "return false, don't throw", so
execution falls through to the http handler. That's why the bug never
showed up there.

Switch both fs::is_directory(p) and fs::is_regular_file(p) to the
noexcept (path, error_code) overloads. They do the same syscall but
report errors through error_code instead of throwing — so on Windows
they return false for a URL string and execution reaches the http
handler, matching Linux. The error_code is intentionally unread: we
only care that the path isn't a local file or directory.

Safe on Linux because the new overloads share their implementation
with the throwing form — they're just a different way of surfacing
the same result. Real filesystem paths continue to be classified
identically.

Signed-off-by: Ben de Luca <bdeluca@gmail.com>
* Added ".mxf" as a media file extension.

Changed the Filesystem Browser hotkey from "B" to "Meta+B" as it was clashing with the the existing "B" hotkey to view the blue channel.

When no playlist exists, a "File System Import" playlist was being created and viewed, but not inspected. Added a change to also make it the inspected playlist.

Reworked the UI instantiation logic to leverage the built-in xstudio panel API. This fixed the broken hotkey, which required adding a button to the action bar as well.

Removed the "Plugins|Browser Open" menu as the new action bar button does the same thing.

Removed the "View|Panels" menu as it just wasn't working and it was redundant.

Reworked the drag-and-drop to allow it to work from the pop-out window version of the browser the same way it works from the embedded panel version. Previously it just didn't work in the pop-out window.

Modified the preview logic to prevent from being triggered excessively.

Changing any of the filter settings causes a refresh of the current path. This provides both immediate results for any media directly within the current path, and also resets the deep-scan so it can be manually triggered again. Previously there was no easy way to force a refresh when changing the filter settings (that I could see).

Fixed a couple of error messages.

Fixed a focus issue when tripple-clicking in the path field to select the whole text.

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ken McGaugh <ken@wetafx.co.nz>

* Added missing "import traceback".

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ken McGaugh <ken@wetafx.co.nz>

* Currently, the following produces two media items with the same content but with vastly different names:

    mypath = "/path/to/media.mov"
    m1 = myplaylist.add_media(mypath)
    m2 = myplaylist.add_media(URI(mypath))

The m1 media item will have the name "/path/to/media.mov" whereas the m2 media item will have the name "media".

This discrepancy comes up with the new filesystem browser when adding media via drag-n-drop vs. double clicking.

The fix here is to make it so that the first method procuces the shorter name matching the second method.

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ken McGaugh <ken@wetafx.co.nz>

---------

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ken McGaugh <ken@wetafx.co.nz>
…r selection menus. Previously the list of available colours was hard-coded in multiple locations. Now the list of colours are all taken from the "/core/session/media_flags" preference which already exists but was unused. (AcademySoftwareFoundation#275)

Additionally, this adds hotkeys for directly setting the flag colour on selected media items in the media panel. The hotkeys are Ctrl+Alt+<number>.

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Annotations now create the associated note with the subject text the same as when notes are created by other means (ie. the '; hotkey or from within the notes viewer).

When annotating, holding down the shift key now forwards es all mouse events to the viewport so frames can be scrubbed without leaving annotation mode.

When leaving annotation mode, if the active tool is Laser then it will remain active so that it can be used without the annotation widget being visible. I find this very useful when working in full-screen presentation mode. To disable this you need to activate the annotation widget and switch to any tool other than Laser.

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
Signed-off-by: Ted Waine <ted.waine@gmail.com>
This adds a feature to the media panels such that they now remember their scroll position for each container.

This also adds a 'F' hotkey for "framing" on the selected media.

Signed-off-by: Ken McGaugh <ken@mcgaugh.co.uk>
@tedwaine tedwaine force-pushed the develop branch 2 times, most recently from 80fa446 to e0c88d1 Compare June 22, 2026 13:48
@tedwaine

Copy link
Copy Markdown
Collaborator

This commit is going in via a new PR as the history got changed on destination (develop) branch

#290

@tedwaine tedwaine closed this Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants