Media File Activation#
Screenbox supports two distinct activation paths for opening media files: in-app activation (file picker, library browsing, drag-and-drop) and external file association activation (double-clicking a file in File Explorer). Both paths converge on the same message-driven queue pipeline but differ in their entry point, timing constraints, and the extra metadata attached to the activation.
Activation Entry Points#
External File Association (File Explorer / OS shell)#
When a file is opened externally, the OS invokes App.OnFileActivated. The override:
- Records a Sentry breadcrumb with
PreviousExecutionState. - Initialises or reuses the root frame and navigates to
MainPageif needed . - Sends a
PlayFilesMessagecarrying bothargs.Filesandargs.NeighboringFilesQueryβ the shell-supplied query that lets the player enumerate sibling files in the same folder .
Multi-instance handling runs before OnFileActivated in Program.Main. When the UseMultipleInstances setting is on and the activation kind is File, a new app instance is registered; otherwise the activation is redirected to an existing instance . Xbox always reuses a single instance .
Important:
OnFileActivateddoes not callLibVLCSharp.Shared.Core.Initialize()β that only happens inOnLaunched. For externally activated instances, LibVLC is already initialized because the instance was either new (launch precedes activation) or redirected to a running one.
In-App Activation#
In-app file opens send a PlayMediaMessage (for single items, URIs, or existing queue items) or a PlayFilesMessage (for multi-file selections). Examples:
- File picker (
CommonViewModel.OpenFilesAsync): picks files then sendsPlayMediaMessage(files). - Drag-and-drop (
PlayerPageViewModel.OnDropAsync): sendsPlayFilesMessage(items)for storage items, orPlayMediaMessage(uri)for web links .
Queue Pipeline and Timing#
PlayQueueCoordinator is the sole handler for both message types.
PlayFilesMessage β ProcessPlayFilesAsync#
Receive(PlayFilesMessage) immediately calls ProcessPlayFilesAsync. If MediaPlayer is null at the time of receipt (a race that can occur on first external launch before the player view is ready), the message is stored in _delayPlay and replayed when the player becomes available .
ProcessPlayFilesAsync follows a two-phase approach:
- Immediate playback:
ParseAndPlayAsynccreates aMediaViewModel, starts playback, then parses the full media list (useful when the file is a playlist) . - Neighboring-file enqueue: If exactly one file was opened and
EnqueueAllFilesInFolderis enabled, sibling files are fetched and added to the queue. When the shell providedNeighboringFilesQuery, that is used directly; otherwise one is obtained viaIFilesService.GetNeighboringFilesQueryAsync.
PlayMediaMessage β ParseAndPlayAsync#
Receive(PlayMediaMessage) either plays an item already in the queue (Existing: true) or clears the queue and calls ParseAndPlayAsync. The same deferred-player guard applies here .
MediaViewModel Lifecycle#
A MediaViewModel wraps a StorageFile, Uri, or Media object. The PlaybackItem it exposes is a Lazy<T> β it is not created until first access, which happens when the coordinator assigns it to MediaPlayer.PlaybackItem .
After QueueCurrentItemChangedMessage is broadcast, PlayerPageViewModel fires two async loads:
LoadDetailsAsyncβ readsMusicProperties/VideoPropertiesfrom theStorageFileand optionally enriches from LibVLC metadata once the media is parsed .LoadThumbnailAsyncβ loads artwork then updates theThumbnailproperty .
Thumbnail / Cover Art Extraction#
LoadThumbnailAsync tries two sources in order:
-
Tag-embedded cover art (
GetCoverFromTagAsync): Opens the file stream, reads via TagLib# (ReadStyle.PictureLazy), and prefersFrontCoverorMediapicture types. All exceptions (FileNotFoundException,UnsupportedFormatException,CorruptFileException) are silently swallowed; the method returnsnullon any failure . -
Shell thumbnail (
GetStorageFileThumbnailAsync): Falls back toStorageFile.GetThumbnailAsync(ThumbnailMode.SingleItem). OnlyThumbnailType.Imageresults are used. Exceptions (e.g.0x8000000Aβ data not yet available;0x800706BAβ RPC server unavailable) are silently swallowed . -
LibVLC ArtworkURL: If the source is not a
StorageFileand thePlaybackItemhas been created with a parsedMedia, theMetadataType.ArtworkURLvalue is used to construct aBitmapImagedirectly .
If all three sources fail, Thumbnail stays null β no error is surfaced to the user. Callers should treat a null thumbnail as normal. Thumbnail bitmaps are stored as WeakReference<BitmapImage> to allow GC under memory pressure .
The coordinator also maintains a thumbnail pre-buffer: UpdateMediaBufferAsync is called whenever the current item changes and pre-loads thumbnails for items adjacent to the current position, releasing thumbnails for items that scroll out of the buffer window.
Media Load Failure Handling#
Failures during PlaybackItem creation send a MediaLoadFailedNotificationMessage with a Reason and Path . NotificationViewModel.Receive formats these into an in-app error toast . On playback start, OnMediaFailed marks the current item IsAvailable = false . If loading succeeds and playback begins, IsAvailable is flipped back to true .