Winui media player element PlayToEnd()

Fernand Delavy 20 Reputation points
2023-03-03T14:55:32.03+00:00

Sorry for my bal english !

On Microsoft store i have an app Horloge parlante, it is an UWP app works only if langage French is installed on Windows 10 / 11

I try to build a new one with Winui Desktop Micorosft.WindowsAppsSDK

the problem is mediaPlayer PalyToEnd().

On the UWP I have this to do the job : mediaplayer wait until play sound ends.

<

 for (int i = 0; i < x; i++)
                {
                    await son.PlayToEndAsync(uri);
                }

public static class MediaElementExtensions
    {
        public static async Task<MediaElement> PlayToEndAsync(this MediaElement mediaElement, Uri source)
        {
            mediaElement.Source = source;
            return await mediaElement.WaitToCompleteAsync();
        }

        /*********************************************************************/

        public static async Task<MediaElement> WaitToCompleteAsync(this MediaElement mediaElement)
        {
            var tcs = new TaskCompletionSource<MediaElement>();
            RoutedEventHandler reh = null;
            reh = (s, e) =>
            {
                if (mediaElement.CurrentState == MediaElementState.Buffering ||
                    mediaElement.CurrentState == MediaElementState.Opening ||
                    mediaElement.CurrentState == MediaElementState.Playing)
                {
                    return;
                }
                mediaElement.CurrentStateChanged -= reh;
                tcs.SetResult((MediaElement)s);
            };
            mediaElement.CurrentStateChanged += reh;
            return await tcs.Task;
        }

Wniui ha no MediaElement but a MediaPLayerElement I ty to modify the class for Winui like this :

<

public static class MediaElementExtensions
{
    public static async Task<MediaPlayerElement> PlayToEndAsync(this MediaPlayerElement mediaElement, Uri source)
    {
        mediaElement.Source = Windows.Media.Core.MediaSource.CreateFromUri(source);
        mediaElement.MediaPlayer.Play();
        return await mediaElement.WaitToCompleteAsync();
    }

    /*********************************************************************/

    public static async Task<MediaPlayerElement> WaitToCompleteAsync(this MediaPlayerElement mediaElement)
    {
        var tcs = new TaskCompletionSource<MediaPlayerElement>();
        RoutedEventHandler reh = null;
        reh = (s, e) =>
        {
            if (mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Buffering ||
                mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Opening ||
                mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Playing)
            {
                return;
            }
            mediaElement.MediaPlayer.CurrentStateChanged -= reh;
            tcs.SetResult((MediaPlayerElement)s);
        };
        mediaElement.MediaPlayer.CurrentStateChanged += reh;
        return await tcs.Task;
    }
>

This won't compile i get :
Error	CS0029	Cannot implicitly convert type 'Microsoft.UI.Xaml.RoutedEventHandler' to 'Windows.Foundation.TypedEventHandler<Windows.Media.Playback.MediaPlayer, object>'	Horloge parlante	D:\Mes SDK\Horloge parlante\Horloge parlante\Horloge\HorlogeMain.xaml.cs

Any idee to modifiy this in WinUI ?

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,650 questions
Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
752 questions
0 comments No comments
{count} votes

Accepted answer
  1. Junjie Zhu - MSFT 16,706 Reputation points Microsoft Vendor
    2023-03-06T07:47:34.6566667+00:00

    Hello @Fernand Delavy ,

    Welcome to Microsoft Q&A!

    In MediaPlayer Class,

    MediaPlayer.CurrentStateChanged may be altered or unavailable after Windows 10, version 1607. Instead, use the MediaPlayer.PlaybackSession property to get a MediaPlaybackSession object and then use the MediaPlaybackSession.PlaybackStateChanged event.

    So, you need to use PlaybackStateChanged event instead of CurrentStateChanged.

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. Fernand Delavy 20 Reputation points
    2023-03-07T13:10:01.9333333+00:00

    The problem is the same with your post :

    public static async Task<MediaPlayerElement> WaitToCompleteAsync(this MediaPlayerElement mediaElement)
        {
            var tcs = new TaskCompletionSource<MediaPlayerElement>();
            RoutedEventHandler reh = null;
            reh = (s, e) =>
            {
                if (mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Buffering ||
                    mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Opening ||
                    mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Playing)
                {
                    return;
                }
                mediaElement.MediaPlayer.PlaybackSession.PlaybackStateChanged -= reh;
                tcs.SetResult((MediaPlayerElement)s);
            };
            mediaElement.MediaPlayer.PlaybackSession.PlaybackStateChanged += reh;
            return await tcs.Task;
        }
    

    Visual Studio 2022 compile error on the two lines :

    mediaElement.MediaPlayer.PlaybackSession.PlaybackStateChanged
    

    Cannot implicitly convert type 'Microsoft.UI.Xaml.RoutedEventHandler' to 'Windows.Foundation.TypedEventHandler<Windows.Media.Playback.MediaPlaybackSession, object>'

    
        {
            var tcs = new TaskCompletionSource<MediaPlayerElement>();
            RoutedEventHandler reh = null;
            reh = (s, e) =>
            {
                if (mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Buffering ||
                    mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Opening ||
                    mediaElement.MediaPlayer.CurrentState == Windows.Media.Playback.MediaPlayerState.Playing)
                {
                    return;
                }
                mediaElement.MediaPlayer.PlaybackSession.PlaybackStateChanged -= reh;
                tcs.SetResult((MediaPlayerElement)s);
            };
            mediaElement.MediaPlayer.PlaybackSession.PlaybackStateChanged += reh;
            return await tcs.Task;
        }
    
    

  2. Fernand Delavy 20 Reputation points
    2023-03-14T14:45:08.6366667+00:00

    Thank you Sir,

    Now it compile but not work as expected !

    I have this to call the PlayToEndAsync :

    if (dt.Minute == 0) // Sonner les heures
            {
                Uri uri = new(installFolder.Path + @"\" + Sonneries[Options[0].Sonnerie].Heure);
                int heu = heures;
                if (heu > 12)
                    heu -= 12;
                for (int i = 0; i < heu; i++)
                {
                    await clochesPlayer.PlayToEndAsync(uri); // here not waiting to ens !
                }
            }
    
    If it is 5 hours it should play 5 times the sound, but it plays only once !
    so the play to end does not work !
    
    0 comments No comments

  3. Fernand Delavy 20 Reputation points
    2023-03-20T13:18:12.8633333+00:00

    I didn't find a solution on web.

    I did try ChatGBT and i got this :

    for (int i = 0; i < heu; i++)
                {
                    clochesPlayer = new MediaPlayerElement()
                    {
                        Source = Windows.Media.Core.MediaSource.CreateFromUri(uri)
                    };
                    TaskCompletionSource<bool> mediaEndedTcs = new ();
                    clochesPlayer.MediaPlayer.MediaEnded += (sender, args) =>
                    {
                        mediaEndedTcs.SetResult(true);
                    };
                    clochesPlayer.MediaPlayer.Play();
                    await mediaEndedTcs.Task;
                }
    

    And this works as expected !

    0 comments No comments