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
|
||||
<details>
|
||||
<summary>Windows details</summary>
|
||||
<summary>Windows RNW C++/WinRT details</summary>
|
||||
|
||||
Make the following additions to the given files manually:
|
||||
|
||||
#### **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
|
||||
* UWP: Select `node_modules\react-native-video\windows\ReactNativeVideo\ReactNativeVideo.csproj`
|
||||
* WPF: Select `node_modules\react-native-video\windows\ReactNativeVideo.Net46\ReactNativeVideo.Net46.csproj`
|
||||
Select `node_modules\react-native-video\windows\ReactNativeVideoCPP\ReactNativeVideoCPP.vcxproj`
|
||||
|
||||
#### **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...
|
||||
* UWP: Check `ReactNativeVideo` from Solution Projects.
|
||||
* WPF: Check `ReactNativeVideo.Net46` from Solution Projects.
|
||||
Check `ReactNativeVideoCPP` 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.
|
||||
```cs
|
||||
using ReactNative;
|
||||
using ReactNative.Modules.Core;
|
||||
using ReactNative.Shell;
|
||||
using ReactNativeVideo; // <-- Add this
|
||||
using System.Collections.Generic;
|
||||
...
|
||||
Add `#include "winrt/ReactNativeVideoCPP.h"`.
|
||||
|
||||
public override List<IReactPackage> Packages
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<IReactPackage>
|
||||
{
|
||||
new MainReactPackage(),
|
||||
new ReactVideoPackage(), // <-- Add this
|
||||
};
|
||||
}
|
||||
}
|
||||
#### **app.cpp**
|
||||
|
||||
Add `PackageProviders().Append(winrt::ReactNativeVideoCPP::ReactPackageProvider());` before `InitializeComponent();`.
|
||||
|
||||
...
|
||||
```
|
||||
</details>
|
||||
|
||||
### 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