Add support for react-native Windows Cpp/WinRT (#1893)
This also deprecates the old react-native windows implementation
This commit is contained in:
parent
4f07aab8b1
commit
a4fec8eb99
44
README.md
44
README.md
@ -184,52 +184,34 @@ protected List<ReactPackage> getPackages() {
|
|||||||
|
|
||||||
### Windows installation
|
### Windows installation
|
||||||
<details>
|
<details>
|
||||||
<summary>Windows details</summary>
|
<summary>Windows RNW C++/WinRT details</summary>
|
||||||
|
|
||||||
Make the following additions to the given files manually:
|
Make the following additions to the given files manually:
|
||||||
|
|
||||||
#### **windows/myapp.sln**
|
#### **windows/myapp.sln**
|
||||||
|
|
||||||
Add the `ReactNativeVideo` project to your solution.
|
Add the `ReactNativeVideoCPP` project to your solution.
|
||||||
|
|
||||||
1. Open the solution in Visual Studio 2015
|
1. Open the solution in Visual Studio 2019
|
||||||
2. Right-click Solution icon in Solution Explorer > Add > Existing Project
|
2. Right-click Solution icon in Solution Explorer > Add > Existing Project
|
||||||
* UWP: Select `node_modules\react-native-video\windows\ReactNativeVideo\ReactNativeVideo.csproj`
|
Select `node_modules\react-native-video\windows\ReactNativeVideoCPP\ReactNativeVideoCPP.vcxproj`
|
||||||
* WPF: Select `node_modules\react-native-video\windows\ReactNativeVideo.Net46\ReactNativeVideo.Net46.csproj`
|
|
||||||
|
|
||||||
#### **windows/myapp/myapp.csproj**
|
#### **windows/myapp/myapp.vcxproj**
|
||||||
|
|
||||||
Add a reference to `ReactNativeVideo` to your main application project. From Visual Studio 2015:
|
Add a reference to `ReactNativeVideoCPP` to your main application project. From Visual Studio 2019:
|
||||||
|
|
||||||
1. Right-click main application project > Add > Reference...
|
1. Right-click main application project > Add > Reference...
|
||||||
* UWP: Check `ReactNativeVideo` from Solution Projects.
|
Check `ReactNativeVideoCPP` from Solution Projects.
|
||||||
* WPF: Check `ReactNativeVideo.Net46` from Solution Projects.
|
|
||||||
|
|
||||||
#### **MainPage.cs**
|
2. Modify files below to add the video package providers to your main application project
|
||||||
|
#### **pch.h**
|
||||||
|
|
||||||
Add the `ReactVideoPackage` class to your list of exported packages.
|
Add `#include "winrt/ReactNativeVideoCPP.h"`.
|
||||||
```cs
|
|
||||||
using ReactNative;
|
|
||||||
using ReactNative.Modules.Core;
|
|
||||||
using ReactNative.Shell;
|
|
||||||
using ReactNativeVideo; // <-- Add this
|
|
||||||
using System.Collections.Generic;
|
|
||||||
...
|
|
||||||
|
|
||||||
public override List<IReactPackage> Packages
|
#### **app.cpp**
|
||||||
{
|
|
||||||
get
|
Add `PackageProviders().Append(winrt::ReactNativeVideoCPP::ReactPackageProvider());` before `InitializeComponent();`.
|
||||||
{
|
|
||||||
return new List<IReactPackage>
|
|
||||||
{
|
|
||||||
new MainReactPackage(),
|
|
||||||
new ReactVideoPackage(), // <-- Add this
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
```
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### react-native-dom installation
|
### react-native-dom installation
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("ReactNativeVideo.Net46")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("ReactNativeVideo.Net46")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("2d8406ab-0674-42d3-8fe3-41d251403df8")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -1,74 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{2D8406AB-0674-42D3-8FE3-41D251403DF8}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>ReactNativeVideo.Net46</RootNamespace>
|
|
||||||
<AssemblyName>ReactNativeVideo.Net46</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
|
||||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="PresentationCore" />
|
|
||||||
<Reference Include="PresentationFramework" />
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xaml" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="WindowsBase" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="ReactVideoEventType.cs" />
|
|
||||||
<Compile Include="ReactVideoEventTypeExtensions.cs" />
|
|
||||||
<Compile Include="ReactVideoPackage.cs" />
|
|
||||||
<Compile Include="ReactVideoView.cs" />
|
|
||||||
<Compile Include="ReactVideoViewManager.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="$(SolutionDir)\..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj">
|
|
||||||
<Project>{22CBFF9C-FE36-43E8-A246-266C7635E662}</Project>
|
|
||||||
<Name>ReactNative.Net46</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="packages.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
@ -1,15 +0,0 @@
|
|||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
enum ReactVideoEventType
|
|
||||||
{
|
|
||||||
LoadStart,
|
|
||||||
Load,
|
|
||||||
Error,
|
|
||||||
Progress,
|
|
||||||
Seek,
|
|
||||||
End,
|
|
||||||
Stalled,
|
|
||||||
Resume,
|
|
||||||
ReadyForDisplay,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
using static System.FormattableString;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
static class ReactVideoEventTypeExtensions
|
|
||||||
{
|
|
||||||
public static string GetEventName(this ReactVideoEventType eventType)
|
|
||||||
{
|
|
||||||
switch (eventType)
|
|
||||||
{
|
|
||||||
case ReactVideoEventType.LoadStart:
|
|
||||||
return "onVideoLoadStart";
|
|
||||||
case ReactVideoEventType.Load:
|
|
||||||
return "onVideoLoad";
|
|
||||||
case ReactVideoEventType.Error:
|
|
||||||
return "onVideoError";
|
|
||||||
case ReactVideoEventType.Progress:
|
|
||||||
return "onVideoProgress";
|
|
||||||
case ReactVideoEventType.Seek:
|
|
||||||
return "onVideoSeek";
|
|
||||||
case ReactVideoEventType.End:
|
|
||||||
return "onVideoEnd";
|
|
||||||
case ReactVideoEventType.Stalled:
|
|
||||||
return "onPlaybackStalled";
|
|
||||||
case ReactVideoEventType.Resume:
|
|
||||||
return "onPlaybackResume";
|
|
||||||
case ReactVideoEventType.ReadyForDisplay:
|
|
||||||
return "onReadyForDisplay";
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException(
|
|
||||||
Invariant($"No event name added for event type '{eventType}'."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using ReactNative.Bridge;
|
|
||||||
using ReactNative.Modules.Core;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
public class ReactVideoPackage : IReactPackage
|
|
||||||
{
|
|
||||||
public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
|
|
||||||
{
|
|
||||||
return Array.Empty<Type>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
|
|
||||||
{
|
|
||||||
return Array.Empty<INativeModule>();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<IViewManager> CreateViewManagers(ReactContext reactContext)
|
|
||||||
{
|
|
||||||
return new List<IViewManager>
|
|
||||||
{
|
|
||||||
new ReactVideoViewManager(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,359 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using ReactNative.Bridge;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using ReactNative.UIManager.Events;
|
|
||||||
using System;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Animation;
|
|
||||||
using System.Windows.Threading;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
class ReactVideoView : Border, IDisposable
|
|
||||||
{
|
|
||||||
public const string EVENT_PROP_SEEK_TIME = "seekTime";
|
|
||||||
|
|
||||||
private readonly DispatcherTimer _timer;
|
|
||||||
|
|
||||||
private bool _isLoopingEnabled;
|
|
||||||
private bool _isPaused;
|
|
||||||
private bool _isMuted;
|
|
||||||
private bool _isCompleted;
|
|
||||||
private double _volume;
|
|
||||||
private double _rate;
|
|
||||||
|
|
||||||
private MediaPlayer _player;
|
|
||||||
private VideoDrawing _drawing;
|
|
||||||
private MediaTimeline _timeline;
|
|
||||||
private MediaClock _clock;
|
|
||||||
private DrawingBrush _brush;
|
|
||||||
|
|
||||||
public ReactVideoView()
|
|
||||||
{
|
|
||||||
_timer = new DispatcherTimer();
|
|
||||||
_timer.Interval = TimeSpan.FromMilliseconds(250.0);
|
|
||||||
_timer.Start();
|
|
||||||
_player = new MediaPlayer();
|
|
||||||
_drawing = new VideoDrawing();
|
|
||||||
_drawing.Rect = new Rect(0, 0, 100, 100); // Set the initial viewing area
|
|
||||||
_drawing.Player = _player;
|
|
||||||
_brush = new DrawingBrush(_drawing);
|
|
||||||
this.Background = _brush;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Source
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var uri = new Uri(value);
|
|
||||||
|
|
||||||
_player.Open(uri);
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.LoadStart.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{"src", uri}
|
|
||||||
}));
|
|
||||||
|
|
||||||
ApplyModifiers();
|
|
||||||
SubscribeEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLoopingEnabled
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isLoopingEnabled = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMuted
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isMuted = value;
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
_player.IsMuted = _isMuted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPaused
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isPaused = value;
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
if (_isPaused)
|
|
||||||
{
|
|
||||||
_player.Pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_player.Play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Volume
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_volume = value;
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
_player.Volume = _volume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Rate
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_rate = value;
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
_player.SpeedRatio = _rate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double ProgressUpdateInterval
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_timer.Interval = TimeSpan.FromSeconds(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Seek(double seek)
|
|
||||||
{
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
_player.Position = TimeSpan.FromSeconds(seek);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_player != null)
|
|
||||||
{
|
|
||||||
_timer.Tick -= OnTick;
|
|
||||||
_player.MediaOpened -= OnMediaOpened;
|
|
||||||
_player.MediaFailed -= OnMediaFailed;
|
|
||||||
_player.MediaEnded -= OnMediaEnded;
|
|
||||||
_player.BufferingStarted -= OnBufferingStarted;
|
|
||||||
_player.BufferingEnded -= OnBufferingEnded;
|
|
||||||
// _player.SeekCompleted -= OnSeekCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timer.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyModifiers()
|
|
||||||
{
|
|
||||||
IsLoopingEnabled = _isLoopingEnabled;
|
|
||||||
IsMuted = _isMuted;
|
|
||||||
IsPaused = _isPaused;
|
|
||||||
Volume = _volume;
|
|
||||||
Rate = _rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeEvents()
|
|
||||||
{
|
|
||||||
_timer.Tick += OnTick;
|
|
||||||
_player.MediaOpened += OnMediaOpened;
|
|
||||||
_player.MediaFailed += OnMediaFailed;
|
|
||||||
_player.MediaEnded += OnMediaEnded;
|
|
||||||
_player.BufferingStarted += OnBufferingStarted;
|
|
||||||
_player.BufferingEnded += OnBufferingEnded;
|
|
||||||
//_player.SeekCompleted += OnSeekCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTick(object sender, object e)
|
|
||||||
{
|
|
||||||
if (_player != null && !_isCompleted && !_isPaused)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Progress.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "currentTime", _player.Position.TotalSeconds },
|
|
||||||
{ "playableDuration", 0.0 /* TODO */ }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaOpened(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
RunOnDispatcher(delegate
|
|
||||||
{
|
|
||||||
var width = _player.NaturalVideoWidth;
|
|
||||||
var height = _player.NaturalVideoHeight;
|
|
||||||
var orientation = (width > height) ? "landscape" : "portrait";
|
|
||||||
var size = new JObject
|
|
||||||
{
|
|
||||||
{ "width", width },
|
|
||||||
{ "height", height },
|
|
||||||
{ "orientation", orientation }
|
|
||||||
};
|
|
||||||
|
|
||||||
_drawing.Rect = new Rect(new Size(width, height));
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Load.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "duration", _player.NaturalDuration.TimeSpan.TotalSeconds },
|
|
||||||
{ "currentTime", _player.Position.TotalSeconds },
|
|
||||||
{ "naturalSize", size },
|
|
||||||
{ "canPlayFastForward", false },
|
|
||||||
{ "canPlaySlowForward", false },
|
|
||||||
{ "canPlaySlow", false },
|
|
||||||
{ "canPlayReverse", false },
|
|
||||||
{ "canStepBackward", false },
|
|
||||||
{ "canStepForward", false }
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaFailed(object sender, ExceptionEventArgs args)
|
|
||||||
{
|
|
||||||
var errorData = new JObject
|
|
||||||
{
|
|
||||||
{ "what", args.ErrorException.HResult.ToString() },
|
|
||||||
{ "extra", args.ErrorException.Message }
|
|
||||||
};
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Error.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "error", errorData }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaEnded(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
if (_isLoopingEnabled)
|
|
||||||
{
|
|
||||||
_player.Position = TimeSpan.Zero;
|
|
||||||
_player.Play();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_isCompleted = true;
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.End.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBufferingStarted(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Stalled.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBufferingEnded(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Resume.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSeekCompleted(object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Seek.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async void RunOnDispatcher(Action action)
|
|
||||||
{
|
|
||||||
await Application.Current.Dispatcher.InvokeAsync(action).Task.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReactVideoEvent : Event
|
|
||||||
{
|
|
||||||
private readonly string _eventName;
|
|
||||||
private readonly JObject _eventData;
|
|
||||||
|
|
||||||
public ReactVideoEvent(string eventName, int viewTag, JObject eventData)
|
|
||||||
: base(viewTag)
|
|
||||||
{
|
|
||||||
_eventName = eventName;
|
|
||||||
_eventData = eventData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string EventName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _eventName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanCoalesce
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispatch(RCTEventEmitter eventEmitter)
|
|
||||||
{
|
|
||||||
eventEmitter.receiveEvent(ViewTag, EventName, _eventData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using ReactNative.UIManager.Annotations;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
class ReactVideoViewManager : SimpleViewManager<ReactVideoView>
|
|
||||||
{
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "RCTVideo";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<string, object> ExportedViewConstants
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "ScaleNone", ((int)Stretch.None).ToString() },
|
|
||||||
{ "ScaleToFill", ((int)Stretch.UniformToFill).ToString() },
|
|
||||||
{ "ScaleAspectFit", ((int)Stretch.Uniform).ToString() },
|
|
||||||
{ "ScaleAspectFill", ((int)Stretch.Fill).ToString() },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<string, object> ExportedCustomDirectEventTypeConstants
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var events = new Dictionary<string, object>();
|
|
||||||
var eventTypes = Enum.GetValues(typeof(ReactVideoEventType)).OfType<ReactVideoEventType>();
|
|
||||||
foreach (var eventType in eventTypes)
|
|
||||||
{
|
|
||||||
events.Add(eventType.GetEventName(), new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "registrationName", eventType.GetEventName() },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return events;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("src")]
|
|
||||||
public void SetSource(ReactVideoView view, JObject source)
|
|
||||||
{
|
|
||||||
view.Source = source.Value<string>("uri");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("resizeMode")]
|
|
||||||
public void SetResizeMode(ReactVideoView view, string resizeMode)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Resize Mode has not been implemented for WPF.");
|
|
||||||
// view.Stretch = (Stretch)int.Parse(resizeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("repeat")]
|
|
||||||
public void SetRepeat(ReactVideoView view, bool repeat)
|
|
||||||
{
|
|
||||||
view.IsLoopingEnabled = repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("paused")]
|
|
||||||
public void SetPaused(ReactVideoView view, bool paused)
|
|
||||||
{
|
|
||||||
view.IsPaused = paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("muted")]
|
|
||||||
public void SetMuted(ReactVideoView view, bool muted)
|
|
||||||
{
|
|
||||||
view.IsMuted = muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("volume", DefaultDouble = 1.0)]
|
|
||||||
public void SetVolume(ReactVideoView view, double volume)
|
|
||||||
{
|
|
||||||
view.Volume = volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("seek")]
|
|
||||||
public void SetSeek(ReactVideoView view, double? seek)
|
|
||||||
{
|
|
||||||
if (seek.HasValue)
|
|
||||||
{
|
|
||||||
view.Seek(seek.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("rate", DefaultDouble = 1.0)]
|
|
||||||
public void SetPlaybackRate(ReactVideoView view, double rate)
|
|
||||||
{
|
|
||||||
view.Rate = rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("playInBackground")]
|
|
||||||
public void SetPlayInBackground(ReactVideoView view, bool playInBackground)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Play in background has not been implemented on Windows.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Utilize MediaElement when user control enabled and MediaPlayer + VideoDrawing when disabled
|
|
||||||
[ReactProp("controls")]
|
|
||||||
public void SetControls(ReactVideoView view, bool controls)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("User controls have not been implemented on WPF.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("progressUpdateInterval")]
|
|
||||||
public void SetProgressUpdateInterval(ReactVideoView view, double progressUpdateInterval)
|
|
||||||
{
|
|
||||||
view.ProgressUpdateInterval = progressUpdateInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnDropViewInstance(ThemedReactContext reactContext, ReactVideoView view)
|
|
||||||
{
|
|
||||||
base.OnDropViewInstance(reactContext, view);
|
|
||||||
view.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ReactVideoView CreateViewInstance(ThemedReactContext reactContext)
|
|
||||||
{
|
|
||||||
return new ReactVideoView
|
|
||||||
{
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
|
|
||||||
</packages>
|
|
@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 14
|
|
||||||
VisualStudioVersion = 14.0.25420.1
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNativeVideo.Net46", "ReactNativeVideo.Net46\ReactNativeVideo.Net46.csproj", "{2D8406AB-0674-42D3-8FE3-41D251403DF8}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative.Net46", "..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj", "{22CBFF9C-FE36-43E8-A246-266C7635E662}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
|
||||||
..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{22cbff9c-fe36-43e8-a246-266c7635e662}*SharedItemsImports = 4
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|ARM = Debug|ARM
|
|
||||||
Debug|x64 = Debug|x64
|
|
||||||
Debug|x86 = Debug|x86
|
|
||||||
Release|ARM = Release|ARM
|
|
||||||
Release|x64 = Release|x64
|
|
||||||
Release|x86 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|ARM.ActiveCfg = Debug|x86
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x86.ActiveCfg = Debug|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x86.Build.0 = Debug|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|ARM.ActiveCfg = Release|x86
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x64.Build.0 = Release|x64
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x86.Build.0 = Release|x86
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.ActiveCfg = Debug|ARM
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.Build.0 = Debug|ARM
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.ActiveCfg = Debug|x86
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.Build.0 = Debug|x86
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.ActiveCfg = Release|ARM
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.Build.0 = Release|ARM
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.Build.0 = Release|x64
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.ActiveCfg = Release|x86
|
|
||||||
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.Build.0 = Release|x86
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
@ -1,29 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("ReactNativeVideo")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("")]
|
|
||||||
[assembly: AssemblyProduct("ReactNativeVideo")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
[assembly: ComVisible(false)]
|
|
@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
This file contains Runtime Directives, specifications about types your application accesses
|
|
||||||
through reflection and other dynamic code patterns. Runtime Directives are used to control the
|
|
||||||
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
|
|
||||||
library does not do any reflection, then you generally do not need to edit this file. However,
|
|
||||||
if your library reflects over types, especially types passed to it or derived from its types,
|
|
||||||
then you should write Runtime Directives.
|
|
||||||
|
|
||||||
The most common use of reflection in libraries is to discover information about types passed
|
|
||||||
to the library. Runtime Directives have three ways to express requirements on types passed to
|
|
||||||
your library.
|
|
||||||
|
|
||||||
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
|
|
||||||
Use these directives to reflect over types passed as a parameter.
|
|
||||||
|
|
||||||
2. SubTypes
|
|
||||||
Use a SubTypes directive to reflect over types derived from another type.
|
|
||||||
|
|
||||||
3. AttributeImplies
|
|
||||||
Use an AttributeImplies directive to indicate that your library needs to reflect over
|
|
||||||
types or methods decorated with an attribute.
|
|
||||||
|
|
||||||
For more information on writing Runtime Directives for libraries, please visit
|
|
||||||
http://go.microsoft.com/fwlink/?LinkID=391919
|
|
||||||
-->
|
|
||||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
|
||||||
<Library Name="ReactNativeVideo">
|
|
||||||
|
|
||||||
<!-- add directives for your library here -->
|
|
||||||
|
|
||||||
</Library>
|
|
||||||
</Directives>
|
|
@ -1,116 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
|
||||||
<ProjectGuid>{E8F5F57F-757E-4237-AD23-F7A8755427CD}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>ReactNativeVideo</RootNamespace>
|
|
||||||
<AssemblyName>ReactNativeVideo</AssemblyName>
|
|
||||||
<DefaultLanguage>en-US</DefaultLanguage>
|
|
||||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
|
||||||
<TargetPlatformVersion>10.0.14393.0</TargetPlatformVersion>
|
|
||||||
<TargetPlatformMinVersion>10.0.10586.0</TargetPlatformMinVersion>
|
|
||||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\ARM\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<OutputPath>bin\ARM\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>ARM</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<NoWarn>;2008</NoWarn>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
|
||||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
|
|
||||||
<None Include="project.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="ReactVideoPackage.cs" />
|
|
||||||
<Compile Include="ReactVideoView.cs" />
|
|
||||||
<Compile Include="ReactVideoViewManager.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="ReactVideoEventType.cs" />
|
|
||||||
<Compile Include="ReactVideoEventTypeExtensions.cs" />
|
|
||||||
<EmbeddedResource Include="Properties\ReactNativeVideo.rd.xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj">
|
|
||||||
<Project>{c7673ad5-e3aa-468c-a5fd-fa38154e205c}</Project>
|
|
||||||
<Name>ReactNative</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
|
||||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
|
@ -1,15 +0,0 @@
|
|||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
enum ReactVideoEventType
|
|
||||||
{
|
|
||||||
LoadStart,
|
|
||||||
Load,
|
|
||||||
Error,
|
|
||||||
Progress,
|
|
||||||
Seek,
|
|
||||||
End,
|
|
||||||
Stalled,
|
|
||||||
Resume,
|
|
||||||
ReadyForDisplay,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
using System;
|
|
||||||
using static System.FormattableString;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
static class ReactVideoEventTypeExtensions
|
|
||||||
{
|
|
||||||
public static string GetEventName(this ReactVideoEventType eventType)
|
|
||||||
{
|
|
||||||
switch (eventType)
|
|
||||||
{
|
|
||||||
case ReactVideoEventType.LoadStart:
|
|
||||||
return "onVideoLoadStart";
|
|
||||||
case ReactVideoEventType.Load:
|
|
||||||
return "onVideoLoad";
|
|
||||||
case ReactVideoEventType.Error:
|
|
||||||
return "onVideoError";
|
|
||||||
case ReactVideoEventType.Progress:
|
|
||||||
return "onVideoProgress";
|
|
||||||
case ReactVideoEventType.Seek:
|
|
||||||
return "onVideoSeek";
|
|
||||||
case ReactVideoEventType.End:
|
|
||||||
return "onVideoEnd";
|
|
||||||
case ReactVideoEventType.Stalled:
|
|
||||||
return "onPlaybackStalled";
|
|
||||||
case ReactVideoEventType.Resume:
|
|
||||||
return "onPlaybackResume";
|
|
||||||
case ReactVideoEventType.ReadyForDisplay:
|
|
||||||
return "onReadyForDisplay";
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException(
|
|
||||||
Invariant($"No event name added for event type '{eventType}'."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
using ReactNative.Bridge;
|
|
||||||
using ReactNative.Modules.Core;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
public class ReactVideoPackage : IReactPackage
|
|
||||||
{
|
|
||||||
public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
|
|
||||||
{
|
|
||||||
return Array.Empty<Type>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
|
|
||||||
{
|
|
||||||
return Array.Empty<INativeModule>();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<IViewManager> CreateViewManagers(ReactContext reactContext)
|
|
||||||
{
|
|
||||||
return new List<IViewManager>
|
|
||||||
{
|
|
||||||
new ReactVideoViewManager(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,365 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using ReactNative.UIManager.Events;
|
|
||||||
using System;
|
|
||||||
using Windows.ApplicationModel.Core;
|
|
||||||
using Windows.Media.Core;
|
|
||||||
using Windows.Media.Playback;
|
|
||||||
using Windows.UI.Core;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Controls;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
class ReactVideoView : MediaPlayerElement, IDisposable
|
|
||||||
{
|
|
||||||
public const string EVENT_PROP_SEEK_TIME = "seekTime";
|
|
||||||
|
|
||||||
private readonly DispatcherTimer _timer;
|
|
||||||
|
|
||||||
private bool _isLoopingEnabled;
|
|
||||||
private bool _isPaused;
|
|
||||||
private bool _isMuted;
|
|
||||||
private bool _isUserControlEnabled;
|
|
||||||
private bool _isCompleted;
|
|
||||||
private double _volume;
|
|
||||||
private double _rate;
|
|
||||||
|
|
||||||
public ReactVideoView()
|
|
||||||
{
|
|
||||||
_timer = new DispatcherTimer();
|
|
||||||
_timer.Interval = TimeSpan.FromMilliseconds(250.0);
|
|
||||||
_timer.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public new string Source
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var uri = value;
|
|
||||||
|
|
||||||
base.Source = MediaSource.CreateFromUri(new Uri(uri));
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.LoadStart.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "src", uri }
|
|
||||||
}));
|
|
||||||
|
|
||||||
ApplyModifiers();
|
|
||||||
SubscribeEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsLoopingEnabled
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isLoopingEnabled = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.IsLoopingEnabled = _isLoopingEnabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsMuted
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isMuted = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.IsMuted = _isMuted;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPaused
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isPaused = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
if (_isPaused)
|
|
||||||
{
|
|
||||||
mediaPlayer.Pause();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mediaPlayer.Play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsUserControlEnabled
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isUserControlEnabled = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.SystemMediaTransportControls.IsEnabled = _isUserControlEnabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Volume
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_volume = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.Volume = _volume;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double Rate
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_rate = value;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.PlaybackSession.PlaybackRate = _rate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double ProgressUpdateInterval
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_timer.Interval = TimeSpan.FromSeconds(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Seek(double seek)
|
|
||||||
{
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
mediaPlayer.PlaybackSession.Position = TimeSpan.FromSeconds(seek);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null)
|
|
||||||
{
|
|
||||||
_timer.Tick -= OnTick;
|
|
||||||
mediaPlayer.MediaOpened -= OnMediaOpened;
|
|
||||||
mediaPlayer.MediaFailed -= OnMediaFailed;
|
|
||||||
mediaPlayer.MediaEnded -= OnMediaEnded;
|
|
||||||
mediaPlayer.PlaybackSession.BufferingStarted -= OnBufferingStarted;
|
|
||||||
mediaPlayer.PlaybackSession.BufferingEnded -= OnBufferingEnded;
|
|
||||||
MediaPlayer.PlaybackSession.SeekCompleted -= OnSeekCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timer.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ApplyModifiers()
|
|
||||||
{
|
|
||||||
IsLoopingEnabled = _isLoopingEnabled;
|
|
||||||
IsMuted = _isMuted;
|
|
||||||
IsPaused = _isPaused;
|
|
||||||
IsUserControlEnabled = _isUserControlEnabled;
|
|
||||||
Volume = _volume;
|
|
||||||
Rate = _rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SubscribeEvents()
|
|
||||||
{
|
|
||||||
_timer.Tick += OnTick;
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
mediaPlayer.MediaOpened += OnMediaOpened;
|
|
||||||
mediaPlayer.MediaFailed += OnMediaFailed;
|
|
||||||
mediaPlayer.MediaEnded += OnMediaEnded;
|
|
||||||
mediaPlayer.PlaybackSession.BufferingStarted += OnBufferingStarted;
|
|
||||||
mediaPlayer.PlaybackSession.BufferingEnded += OnBufferingEnded;
|
|
||||||
mediaPlayer.PlaybackSession.SeekCompleted += OnSeekCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTick(object sender, object e)
|
|
||||||
{
|
|
||||||
var mediaPlayer = MediaPlayer;
|
|
||||||
if (mediaPlayer != null && !_isCompleted && !_isPaused)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Progress.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "currentTime", mediaPlayer.PlaybackSession.Position.TotalSeconds },
|
|
||||||
{ "playableDuration", 0.0 /* TODO */ }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaOpened(MediaPlayer sender, object args)
|
|
||||||
{
|
|
||||||
RunOnDispatcher(delegate
|
|
||||||
{
|
|
||||||
var width = sender.PlaybackSession.NaturalVideoWidth;
|
|
||||||
var height = sender.PlaybackSession.NaturalVideoHeight;
|
|
||||||
var orientation = (width > height) ? "landscape" : "portrait";
|
|
||||||
var size = new JObject
|
|
||||||
{
|
|
||||||
{ "width", width },
|
|
||||||
{ "height", height },
|
|
||||||
{ "orientation", orientation }
|
|
||||||
};
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Load.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "duration", sender.PlaybackSession.NaturalDuration.TotalSeconds },
|
|
||||||
{ "currentTime", sender.PlaybackSession.Position.TotalSeconds },
|
|
||||||
{ "naturalSize", size },
|
|
||||||
{ "canPlayFastForward", false },
|
|
||||||
{ "canPlaySlowForward", false },
|
|
||||||
{ "canPlaySlow", false },
|
|
||||||
{ "canPlayReverse", false },
|
|
||||||
{ "canStepBackward", false },
|
|
||||||
{ "canStepForward", false }
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaFailed(MediaPlayer sender, MediaPlayerFailedEventArgs args)
|
|
||||||
{
|
|
||||||
var errorData = new JObject
|
|
||||||
{
|
|
||||||
{ "what", args.Error.ToString() },
|
|
||||||
{ "extra", args.ErrorMessage }
|
|
||||||
};
|
|
||||||
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Error.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject
|
|
||||||
{
|
|
||||||
{ "error", errorData }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnMediaEnded(MediaPlayer sender, object args)
|
|
||||||
{
|
|
||||||
_isCompleted = true;
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.End.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
null));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBufferingStarted(MediaPlaybackSession sender, object args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Stalled.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnBufferingEnded(MediaPlaybackSession sender, object args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher
|
|
||||||
.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Resume.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSeekCompleted(MediaPlaybackSession sender, object args)
|
|
||||||
{
|
|
||||||
this.GetReactContext()
|
|
||||||
.GetNativeModule<UIManagerModule>()
|
|
||||||
.EventDispatcher.DispatchEvent(
|
|
||||||
new ReactVideoEvent(
|
|
||||||
ReactVideoEventType.Seek.GetEventName(),
|
|
||||||
this.GetTag(),
|
|
||||||
new JObject()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async void RunOnDispatcher(DispatchedHandler action)
|
|
||||||
{
|
|
||||||
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, action).AsTask().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReactVideoEvent : Event
|
|
||||||
{
|
|
||||||
private readonly string _eventName;
|
|
||||||
private readonly JObject _eventData;
|
|
||||||
|
|
||||||
public ReactVideoEvent(string eventName, int viewTag, JObject eventData)
|
|
||||||
: base(viewTag)
|
|
||||||
{
|
|
||||||
_eventName = eventName;
|
|
||||||
_eventData = eventData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string EventName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _eventName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanCoalesce
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispatch(RCTEventEmitter eventEmitter)
|
|
||||||
{
|
|
||||||
eventEmitter.receiveEvent(ViewTag, EventName, _eventData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,137 +0,0 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using ReactNative.UIManager;
|
|
||||||
using ReactNative.UIManager.Annotations;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
|
|
||||||
namespace ReactNativeVideo
|
|
||||||
{
|
|
||||||
class ReactVideoViewManager : SimpleViewManager<ReactVideoView>
|
|
||||||
{
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "RCTVideo";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<string, object> ExportedViewConstants
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "ScaleNone", ((int)Stretch.None).ToString() },
|
|
||||||
{ "ScaleToFill", ((int)Stretch.UniformToFill).ToString() },
|
|
||||||
{ "ScaleAspectFit", ((int)Stretch.Uniform).ToString() },
|
|
||||||
{ "ScaleAspectFill", ((int)Stretch.Fill).ToString() },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IReadOnlyDictionary<string, object> ExportedCustomDirectEventTypeConstants
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var events = new Dictionary<string, object>();
|
|
||||||
var eventTypes = Enum.GetValues(typeof(ReactVideoEventType)).OfType<ReactVideoEventType>();
|
|
||||||
foreach (var eventType in eventTypes)
|
|
||||||
{
|
|
||||||
events.Add(eventType.GetEventName(), new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "registrationName", eventType.GetEventName() },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return events;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("src")]
|
|
||||||
public void SetSource(ReactVideoView view, JObject source)
|
|
||||||
{
|
|
||||||
view.Source = source.Value<string>("uri");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("resizeMode")]
|
|
||||||
public void SetResizeMode(ReactVideoView view, string resizeMode)
|
|
||||||
{
|
|
||||||
view.Stretch = (Stretch)int.Parse(resizeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("repeat")]
|
|
||||||
public void SetRepeat(ReactVideoView view, bool repeat)
|
|
||||||
{
|
|
||||||
view.IsLoopingEnabled = repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("paused")]
|
|
||||||
public void SetPaused(ReactVideoView view, bool paused)
|
|
||||||
{
|
|
||||||
view.IsPaused = paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("muted")]
|
|
||||||
public void SetMuted(ReactVideoView view, bool muted)
|
|
||||||
{
|
|
||||||
view.IsMuted = muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("volume", DefaultDouble = 1.0)]
|
|
||||||
public void SetVolume(ReactVideoView view, double volume)
|
|
||||||
{
|
|
||||||
view.Volume = volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("seek")]
|
|
||||||
public void SetSeek(ReactVideoView view, double? seek)
|
|
||||||
{
|
|
||||||
if (seek.HasValue)
|
|
||||||
{
|
|
||||||
view.Seek(seek.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("rate", DefaultDouble = 1.0)]
|
|
||||||
public void SetPlaybackRate(ReactVideoView view, double rate)
|
|
||||||
{
|
|
||||||
view.Rate = rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("playInBackground")]
|
|
||||||
public void SetPlayInBackground(ReactVideoView view, bool playInBackground)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException("Play in background has not been implemented on Windows.");
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("controls")]
|
|
||||||
public void SetControls(ReactVideoView view, bool controls)
|
|
||||||
{
|
|
||||||
view.IsUserControlEnabled = controls;
|
|
||||||
}
|
|
||||||
|
|
||||||
[ReactProp("progressUpdateInterval")]
|
|
||||||
public void SetProgressUpdateInterval(ReactVideoView view, double progressUpdateInterval)
|
|
||||||
{
|
|
||||||
view.ProgressUpdateInterval = progressUpdateInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnDropViewInstance(ThemedReactContext reactContext, ReactVideoView view)
|
|
||||||
{
|
|
||||||
base.OnDropViewInstance(reactContext, view);
|
|
||||||
view.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override ReactVideoView CreateViewInstance(ThemedReactContext reactContext)
|
|
||||||
{
|
|
||||||
return new ReactVideoView
|
|
||||||
{
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
|
|
||||||
"Newtonsoft.Json": "10.0.3"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"uap10.0": {}
|
|
||||||
},
|
|
||||||
"runtimes": {
|
|
||||||
"win10-arm": {},
|
|
||||||
"win10-arm-aot": {},
|
|
||||||
"win10-x86": {},
|
|
||||||
"win10-x86-aot": {},
|
|
||||||
"win10-x64": {},
|
|
||||||
"win10-x64-aot": {}
|
|
||||||
}
|
|
||||||
}
|
|
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>
|
Loading…
Reference in New Issue
Block a user