| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | #include "pch.h"
 | 
					
						
							|  |  |  | #include "ReactVideoView.h"
 | 
					
						
							|  |  |  | #include "ReactVideoView.g.cpp"
 | 
					
						
							|  |  |  | #include "NativeModules.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace winrt; | 
					
						
							|  |  |  | using namespace Windows::Foundation; | 
					
						
							|  |  |  | using namespace Windows::Foundation::Collections; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace Windows::UI::Xaml; | 
					
						
							|  |  |  | using namespace Windows::UI::Xaml::Media; | 
					
						
							|  |  |  | using namespace Windows::UI::Xaml::Controls; | 
					
						
							|  |  |  | using namespace Windows::UI::Core; | 
					
						
							|  |  |  | using namespace Windows::Media::Core; | 
					
						
							|  |  |  | using namespace Windows::Media::Playback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace winrt::ReactNativeVideoCPP::implementation { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | ReactVideoView::ReactVideoView(winrt::Microsoft::ReactNative::IReactContext const &reactContext) | 
					
						
							|  |  |  |     : m_reactContext(reactContext) { | 
					
						
							|  |  |  |   // always create and set the player here instead of depending on auto-create logic
 | 
					
						
							|  |  |  |   // in the MediaPlayerElement (only when auto play is on or URI is set)
 | 
					
						
							|  |  |  |   m_player = winrt::Windows::Media::Playback::MediaPlayer(); | 
					
						
							|  |  |  |   SetMediaPlayer(m_player); | 
					
						
							|  |  |  |   m_uiDispatcher = CoreWindow::GetForCurrentThread().Dispatcher(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_mediaOpenedToken = | 
					
						
							|  |  |  |       m_player.MediaOpened(winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         if (auto self = ref.get()) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |           self->OnMediaOpened(sender, args); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  |   m_mediaFailedToken = | 
					
						
							|  |  |  |       m_player.MediaFailed(winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         if (auto self = ref.get()) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |           self->OnMediaFailed(sender, args); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_mediaEndedToken = m_player.MediaEnded(winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							|  |  |  |     if (auto self = ref.get()) { | 
					
						
							|  |  |  |       self->OnMediaEnded(sender, args); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_bufferingStartedToken = m_player.PlaybackSession().BufferingStarted( | 
					
						
							|  |  |  |       winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         if (auto self = ref.get()) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |           self->OnBufferingStarted(sender, args); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_bufferingEndedToken = m_player.PlaybackSession().BufferingEnded( | 
					
						
							|  |  |  |       winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         if (auto self = ref.get()) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |           self->OnBufferingEnded(sender, args); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_seekCompletedToken = m_player.PlaybackSession().SeekCompleted( | 
					
						
							|  |  |  |       winrt::auto_revoke, [ref = get_weak()](auto const &sender, auto const &args) { | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         if (auto self = ref.get()) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |           self->OnSeekCompleted(sender, args); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_timer = Windows::UI::Xaml::DispatcherTimer(); | 
					
						
							|  |  |  |   m_timer.Interval(std::chrono::milliseconds{250}); | 
					
						
							|  |  |  |   m_timer.Start(); | 
					
						
							|  |  |  |   auto token = m_timer.Tick([ref = get_weak()](auto const &, auto const &) { | 
					
						
							|  |  |  |     if (auto self = ref.get()) { | 
					
						
							|  |  |  |       if (auto mediaPlayer = self->m_player) { | 
					
						
							|  |  |  |         if (mediaPlayer.PlaybackSession().PlaybackState() == | 
					
						
							|  |  |  |             winrt::Windows::Media::Playback::MediaPlaybackState::Playing) { | 
					
						
							|  |  |  |           auto currentTimeInSeconds = mediaPlayer.PlaybackSession().Position().count() / 10000000; | 
					
						
							|  |  |  |           self->m_reactContext.DispatchEvent( | 
					
						
							|  |  |  |               *self, | 
					
						
							|  |  |  |               L"topProgress", | 
					
						
							|  |  |  |               [&](winrt::Microsoft::ReactNative::IJSValueWriter const &eventDataWriter) noexcept { | 
					
						
							|  |  |  |                 eventDataWriter.WriteObjectBegin(); | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"currentTime", currentTimeInSeconds); | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"playableDuration", 0.0); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |                 eventDataWriter.WriteObjectEnd(); | 
					
						
							|  |  |  |               }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::OnMediaOpened(IInspectable const &, IInspectable const &) { | 
					
						
							|  |  |  |   runOnQueue([weak_this{get_weak()}]() { | 
					
						
							|  |  |  |     if (auto strong_this{weak_this.get()}) { | 
					
						
							|  |  |  |       if (auto mediaPlayer = strong_this->m_player) { | 
					
						
							|  |  |  |         auto width = mediaPlayer.PlaybackSession().NaturalVideoWidth(); | 
					
						
							|  |  |  |         auto height = mediaPlayer.PlaybackSession().NaturalVideoHeight(); | 
					
						
							|  |  |  |         auto orientation = (width > height) ? L"landscape" : L"portrait"; | 
					
						
							|  |  |  |         auto durationInSeconds = mediaPlayer.PlaybackSession().NaturalDuration().count() / 10000000; | 
					
						
							|  |  |  |         auto currentTimeInSeconds = mediaPlayer.PlaybackSession().Position().count() / 10000000; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         strong_this->m_reactContext.DispatchEvent( | 
					
						
							|  |  |  |             *strong_this, | 
					
						
							|  |  |  |             L"topLoad", | 
					
						
							|  |  |  |             [&](winrt::Microsoft::ReactNative::IJSValueWriter const &eventDataWriter) noexcept { | 
					
						
							|  |  |  |               eventDataWriter.WriteObjectBegin(); | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"duration", durationInSeconds); | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"currentTime", currentTimeInSeconds); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 eventDataWriter.WritePropertyName(L"naturalSize"); | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                   eventDataWriter.WriteObjectBegin(); | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"width", width); | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"height", height); | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"orientation", orientation); | 
					
						
							|  |  |  |                   WriteProperty(eventDataWriter, L"orientation", orientation); | 
					
						
							|  |  |  |                   eventDataWriter.WriteObjectEnd(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"canPlayFastForward", false); | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"canPlaySlowForward", false); | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"canPlaySlow", false); | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"canStepBackward", false); | 
					
						
							|  |  |  |                 WriteProperty(eventDataWriter, L"canStepForward", false); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               eventDataWriter.WriteObjectEnd(); | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-18 18:08:21 -07:00
										 |  |  | void ReactVideoView::OnMediaFailed(IInspectable const &, IInspectable const &) { | 
					
						
							|  |  |  |   runOnQueue([weak_this{get_weak()}]() { | 
					
						
							|  |  |  |     if (auto strong_this{weak_this.get()}) { | 
					
						
							|  |  |  |       strong_this->m_reactContext.DispatchEvent(*strong_this, L"topError", nullptr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::OnMediaEnded(IInspectable const &, IInspectable const &) { | 
					
						
							|  |  |  |   runOnQueue([weak_this{get_weak()}]() { | 
					
						
							|  |  |  |     if (auto strong_this{weak_this.get()}) { | 
					
						
							|  |  |  |       strong_this->m_reactContext.DispatchEvent(*strong_this, L"topEnd", nullptr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::OnBufferingStarted(IInspectable const &, IInspectable const &) {} | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::OnBufferingEnded(IInspectable const &, IInspectable const &) {} | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::OnSeekCompleted(IInspectable const &, IInspectable const &) { | 
					
						
							|  |  |  |   runOnQueue([weak_this{get_weak()}]() { | 
					
						
							|  |  |  |     if (auto strong_this{weak_this.get()}) { | 
					
						
							|  |  |  |       strong_this->m_reactContext.DispatchEvent(*strong_this, L"topSeek", nullptr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_ProgressUpdateInterval(int64_t interval) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_timer.Interval(std::chrono::milliseconds{interval}); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_IsLoopingEnabled(bool value) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_isLoopingEnabled = value; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     m_player.IsLoopingEnabled(m_isLoopingEnabled); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::Set_UriString(hstring const &value) { | 
					
						
							|  |  |  |   m_uriString = value; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     auto uri = Uri(m_uriString); | 
					
						
							|  |  |  |     m_player.Source(MediaSource::CreateFromUri(uri)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_Paused(bool value) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_isPaused = value; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     if (m_isPaused) { | 
					
						
							|  |  |  |       if (IsPlaying(m_player.PlaybackSession().PlaybackState())) { | 
					
						
							|  |  |  |         m_player.Pause(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (!IsPlaying(m_player.PlaybackSession().PlaybackState())) { | 
					
						
							|  |  |  |         m_player.Play(); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_AutoPlay(bool autoPlay) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_player.AutoPlay(autoPlay); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_Muted(bool isMuted) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_isMuted = isMuted; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     m_player.IsMuted(m_isMuted); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_Controls(bool useControls) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_useControls = useControls; | 
					
						
							|  |  |  |   AreTransportControlsEnabled(m_useControls); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_FullScreen(bool fullScreen) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_fullScreen = fullScreen; | 
					
						
							|  |  |  |   IsFullWindow(m_fullScreen); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   if (m_fullScreen) { | 
					
						
							|  |  |  |     Set_Controls(true); // full window will always have transport control enabled
 | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_Volume(double volume) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_volume = volume; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     m_player.Volume(m_volume); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_Position(double position) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   m_position = position; | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     std::chrono::seconds duration(static_cast<int>(m_position)); | 
					
						
							|  |  |  |     m_player.PlaybackSession().Position(duration); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ReactVideoView::Set_PlaybackRate(double rate) { | 
					
						
							|  |  |  |   if (m_player != nullptr) { | 
					
						
							|  |  |  |     m_player.PlaybackSession().PlaybackRate(rate); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool ReactVideoView::IsPlaying(MediaPlaybackState currentState) { | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  |   return ( | 
					
						
							|  |  |  |       currentState == MediaPlaybackState::Buffering || currentState == MediaPlaybackState::Opening || | 
					
						
							|  |  |  |       currentState == MediaPlaybackState::Playing); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-08 10:37:35 -07:00
										 |  |  | void ReactVideoView::runOnQueue(std::function<void()> &&func) { | 
					
						
							|  |  |  |   m_uiDispatcher.RunAsync( | 
					
						
							|  |  |  |       winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [func = std::move(func)]() { func(); }); | 
					
						
							| 
									
										
										
										
											2020-02-25 06:21:06 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace winrt::ReactNativeVideoCPP::implementation
 |