Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full screen events #2041

Open
wants to merge 65 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
bba92d1
Add full screen state management for media elements
ne0rrmatrix May 24, 2024
2aaa53e
Merge Main into FullScreenEvents
ne0rrmatrix Jun 16, 2024
6db6b06
fix merge bug
ne0rrmatrix Jun 16, 2024
17601c3
Enhance fullscreen event handling
ne0rrmatrix Jun 16, 2024
7669d0a
fix fullscreen event handling macios
ne0rrmatrix Jun 16, 2024
38c5834
Update comment for OnWindowsChanged event
ne0rrmatrix Jun 16, 2024
2783077
Merge branch 'CommunityToolkit:main' into FullScreenEvents
ne0rrmatrix Jun 17, 2024
47b6434
Merge branch 'CommunityToolkit:main' into FullScreenEvents
ne0rrmatrix Jun 24, 2024
5185222
Merge Main into FullScreenEvents
ne0rrmatrix Jul 11, 2024
8198c94
fix merge errror
ne0rrmatrix Jul 11, 2024
6d34192
Fix another merge error
ne0rrmatrix Jul 11, 2024
d7c12eb
Merge branch 'FullScreenEvents' of https://github.com/ne0rrmatrix/Mau…
ne0rrmatrix Jul 11, 2024
afa937f
Merge branch 'CommunityToolkit:main' into FullScreenEvents
ne0rrmatrix Jul 19, 2024
6c8b106
Refactor full-screen event handling
ne0rrmatrix Jul 19, 2024
697950d
Merge branch 'FullScreenEvents' of https://github.com/ne0rrmatrix/Mau…
ne0rrmatrix Jul 19, 2024
5706688
fix spacing issue
ne0rrmatrix Jul 19, 2024
201e54e
Refactor full-screen state handling
ne0rrmatrix Jul 19, 2024
4a12906
Centralize FullScreenEvents subscription
ne0rrmatrix Jul 19, 2024
3425c25
fix cosmetic issues
ne0rrmatrix Jul 19, 2024
7f75702
More Cosmetic Fixes
ne0rrmatrix Jul 19, 2024
8bfed07
Refactor full screen event handling
ne0rrmatrix Jul 19, 2024
58ffa61
Increase accessibility and refine directives
ne0rrmatrix Jul 19, 2024
1e65556
Refine visibility and structure of records
ne0rrmatrix Jul 19, 2024
4abb02c
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Jul 22, 2024
63bf581
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Jul 24, 2024
b43ccfa
Merge branch 'main' into FullScreenEvents
brminnick Jul 24, 2024
f1c1ae6
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Jul 25, 2024
f9a516c
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 2, 2024
fa8e9fb
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 3, 2024
fddb7f6
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 4, 2024
aa09b29
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 8, 2024
2f6c67e
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 9, 2024
de01200
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 9, 2024
ba378b9
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 10, 2024
69714db
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 16, 2024
6dba9bb
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 19, 2024
c3322fa
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 19, 2024
72bc9da
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Aug 22, 2024
279cd7f
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Sep 2, 2024
2bb21dd
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Sep 5, 2024
ebe0d60
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Sep 10, 2024
142544c
Merge branch 'CommunityToolkit:main' into FullScreenEvents
ne0rrmatrix Sep 11, 2024
112e7e5
Merge branch 'CommunityToolkit:main' into FullScreenEvents
ne0rrmatrix Sep 16, 2024
5ffabb7
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Sep 24, 2024
ee8868a
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Sep 27, 2024
1684f86
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 1, 2024
d1bebfd
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 10, 2024
1590fe1
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 15, 2024
a0e47d7
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 16, 2024
f585895
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 20, 2024
2a6f156
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Oct 31, 2024
2b35903
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Nov 5, 2024
b72c39e
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Nov 7, 2024
a5028d2
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Nov 11, 2024
9ce744b
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Nov 11, 2024
6f94766
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Dec 2, 2024
c841e3c
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Dec 12, 2024
33f44ba
Merge branch 'main' into FullScreenEvents
brminnick Dec 18, 2024
dfa7af1
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Dec 19, 2024
8bdb8a9
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Dec 20, 2024
692c286
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Dec 28, 2024
59e7e1c
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Jan 3, 2025
b26bb60
Fix Merge Confilicts
ne0rrmatrix Jan 20, 2025
94436e2
fix merge error
ne0rrmatrix Jan 20, 2025
77878ed
Merge branch 'main' into FullScreenEvents
ne0rrmatrix Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
MediaOpened="OnMediaOpened"
PositionChanged="OnPositionChanged"
StateChanged="OnStateChanged"
SeekCompleted="OnSeekCompleted"/>
SeekCompleted="OnSeekCompleted"
FullScreenStateChanged="MediaElement_FullScreenStateChanged"/>
<HorizontalStackLayout Grid.Row="1" Padding="0,0,0,15">
<Label HorizontalOptions="Center" x:DataType="toolkit:MediaElement">
<Label.Text>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.ComponentModel;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Primitives;
using CommunityToolkit.Maui.Sample.ViewModels.Views;
using CommunityToolkit.Maui.Views;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -30,6 +31,8 @@ public MediaElementPage(MediaElementViewModel viewModel, ILogger<MediaElementPag
MediaElement.PropertyChanged += MediaElement_PropertyChanged;
}

void MediaElement_FullScreenStateChanged(object? sender, FullScreenStateChangedEventArgs e) =>
logger.LogInformation("FullScreen State Changed. Old State: {PreviousState}, New State: {NewState}", e.PreviousState, e.NewState);
void MediaElement_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == MediaElement.DurationProperty.PropertyName)
Expand Down
17 changes: 17 additions & 0 deletions src/CommunityToolkit.Maui.MediaElement/Interfaces/IMediaElement.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Primitives;
using CommunityToolkit.Maui.Views;

namespace CommunityToolkit.Maui.Core;
Expand Down Expand Up @@ -34,6 +35,11 @@ public interface IMediaElement : IView, IAsynchronousMediaElementHandler
/// </summary>
MediaElementState CurrentState { get; }

/// <summary>
/// Gets the full screen state of the media element.
/// </summary>
MediaElementScreenState FullScreenState { get;}

/// <summary>
/// Gets the height (in pixels) of the loaded media in pixels.
/// </summary>
Expand Down Expand Up @@ -111,6 +117,11 @@ public interface IMediaElement : IView, IAsynchronousMediaElementHandler
/// </summary>
event EventHandler<MediaPositionChangedEventArgs> PositionChanged;

/// <summary>
/// Occurs when the <see cref="FullScreenState"/> changes.
/// </summary>
event EventHandler<FullScreenStateChangedEventArgs> FullScreenStateChanged;

/// <summary>
/// Occurs when the media has ended playing successfully.
/// </summary>
Expand Down Expand Up @@ -161,4 +172,10 @@ public interface IMediaElement : IView, IAsynchronousMediaElementHandler
/// </summary>
/// <param name="newState">The new state the <see cref="MediaElement"/> transitioned to.</param>
internal void CurrentStateChanged(MediaElementState newState);

/// <summary>
/// Triggers a <see cref="FullScreenState"/> change.
/// </summary>
/// <param name="newState"></param>
internal void FullScreenChanged(MediaElementScreenState newState);
}
38 changes: 38 additions & 0 deletions src/CommunityToolkit.Maui.MediaElement/MediaElement.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using CommunityToolkit.Maui.Converters;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Primitives;

namespace CommunityToolkit.Maui.Views;

Expand Down Expand Up @@ -31,6 +32,13 @@ public partial class MediaElement : View, IMediaElement, IDisposable
/// </summary>
public static readonly BindableProperty DurationProperty = durationPropertyKey.BindableProperty;

/// <summary>
/// Backing store for the <see cref="FullScreenState"/> property.
/// </summary>
public static readonly BindableProperty FullScreenProperty =
BindableProperty.Create(nameof(FullScreenState), typeof(MediaElementScreenState), typeof(MediaElement),
MediaElementScreenState.Default, propertyChanged: OnFullScreenPropertyChanged);

/// <summary>
/// Backing store for the <see cref="ShouldAutoPlay"/> property.
/// </summary>
Expand Down Expand Up @@ -155,6 +163,13 @@ public event EventHandler SeekCompleted
remove => eventManager.RemoveEventHandler(value);
}

/// <inheritdoc cref="IMediaElement.FullScreenStateChanged"/>
public event EventHandler<FullScreenStateChangedEventArgs> FullScreenStateChanged
{
add => eventManager.AddEventHandler(value);
remove => eventManager.RemoveEventHandler(value);
}

/// <inheritdoc cref="IMediaElement.StateChanged"/>
public event EventHandler<MediaStateChangedEventArgs> StateChanged
{
Expand Down Expand Up @@ -390,6 +405,15 @@ public MediaElementState CurrentState
private set => SetValue(CurrentStateProperty, value);
}

/// <summary>
/// Gets the full screen state of the media element.
/// </summary>
public MediaElementScreenState FullScreenState
{
get => (MediaElementScreenState)GetValue(FullScreenProperty);
private set => SetValue(FullScreenProperty, value);
}

TimeSpan IMediaElement.Position
{
get => (TimeSpan)GetValue(PositionProperty);
Expand Down Expand Up @@ -527,6 +551,15 @@ static void OnSourcePropertyChanged(BindableObject bindable, object oldValue, ob
static void OnSourcePropertyChanging(BindableObject bindable, object oldValue, object newValue) =>
((MediaElement)bindable).OnSourcePropertyChanging((MediaSource?)oldValue);

static void OnFullScreenPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var MediaElement = (MediaElement)bindable;
var previousState = (MediaElementScreenState)oldValue;
var newState = (MediaElementScreenState)newValue;

MediaElement.OnFullScreenChanged(new FullScreenStateChangedEventArgs(previousState, newState));
}

static void OnCurrentStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var mediaElement = (MediaElement)bindable;
Expand Down Expand Up @@ -630,12 +663,17 @@ void IMediaElement.SeekCompleted()

void IMediaElement.CurrentStateChanged(MediaElementState newState) => CurrentState = newState;

void IMediaElement.FullScreenChanged(MediaElementScreenState newState) => FullScreenState = newState;

void OnPositionChanged(MediaPositionChangedEventArgs mediaPositionChangedEventArgs) =>
eventManager.HandleEvent(this, mediaPositionChangedEventArgs, nameof(PositionChanged));

void OnStateChanged(MediaStateChangedEventArgs mediaStateChangedEventArgs) =>
eventManager.HandleEvent(this, mediaStateChangedEventArgs, nameof(StateChanged));

void OnFullScreenChanged(FullScreenStateChangedEventArgs fullScreenStateChangedEventArgs) =>
eventManager.HandleEvent(this, fullScreenStateChangedEventArgs, nameof(FullScreenStateChanged));

void OnPauseRequested() => eventManager.HandleEvent(this, EventArgs.Empty, nameof(PauseRequested));

void OnPlayRequested() => eventManager.HandleEvent(this, EventArgs.Empty, nameof(PlayRequested));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace CommunityToolkit.Maui.Primitives;

/// <summary>
/// Event data for when the full screen state of the media element has changed.
/// </summary>
public sealed class FullScreenStateChangedEventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="FullScreenStateChangedEventArgs"/> class.
/// </summary>
/// <param name="previousState"></param>
/// <param name="newState"></param>
public FullScreenStateChangedEventArgs(MediaElementScreenState previousState, MediaElementScreenState newState)
{
PreviousState = previousState;
NewState = newState;
}

/// <summary>
/// Gets the previous state that the <see cref="Core.IMediaElement"/> instance is transitioning from.
/// </summary>
public MediaElementScreenState PreviousState { get; }

/// <summary>
/// Gets the new state that the <see cref="Core.IMediaElement"/> instance is transitioning to.
/// </summary>
public MediaElementScreenState NewState { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace CommunityToolkit.Maui.Primitives;

/// <summary>
///
/// </summary>
public enum MediaElementScreenState
{
/// <summary>
/// Full screen.
/// </summary>
FullScreen,

/// <summary>
/// The default state.
/// </summary>
Default,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using AndroidX.CoordinatorLayout.Widget;
using AndroidX.Core.View;
using AndroidX.Media3.UI;
using CommunityToolkit.Maui.Primitives;
using CommunityToolkit.Maui.Views;

namespace CommunityToolkit.Maui.Core.Views;
Expand Down Expand Up @@ -120,12 +121,14 @@ void OnFullscreenButtonClick(object? sender, PlayerView.FullscreenButtonClickEve
isFullScreen = true;
RemoveView(relativeLayout);
layout?.AddView(relativeLayout);
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.Default, MediaElementScreenState.FullScreen));
}
else
{
isFullScreen = false;
layout?.RemoveView(relativeLayout);
AddView(relativeLayout);
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.FullScreen, MediaElementScreenState.Default));
}
// Hide/Show the SystemBars and Status bar
SetSystemBarsVisibility();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CommunityToolkit.Maui.Extensions;
using CommunityToolkit.Maui.Primitives;
using CommunityToolkit.Maui.Views;
using Microsoft.UI;
using Microsoft.UI.Windowing;
Expand Down Expand Up @@ -169,6 +170,7 @@ void OnFullScreenButtonClick(object sender, RoutedEventArgs e)
var parent = mediaPlayerElement.Parent as FrameworkElement;
mediaPlayerElement.Width = parent?.Width ?? mediaPlayerElement.Width;
mediaPlayerElement.Height = parent?.Height ?? mediaPlayerElement.Height;
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.FullScreen, MediaElementScreenState.Default));
}
else
{
Expand Down Expand Up @@ -197,6 +199,7 @@ void OnFullScreenButtonClick(object sender, RoutedEventArgs e)
{
popup.IsOpen = true;
}
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.Default, MediaElementScreenState.FullScreen));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AVFoundation;
using AVKit;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Primitives;
using CommunityToolkit.Maui.Views;
using CoreFoundation;
using CoreGraphics;
Expand Down Expand Up @@ -95,7 +96,8 @@ public partial class MediaManager : IDisposable
Player = new();
PlayerViewController = new()
{
Player = Player
Player = Player,
Delegate = new MediaManagerDelegate()
};
// Pre-initialize Volume and Muted properties to the player object
Player.Muted = MediaElement.ShouldMute;
Expand Down Expand Up @@ -718,4 +720,16 @@ void RateChanged(object? sender, NSNotificationEventArgs args)
}
}
}
}

sealed class MediaManagerDelegate : AVPlayerViewControllerDelegate
{
public override void WillBeginFullScreenPresentation(AVPlayerViewController playerViewController, IUIViewControllerTransitionCoordinator coordinator)
{
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.Default, MediaElementScreenState.FullScreen));
}
public override void WillEndFullScreenPresentation(AVPlayerViewController playerViewController, IUIViewControllerTransitionCoordinator coordinator)
{
MediaManager.FullScreenEvents.OnWindowsChanged(new FullScreenStateChangedEventArgs(MediaElementScreenState.FullScreen, MediaElementScreenState.Default));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#if !(ANDROID || IOS || WINDOWS || MACCATALYST || TIZEN)
// NOTE: PR shares code with #1918 https://github.com/CommunityToolkit/Maui/pull/1918
#if !(ANDROID || IOS || WINDOWS || MACCATALYST || TIZEN)
global using PlatformMediaElement = System.Object;
#elif ANDROID
global using PlatformMediaElement = AndroidX.Media3.ExoPlayer.IExoPlayer;
Expand All @@ -10,6 +11,7 @@
global using PlatformMediaElement = CommunityToolkit.Maui.Core.Views.TizenPlayer;
#endif

using CommunityToolkit.Maui.Primitives;
using Microsoft.Extensions.Logging;

namespace CommunityToolkit.Maui.Core.Views;
Expand All @@ -36,6 +38,40 @@ public MediaManager(IMauiContext context, IMediaElement mediaElement, IDispatche
MediaElement = mediaElement;

Logger = MauiContext.Services.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(MediaManager));
FullScreenEvents.WindowsChanged += OnFullScreenStatusChanged;
}

/// <summary>
/// An event that is raised when the full screen state of the media element has changed.
/// </summary>
internal readonly record struct FullScreenEvents()
{
/// <summary>
/// An event that is raised when the full screen state of the media element has changed.
/// </summary>
public static event EventHandler<FullScreenStateChangedEventArgs>? WindowsChanged;
/// <summary>
/// An event that is raised when the full screen state of the media element has changed.
/// </summary>
/// <param name="e"></param>
public static void OnWindowsChanged(FullScreenStateChangedEventArgs e) => WindowsChanged?.Invoke(null, e);
}

/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void OnFullScreenStatusChanged(object? sender, FullScreenStateChangedEventArgs e)
{
if (MediaElement is not null)
{
MediaElement.FullScreenChanged(e.NewState);
}
else
{
Logger?.LogWarning("MediaElement is null");
}
}

/// <summary>
Expand Down
Loading