Add support for react-native Windows Cpp/WinRT (#1893)
This also deprecates the old react-native windows implementation
This commit is contained in:
16
windows/ReactNativeVideoCPP/PropertySheet.props
Normal file
16
windows/ReactNativeVideoCPP/PropertySheet.props
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<!--
|
||||
To customize common C++/WinRT project properties:
|
||||
* right-click the project node
|
||||
* expand the Common Properties item
|
||||
* select the C++/WinRT property page
|
||||
|
||||
For more advanced scenarios, and complete documentation, please see:
|
||||
https://github.com/Microsoft/xlang/tree/master/src/package/cppwinrt/nuget
|
||||
-->
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup />
|
||||
</Project>
|
3
windows/ReactNativeVideoCPP/ReactNativeVideoCPP.def
Normal file
3
windows/ReactNativeVideoCPP/ReactNativeVideoCPP.def
Normal file
@@ -0,0 +1,3 @@
|
||||
EXPORTS
|
||||
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
157
windows/ReactNativeVideoCPP/ReactNativeVideoCPP.vcxproj
Normal file
157
windows/ReactNativeVideoCPP/ReactNativeVideoCPP.vcxproj
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<ProjectGuid>{765365e4-9553-4900-9f69-e26d4309c8da}</ProjectGuid>
|
||||
<ProjectName>ReactNativeVideoCPP</ProjectName>
|
||||
<RootNamespace>ReactNativeVideoCPP</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.15063.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\..\..\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems" Label="Shared" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="PropertySheet.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||
<!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use -->
|
||||
<AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions>
|
||||
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
|
||||
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateWindowsMetadata>true</GenerateWindowsMetadata>
|
||||
<ModuleDefinitionFile>ReactNativeVideoCPP.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ReactVideoView.h">
|
||||
<DependentUpon>ReactVideoView.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ReactVideoViewManager.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ReactPackageProvider.h">
|
||||
<DependentUpon>ReactPackageProvider.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ReactVideoView.cpp">
|
||||
<DependentUpon>ReactVideoView.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ReactVideoViewManager.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ReactPackageProvider.cpp">
|
||||
<DependentUpon>ReactPackageProvider.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ReactVideoView.idl" />
|
||||
<Midl Include="ReactPackageProvider.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="ReactNativeVideoCPP.def" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj">
|
||||
<Project>{f7d32bd0-2749-483e-9a0d-1635ef7e3136}</Project>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resources">
|
||||
<UniqueIdentifier>accd3aa8-1ba0-4223-9bbe-0c431709210b</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{926ab91d-31b4-48c3-b9a4-e681349f27f0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp" />
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
<ClCompile Include="ReactPackageProvider.cpp" />
|
||||
<ClCompile Include="ReactVideoView.cpp" />
|
||||
<ClCompile Include="ReactVideoViewManager.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="ReactPackageProvider.h" />
|
||||
<ClInclude Include="ReactVideoView.h" />
|
||||
<ClInclude Include="ReactVideoViewManager.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReactNativeVideoCPP.def" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="readme.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Midl Include="ReactPackageProvider.idl" />
|
||||
<Midl Include="ReactVideoView.idl" />
|
||||
</ItemGroup>
|
||||
</Project>
|
17
windows/ReactNativeVideoCPP/ReactPackageProvider.cpp
Normal file
17
windows/ReactNativeVideoCPP/ReactPackageProvider.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "pch.h"
|
||||
#include "ReactPackageProvider.h"
|
||||
#if __has_include("ReactPackageProvider.g.cpp")
|
||||
#include "ReactPackageProvider.g.cpp"
|
||||
#endif
|
||||
|
||||
#include "ReactVideoViewManager.h"
|
||||
|
||||
using namespace winrt::Microsoft::ReactNative;
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::implementation {
|
||||
|
||||
void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept {
|
||||
packageBuilder.AddViewManager(L"ReactVideoViewManager", []() { return winrt::make<ReactVideoViewManager>(); });
|
||||
}
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
20
windows/ReactNativeVideoCPP/ReactPackageProvider.h
Normal file
20
windows/ReactNativeVideoCPP/ReactPackageProvider.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "ReactPackageProvider.g.h"
|
||||
|
||||
using namespace winrt::Microsoft::ReactNative;
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::implementation {
|
||||
|
||||
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider> {
|
||||
ReactPackageProvider() = default;
|
||||
|
||||
void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept;
|
||||
};
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::factory_implementation {
|
||||
|
||||
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider, implementation::ReactPackageProvider> {};
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::factory_implementation
|
7
windows/ReactNativeVideoCPP/ReactPackageProvider.idl
Normal file
7
windows/ReactNativeVideoCPP/ReactPackageProvider.idl
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace ReactNativeVideoCPP {
|
||||
[webhosthidden]
|
||||
[default_interface]
|
||||
runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider {
|
||||
ReactPackageProvider();
|
||||
};
|
||||
} // namespace ReactNativeVideoCPP
|
244
windows/ReactNativeVideoCPP/ReactVideoView.cpp
Normal file
244
windows/ReactNativeVideoCPP/ReactVideoView.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
#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 {
|
||||
|
||||
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) {
|
||||
if (auto self = ref.get()) {
|
||||
self->OnMediaOpened(sender, args);
|
||||
}
|
||||
});
|
||||
m_mediaFailedToken = m_player.MediaFailed(winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
||||
if (auto self = ref.get()) {
|
||||
self->OnMediaFailed(sender, args);
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
m_bufferingStartedToken =
|
||||
m_player.PlaybackSession().BufferingStarted(winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
||||
if (auto self = ref.get()) {
|
||||
self->OnBufferingStarted(sender, args);
|
||||
}
|
||||
});
|
||||
|
||||
m_bufferingEndedToken =
|
||||
m_player.PlaybackSession().BufferingEnded(winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
||||
if (auto self = ref.get()) {
|
||||
self->OnBufferingEnded(sender, args);
|
||||
}
|
||||
});
|
||||
|
||||
m_seekCompletedToken =
|
||||
m_player.PlaybackSession().SeekCompleted(winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
||||
if (auto self = ref.get()) {
|
||||
self->OnSeekCompleted(sender, args);
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
eventDataWriter.WriteObjectEnd();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReactVideoView::OnMediaFailed(IInspectable const&, IInspectable const&) {}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReactVideoView::OnBufferingStarted(IInspectable const&, IInspectable const&) {}
|
||||
|
||||
void ReactVideoView::OnBufferingEnded(IInspectable const&, IInspectable const&) {}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_ProgressUpdateInterval(int64_t interval) {
|
||||
m_timer.Interval(std::chrono::milliseconds{ interval });
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_IsLoopingEnabled(bool value) {
|
||||
m_isLoopingEnabled = value;
|
||||
if (m_player != nullptr) {
|
||||
m_player.IsLoopingEnabled(m_isLoopingEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_Paused(bool value) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_AutoPlay(bool autoPlay) {
|
||||
m_player.AutoPlay(autoPlay);
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_Muted(bool isMuted) {
|
||||
m_isMuted = isMuted;
|
||||
if (m_player != nullptr) {
|
||||
m_player.IsMuted(m_isMuted);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_Controls(bool useControls) {
|
||||
m_useControls = useControls;
|
||||
AreTransportControlsEnabled(m_useControls);
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_FullScreen(bool fullScreen) {
|
||||
m_fullScreen = fullScreen;
|
||||
IsFullWindow(m_fullScreen);
|
||||
|
||||
if (m_fullScreen)
|
||||
{
|
||||
Set_Controls(true); // full window will always have transport control enabled
|
||||
}
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_Volume(double volume) {
|
||||
m_volume = volume;
|
||||
if (m_player != nullptr) {
|
||||
m_player.Volume(m_volume);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactVideoView::Set_Position(double position) {
|
||||
m_position = position;
|
||||
if (m_player != nullptr) {
|
||||
std::chrono::seconds duration(static_cast<int>(m_position));
|
||||
m_player.PlaybackSession().Position(duration);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReactVideoView::IsPlaying(MediaPlaybackState currentState) {
|
||||
return (
|
||||
currentState == MediaPlaybackState::Buffering ||
|
||||
currentState == MediaPlaybackState::Opening ||
|
||||
currentState == MediaPlaybackState::Playing
|
||||
);
|
||||
}
|
||||
|
||||
void ReactVideoView::runOnQueue(std::function<void()>&& func) {
|
||||
m_uiDispatcher.RunAsync(
|
||||
winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [func = std::move(func)]() { func(); });
|
||||
}
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
56
windows/ReactNativeVideoCPP/ReactVideoView.h
Normal file
56
windows/ReactNativeVideoCPP/ReactVideoView.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "ReactVideoView.g.h"
|
||||
#include <functional>
|
||||
using namespace winrt;
|
||||
using namespace Microsoft::ReactNative;
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::implementation {
|
||||
struct ReactVideoView : ReactVideoViewT<ReactVideoView> {
|
||||
public:
|
||||
ReactVideoView(winrt::Microsoft::ReactNative::IReactContext const &reactContext);
|
||||
void Set_UriString(hstring const &value);
|
||||
void Set_IsLoopingEnabled(bool value);
|
||||
void Set_Paused(bool isPaused);
|
||||
void Set_Muted(bool isMuted);
|
||||
void Set_Volume(double volume);
|
||||
void Set_Position(double position);
|
||||
void Set_Controls(bool useControls);
|
||||
void Set_FullScreen(bool fullScreen);
|
||||
void Set_ProgressUpdateInterval(int64_t interval);
|
||||
void Set_AutoPlay(bool autoPlay);
|
||||
|
||||
private:
|
||||
hstring m_uriString;
|
||||
bool m_isLoopingEnabled = false;
|
||||
bool m_isPaused = true;
|
||||
bool m_isMuted = false;
|
||||
bool m_useControls = false;
|
||||
bool m_fullScreen = false;
|
||||
double m_volume = 0;
|
||||
double m_position = 0;
|
||||
Windows::UI::Xaml::DispatcherTimer m_timer;
|
||||
Windows::Media::Playback::MediaPlayer m_player = nullptr;
|
||||
Windows::UI::Core::CoreDispatcher m_uiDispatcher = nullptr;
|
||||
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||
|
||||
Windows::Media::Playback::MediaPlayer::MediaOpened_revoker m_mediaOpenedToken{};
|
||||
Windows::Media::Playback::MediaPlayer::MediaFailed_revoker m_mediaFailedToken{};
|
||||
Windows::Media::Playback::MediaPlayer::MediaEnded_revoker m_mediaEndedToken{};
|
||||
Windows::Media::Playback::MediaPlaybackSession::BufferingStarted_revoker m_bufferingStartedToken{};
|
||||
Windows::Media::Playback::MediaPlaybackSession::BufferingEnded_revoker m_bufferingEndedToken{};
|
||||
Windows::Media::Playback::MediaPlaybackSession::SeekCompleted_revoker m_seekCompletedToken{};
|
||||
|
||||
bool IsPlaying(Windows::Media::Playback::MediaPlaybackState currentState);
|
||||
void OnMediaOpened(IInspectable const &sender, IInspectable const &args);
|
||||
void OnMediaFailed(IInspectable const &sender, IInspectable const &args);
|
||||
void OnMediaEnded(IInspectable const &sender, IInspectable const &);
|
||||
void OnBufferingStarted(IInspectable const &sender, IInspectable const &);
|
||||
void OnBufferingEnded(IInspectable const &sender, IInspectable const &);
|
||||
void OnSeekCompleted(IInspectable const &sender, IInspectable const &);
|
||||
|
||||
void runOnQueue(std::function<void()> &&func);
|
||||
};
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
||||
namespace winrt::ReactNativeVideoCPP::factory_implementation {
|
||||
struct ReactVideoView : ReactVideoViewT<ReactVideoView, implementation::ReactVideoView> {};
|
||||
} // namespace winrt::ReactNativeVideoCPP::factory_implementation
|
16
windows/ReactNativeVideoCPP/ReactVideoView.idl
Normal file
16
windows/ReactNativeVideoCPP/ReactVideoView.idl
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace ReactNativeVideoCPP {
|
||||
|
||||
[default_interface] runtimeclass ReactVideoView : Windows.UI.Xaml.Controls.MediaPlayerElement {
|
||||
ReactVideoView(Microsoft.ReactNative.IReactContext context);
|
||||
void Set_UriString(String uri);
|
||||
void Set_IsLoopingEnabled(Boolean isLoopingEnabled);
|
||||
void Set_Paused(Boolean isPaused);
|
||||
void Set_Muted(Boolean isMuted);
|
||||
void Set_Volume(Double volume);
|
||||
void Set_Position(Double position);
|
||||
void Set_Controls(Boolean useControls);
|
||||
void Set_FullScreen(Boolean fullScreen);
|
||||
void Set_ProgressUpdateInterval(Int64 interval);
|
||||
void Set_AutoPlay(Boolean autoPlay);
|
||||
};
|
||||
} // namespace ReactNativeVideoCPP
|
110
windows/ReactNativeVideoCPP/ReactVideoViewManager.cpp
Normal file
110
windows/ReactNativeVideoCPP/ReactVideoViewManager.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "pch.h"
|
||||
#include "ReactVideoViewManager.h"
|
||||
#include "NativeModules.h"
|
||||
#include "ReactVideoView.h"
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::implementation {
|
||||
|
||||
ReactVideoViewManager::ReactVideoViewManager() {}
|
||||
|
||||
// IViewManager
|
||||
hstring ReactVideoViewManager::Name() noexcept {
|
||||
return L"RCTVideo";
|
||||
}
|
||||
|
||||
FrameworkElement ReactVideoViewManager::CreateView() noexcept {
|
||||
auto reactVideoView = winrt::ReactNativeVideoCPP::ReactVideoView(m_reactContext);
|
||||
return reactVideoView;
|
||||
}
|
||||
|
||||
// IViewManagerWithReactContext
|
||||
IReactContext ReactVideoViewManager::ReactContext() noexcept {
|
||||
return m_reactContext;
|
||||
}
|
||||
|
||||
void ReactVideoViewManager::ReactContext(IReactContext reactContext) noexcept {
|
||||
m_reactContext = reactContext;
|
||||
}
|
||||
|
||||
// IViewManagerWithExportedViewConstants
|
||||
winrt::Microsoft::ReactNative::ConstantProviderDelegate ReactVideoViewManager::ExportedViewConstants() noexcept {
|
||||
return [](winrt::Microsoft::ReactNative::IJSValueWriter const &constantWriter) {
|
||||
WriteProperty(constantWriter, L"ScaleNone", to_hstring(std::to_string((int)Stretch::None)));
|
||||
WriteProperty(constantWriter, L"ScaleToFill", to_hstring(std::to_string((int)Stretch::UniformToFill)));
|
||||
WriteProperty(constantWriter, L"ScaleAspectFit", to_hstring(std::to_string((int)Stretch::Uniform)));
|
||||
WriteProperty(constantWriter, L"ScaleAspectFill", to_hstring(std::to_string((int)Stretch::Fill)));
|
||||
};
|
||||
}
|
||||
|
||||
// IViewManagerWithNativeProperties
|
||||
IMapView<hstring, ViewManagerPropertyType> ReactVideoViewManager::NativeProps() noexcept {
|
||||
auto nativeProps = winrt::single_threaded_map<hstring, ViewManagerPropertyType>();
|
||||
nativeProps.Insert(L"src", ViewManagerPropertyType::Map);
|
||||
nativeProps.Insert(L"resizeMode", ViewManagerPropertyType::String);
|
||||
nativeProps.Insert(L"repeat", ViewManagerPropertyType::Boolean);
|
||||
nativeProps.Insert(L"paused", ViewManagerPropertyType::Boolean);
|
||||
nativeProps.Insert(L"muted", ViewManagerPropertyType::Boolean);
|
||||
nativeProps.Insert(L"volume", ViewManagerPropertyType::Number);
|
||||
nativeProps.Insert(L"seek", ViewManagerPropertyType::Number);
|
||||
nativeProps.Insert(L"controls", ViewManagerPropertyType::Boolean);
|
||||
nativeProps.Insert(L"fullscreen", ViewManagerPropertyType::Boolean);
|
||||
nativeProps.Insert(L"progressUpdateInterval", ViewManagerPropertyType::Number);
|
||||
|
||||
return nativeProps.GetView();
|
||||
}
|
||||
|
||||
void ReactVideoViewManager::UpdateProperties(
|
||||
FrameworkElement const &view,
|
||||
IJSValueReader const &propertyMapReader) noexcept {
|
||||
if (auto reactVideoView = view.try_as<winrt::ReactNativeVideoCPP::ReactVideoView>()) {
|
||||
const JSValueObject &propertyMap = JSValue::ReadObjectFrom(propertyMapReader);
|
||||
|
||||
for (auto const &pair : propertyMap) {
|
||||
auto const &propertyName = pair.first;
|
||||
auto const &propertyValue = pair.second;
|
||||
if (!propertyValue.IsNull()) {
|
||||
if (propertyName == "src") {
|
||||
auto const &srcMap = propertyValue.Object();
|
||||
auto const &uri = srcMap.at("uri");
|
||||
reactVideoView.Set_UriString(to_hstring(uri.String()));
|
||||
} else if (propertyName == "resizeMode") {
|
||||
reactVideoView.Stretch(static_cast<Stretch>(std::stoul(propertyValue.String())));
|
||||
} else if (propertyName == "repeat") {
|
||||
reactVideoView.Set_IsLoopingEnabled(propertyValue.Boolean());
|
||||
} else if (propertyName == "paused") {
|
||||
m_paused = propertyValue.Boolean();
|
||||
reactVideoView.Set_Paused(m_paused);
|
||||
} else if (propertyName == "muted") {
|
||||
reactVideoView.Set_Muted(propertyValue.Boolean());
|
||||
} else if (propertyName == "volume") {
|
||||
reactVideoView.Set_Volume(propertyValue.Double());
|
||||
} else if (propertyName == "seek") {
|
||||
reactVideoView.Set_Position(propertyValue.Double());
|
||||
} else if (propertyName == "controls") {
|
||||
reactVideoView.Set_Controls(propertyValue.Boolean());
|
||||
} else if (propertyName == "fullscreen") {
|
||||
reactVideoView.Set_FullScreen(propertyValue.Boolean());
|
||||
} else if (propertyName == "progressUpdateInterval") {
|
||||
reactVideoView.Set_ProgressUpdateInterval(propertyValue.Int64());
|
||||
}
|
||||
}
|
||||
}
|
||||
reactVideoView.Set_AutoPlay(!m_paused); // auto play on pause false or not set.
|
||||
}
|
||||
}
|
||||
|
||||
// IViewManagerWithExportedEventTypeConstants
|
||||
ConstantProviderDelegate ReactVideoViewManager::ExportedCustomBubblingEventTypeConstants() noexcept {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ConstantProviderDelegate ReactVideoViewManager::ExportedCustomDirectEventTypeConstants() noexcept {
|
||||
return [](winrt::Microsoft::ReactNative::IJSValueWriter const &constantWriter) {
|
||||
WriteCustomDirectEventTypeConstant(constantWriter, "Load");
|
||||
WriteCustomDirectEventTypeConstant(constantWriter, "End");
|
||||
WriteCustomDirectEventTypeConstant(constantWriter, "Seek");
|
||||
WriteCustomDirectEventTypeConstant(constantWriter, "Progress");
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
55
windows/ReactNativeVideoCPP/ReactVideoViewManager.h
Normal file
55
windows/ReactNativeVideoCPP/ReactVideoViewManager.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "winrt/Microsoft.ReactNative.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::Media::Core;
|
||||
|
||||
namespace winrt::ReactNativeVideoCPP::implementation {
|
||||
|
||||
struct ReactVideoViewManager : winrt::implements<
|
||||
ReactVideoViewManager,
|
||||
winrt::Microsoft::ReactNative::IViewManager,
|
||||
winrt::Microsoft::ReactNative::IViewManagerWithReactContext,
|
||||
winrt::Microsoft::ReactNative::IViewManagerWithExportedViewConstants,
|
||||
winrt::Microsoft::ReactNative::IViewManagerWithNativeProperties,
|
||||
winrt::Microsoft::ReactNative::IViewManagerWithExportedEventTypeConstants> {
|
||||
public:
|
||||
ReactVideoViewManager();
|
||||
// IViewManager
|
||||
winrt::hstring Name() noexcept;
|
||||
FrameworkElement CreateView() noexcept;
|
||||
|
||||
// IViewManagerWithReactContext
|
||||
winrt::Microsoft::ReactNative::IReactContext ReactContext() noexcept;
|
||||
void ReactContext(winrt::Microsoft::ReactNative::IReactContext reactContext) noexcept;
|
||||
|
||||
// IViewManagerWithNativeProperties
|
||||
winrt::Windows::Foundation::Collections::
|
||||
IMapView<winrt::hstring, winrt::Microsoft::ReactNative::ViewManagerPropertyType>
|
||||
NativeProps() noexcept;
|
||||
|
||||
void UpdateProperties(
|
||||
winrt::Windows::UI::Xaml::FrameworkElement const &view,
|
||||
winrt::Microsoft::ReactNative::IJSValueReader const &propertyMapReader) noexcept;
|
||||
|
||||
// IViewManagerWithExportedViewConstants
|
||||
winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedViewConstants() noexcept;
|
||||
|
||||
// IViewManagerWithExportedEventTypeConstants
|
||||
winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomBubblingEventTypeConstants() noexcept;
|
||||
|
||||
winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomDirectEventTypeConstants() noexcept;
|
||||
|
||||
private:
|
||||
winrt::Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||
bool m_paused = false;
|
||||
};
|
||||
|
||||
} // namespace winrt::ReactNativeVideoCPP::implementation
|
4
windows/ReactNativeVideoCPP/packages.config
Normal file
4
windows/ReactNativeVideoCPP/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.190730.2" targetFramework="native" />
|
||||
</packages>
|
1
windows/ReactNativeVideoCPP/pch.cpp
Normal file
1
windows/ReactNativeVideoCPP/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
20
windows/ReactNativeVideoCPP/pch.h
Normal file
20
windows/ReactNativeVideoCPP/pch.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <unknwn.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Media.Core.h>
|
||||
#include <winrt/Windows.Media.Playback.h>
|
||||
#include <winrt/Windows.System.Threading.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
#include <winrt/Windows.UI.ViewManagement.h>
|
||||
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
|
||||
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||
#include <winrt/Windows.UI.Xaml.Data.h>
|
||||
#include <winrt/Windows.UI.Xaml.Interop.h>
|
||||
#include <winrt/Windows.UI.Xaml.Markup.h>
|
||||
#include <winrt/Windows.UI.Xaml.Navigation.h>
|
||||
#include <winrt/Windows.UI.Xaml.h>
|
||||
#include <winrt/Windows.UI.Xaml.Input.h>
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
Reference in New Issue
Block a user