Changing the icon in a button based off of MediaPlaybackState

1

I have a MediaPlayerElement and the following class to control it:

class MediaPlayer : INotifyPropertyChanged
        {
            private MediaPlaybackState _State;
            public MediaPlaybackState State
            {
                get
                {
                    return _State;
                }
                set
                {
                    _State = value;
                    OnPropertyChanged();
                }
            }
            public BitmapImage AlbumArt;
            public string Title;
            public string Subtitle;
            private MediaPlayerElement mediaPlayer;

            public event PropertyChangedEventHandler PropertyChanged = delegate { };

            public void PlayerStateChanged(MediaPlaybackSession session, object sender)
            {
                State = session.PlaybackState;
            }
            public void SetMediaElement(MediaPlayerElement param)
            {
                mediaPlayer = param;
            }
            public void PlayFromSearchResult(SearchResult result)
            {
                AlbumArt = new BitmapImage();
                AlbumArt.UriSource = new Uri(result.StationImage);
                Title = result.StationName;
                Subtitle = result.Subtext;
                PlayFromRemoteM3U(result.StreamURL);
            }
            public void Pause()
            {
                mediaPlayer.MediaPlayer.Pause();
            }
            public void Play()
            {
                mediaPlayer.MediaPlayer.Play();
                mediaPlayer.MediaPlayer.PlaybackSession.PlaybackStateChanged += PlayerStateChanged;
            }
            public async void PlayFromRemoteM3U(string url)
            {
                    --SNIP--
                    mediaPlayer.Source = MediaSource.CreateFromUri(new Uri(streamDownloadUrl));
                    Play();
                }
            }
            protected void OnPropertyChanged([CallerMemberName] string name = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

        }

I would like to have a play/pause button that changes it's content based on the current player state, I'm currently debugging with a TextBlock to display the current state:

<TextBlock x:Name="media_player_state" x:FieldModifier="public" FontSize="20" Text="{x:Bind MediaPlayerInstance.State, Mode=OneWay}">Play</TextBlock>

When I run the application and start a stream so the state changes, I get the following error: The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

I want to know if there I am trying to accomplish this the right way or how to fix this.

Thanks

c#
uwp
uwp-xaml
asked on Stack Overflow Jan 4, 2021 by Isiah L

2 Answers

3

Because you're calling it from another thread, you need to use a dispatcher

public void PlayerStateChanged(MediaPlaybackSession session, object sender)
{
   DispatcherHelper.ExecuteOnUIThreadAsync(() =>
   {
      State = session.PlaybackState;
   });
}

please note 2 things:

1- DispatcherHelper is part of the windows community toolkit nuget package (https://www.nuget.org/profiles/Microsoft.Toolkit)

2- DispatcherHelper will be deprecated in favor of the better DispatcherQueueHelper in the 7.0 release

answered on Stack Overflow Jan 6, 2021 by PandaSharp
0

Because you are not setting the state everytime you Play() or Pause(). Change the _State value and then use OnpropertyChanged("State")

answered on Stack Overflow Jan 5, 2021 by Boommer

User contributions licensed under CC BY-SA 3.0