Skip to content

Instantly share code, notes, and snippets.

@AndreiCalazans
Created October 19, 2020 11:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndreiCalazans/e7c537687c0c5d7d6016688a67be99a9 to your computer and use it in GitHub Desktop.
Save AndreiCalazans/e7c537687c0c5d7d6016688a67be99a9 to your computer and use it in GitHub Desktop.
Player with own ShadowView and concrete implementation for a WebPlayer.
import React, { Component } from "react";
import {
requireNativeComponent,
UIManager,
findNodeHandle,
NativeModules,
} from "react-native";
const MKPlayerView = requireNativeComponent("MKPlayerView");
const MKPlayerManager = NativeModules.MKPlayerManager;
type NativeEvent<T extends {}> = {
nativeEvent: T;
};
type MKPlayerProps = {
src: string;
onStateChange: (event: NativeEvent<any>) => void;
onPositionChange: (event: NativeEvent<any>) => void;
onError: (event: NativeEvent<any>) => void;
};
export class MKPlayer extends Component<MKPlayerProps> {
play() {
MKPlayerManager.play();
}
pause() {
MKPlayerManager.pause();
}
stop() {
MKPlayerManager.stop();
}
preload() {
MKPlayerManager.preload();
}
seek(positionInSeconds: number) {
MKPlayerManager.seek(positionInSeconds);
}
liveNow() {
MKPlayerManager.liveNow();
}
setMaxBandwidth(maxBandwidthKbps: number) {
MKPlayerManager.setMaxBandwidth(maxBandwidthKbps);
}
getVideoPosition(): Promise<any> {
return MKPlayerManager.getVideoPosition();
}
getVideoDuration(): Promise<any> {
return MKPlayerManager.getVideoDuration();
}
getProgramInfo(): Promise<any> {
return MKPlayerManager.getProgramInfo();
}
enableClosedCaptions(enabled: boolean) {
MKPlayerManager.enableClosedCaptions(enabled);
}
getClosedCaptionsState(): Promise<any> {
return MKPlayerManager.getClosedCaptionsState();
}
getSubtitleTracks(): Promise<any> {
return MKPlayerManager.getSubtitleTracks();
}
getCurrentSubtitleTrack(): Promise<any> {
return MKPlayerManager.getCurrentSubtitleTrack();
}
setSubtitleTrack(subtitleTrack: string) {
MKPlayerManager.setSubtitleTrack(subtitleTrack);
}
setAudioTrack(audioTrack: string) {
MKPlayerManager.setAudioTrack(audioTrack);
}
getAudioTracks(): Promise<any> {
return MKPlayerManager.getAudioTracks();
}
getCurrentAudioTrack(): Promise<any> {
return MKPlayerManager.getCurrentAudioTrack();
}
getTimeshiftEnabled(): Promise<any> {
return MKPlayerManager.getTimeshiftEnabled();
}
getFFEnabled(): Promise<any> {
return MKPlayerManager.getFFEnabled();
}
getRWEnabled(): Promise<any> {
return MKPlayerManager.getFFEnabled();
}
render() {
return <MKPlayerView {...this.props} />;
}
}
#pragma once
#include <youireact/modules/components/AbstractComponentManagerModule.h>
#include <youireact/modules/components/IViewManager.h>
#include <platform/YiWebBridgeLocator.h>
#include <youireact/nodes/ReactComponent.h>
using namespace yi::react;
class YI_RN_MODULE(MKPlayerManager, AbstractComponentManagerModule), public IViewManager
{
public:
YI_RN_EXPORT_NAME(MKPlayerManager);
~MKPlayerManager();
ReactComponent * reactInstance;
void handleRectangleUpdate(const YI_RECT_REL &rVideoRectangle);
// Add methods that will be available to JSX:
YI_RN_EXPORT_METHOD(play)();
YI_RN_EXPORT_METHOD(pause)();
YI_RN_EXPORT_METHOD(stop)();
YI_RN_EXPORT_METHOD(preload)();
YI_RN_EXPORT_METHOD(seek)(uint64_t secondsPosition);
YI_RN_EXPORT_METHOD(liveNow)();
YI_RN_EXPORT_METHOD(setMaxBandwidth)(uint64_t maxBandwidthKbps);
YI_RN_EXPORT_METHOD(getVideoPosition)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getVideoDuration)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getProgramInfo)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(enableClosedCaptions)(bool enabled);
YI_RN_EXPORT_METHOD(getClosedCaptionsState)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getSubtitleTracks)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getCurrentSubtitleTrack)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(setSubtitleTrack)(const std::string& subtitleTrack);
YI_RN_EXPORT_METHOD(setAudioTrack)(const std::string& audioTrack);
YI_RN_EXPORT_METHOD(getAudioTracks)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getCurrentAudioTrack)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getTimeshiftEnabled)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getFFEnabled)(Callback resolve, Callback reject);
YI_RN_EXPORT_METHOD(getRWEnabled)(Callback resolve, Callback reject);
YI_RN_DEFINE_COMPONENT_MODULE();
// @TODO In the future when we move to more platforms we can overload these
void onStateChange(const yi::rapidjson::Value &eventValue);
void onPlayerError(const yi::rapidjson::Value &eventValue);
void onPositionChange(const yi::rapidjson::Value &eventValue);
YI_RECT_REL m_previousVideoRectangle;
// @TODO In the future when we move to more platforms we can decide if this will be used only by Tizen.
std::vector<uint64_t> registeredEvents;
bool messageHandlersRegistered;
uint64_t registerEventHandler(const CYIString &eventName, CYIWebMessagingBridge::EventCallback &&eventCallback);
void unregisterEventHandler(uint64_t &eventHandlerId);
void registerEventHandlers();
void unregisterEventHandlers();
protected:
virtual void SetupProperties() override;
};
#include "mk_player/MKPlayerManager.h"
#include "mk_player/MKPlayerView.h"
#include <youireact/NativeModuleRegistry.h>
#include <folly/dynamic.h>
/*
* MKPlayerManager implements handles the entire bridge.
* It is responsible for:
* - Receiving props from JSX.
* - Emitting events to JSX.
* - Implementing the JSX MKVideo methods
* - And communicating with Tizen via the WebMessaging module.
*
* WARNING: The PlayerManager naively assumes there can only ever be one Player at once. Further work needs to
* be put into handling multiple players.
*
* HOW TO ADD JSX PROPS?
* - FOR DATA
* Add the prop definition in MKPlayerManager::GetNativeProps() and define a callback to handle it in MKPlayerManager::SetupProperties(),
* notice YI_RN_DEFINE_PROPERTY is used to define the callback to handle the setter.
*
*
* - FOR ON EVENT PROPS:
* In MKPlayerView.h define both the direct event plus its name, i.e.,
YI_RN_EXPORT_DIRECT_EVENT(onStateChange);
YI_RN_EXPORT_DIRECT_EVENT_NAME(onStateChangeName);
Then in MKPlayerView.cpp define the YI_RN_DEFINE_DIRECT_EVENT_NAME & call
the SetDirectEvent(MKPlayerView::onStateChangeName, onStateChange); in the constructor MKPlayerView::MKPlyerView.
With the above you have defined a prop event that can used in JSX as <MKPlayer onStateChange={this.handleOnStateChange} .../>
To trigget the above event in React Native, you can call the reactInstance.EmitDirectEvent function. This function holds a pointer to
the SetDirectEvent function from MKPlayerView.
*
*
*
* HOW TO ADD A METHOD TO CALL IN REACT NATIVE JSX?
* Define a export method in MKPlayerManager.h like:
* YI_RN_EXPORT_METHOD(play)();
* Then in the MKPlayerManager_WebPlayer implement the method by using:
* YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, play)()
*
* HOW TO CALL FUNCTION IN TIZEN JS SCOPE?
* Use functions callTizenWithArgs or callTizenWithoutArgs for this. See how it is being used in the methods below.
*
* HOW TO CALL C++ LAYER FROM TIZEN JS SCOPE?
* To call a method in this C++ class from Tizen's JS scope you must first register a call event as follow:
registeredEvents.push_back(registerEventHandler("onPlayerError", std::bind(&MKPlayerManager::onPlayerError, this, std::placeholders::_1)));
noticy OnPlayerError is a method in MKPlayerManager to handle this call.
In Tizen's JS scope you can use CYIMessaging.sendEvent to send the event to C++ as follow:
CYIMessaging.sendEvent({
context: "CustomVideoPlayer",
name: "onPlayerError",
data: data,
});
* */
using namespace yi::react;
#define TAG "MKPlayerManager"
#define TIZEN_CLASS_NAME "CustomVideoPlayer"
typedef std::function<void(std::vector<folly::dynamic>)> JsCallback;
void callTizenWithoutArgs(const std::string& methodName) {
CYIWebMessagingBridge *pBridge = CYIWebBridgeLocator::GetWebMessagingBridge();
bool messageSent = false;
CYIWebMessagingBridge::FutureResponse futureResponse = pBridge->CallStaticFunction(yi::rapidjson::Document(), TIZEN_CLASS_NAME, methodName, &messageSent);
}
void callTizenWithoutArgs(const std::string& methodName, JsCallback resolve, JsCallback reject) {
CYIWebMessagingBridge *pBridge = CYIWebBridgeLocator::GetWebMessagingBridge();
bool messageSent = false;
CYIWebMessagingBridge::FutureResponse futureResponse = pBridge->CallStaticFunction(yi::rapidjson::Document(), TIZEN_CLASS_NAME, methodName, &messageSent);
if (!messageSent)
reject({});
bool valueAssigned = false;
CYIWebMessagingBridge::Response response = futureResponse.Take(CYIWebMessagingBridge::DEFAULT_RESPONSE_TIMEOUT_MS, &valueAssigned);
if (!valueAssigned)
reject({});
const yi::rapidjson::Value *pData = response.GetResult();
resolve({ToDynamic(*pData)});
}
struct Message {
yi::rapidjson::Document messageDocument; // Message Document to send Data over to tizen.
yi::rapidjson::Value arguments; // Arguments Arrray required for JS functions functionName(args: any[]);
yi::rapidjson::MemoryPoolAllocator<yi::rapidjson::CrtAllocator> &messageAllocator; // Allocated memory which rapidjson requires.
Message():
messageDocument(yi::rapidjson::kObjectType),
arguments(yi::rapidjson::kArrayType),
messageAllocator(messageDocument.GetAllocator())
{}
void addArgument(const yi::rapidjson::Value& arg) {
yi::rapidjson::Value argValue(arg, messageAllocator);
arguments.PushBack(argValue, messageAllocator);
}
};
void callTizenWithArgs(const std::string& methodName, Message msg) {
CYIWebMessagingBridge *pBridge = CYIWebBridgeLocator::GetWebMessagingBridge();
bool messageSent = false;
CYIWebMessagingBridge::FutureResponse futureResponse = pBridge->CallStaticFunctionWithArgs(std::move(msg.messageDocument), TIZEN_CLASS_NAME, methodName, std::move(msg.arguments), &messageSent);
}
YI_RN_INSTANTIATE_MODULE(MKPlayerManager, AbstractComponentManagerModule);
YI_RN_REGISTER_MODULE(MKPlayerManager);
YI_RN_OVERRIDE_OnInit(MKPlayerManager);
YI_RN_OVERRIDE_OnLayoutApplied(MKPlayerManager);
YI_RN_OVERRIDE_ApplyProps(MKPlayerManager);
void MKPlayerManager::DismantleCounterpart(ReactComponent *pInstance)
{
if (pInstance)
{
DismantleCounterpartPriv(*pInstance); \
}
reactInstance = nullptr;
}
void MKPlayerManager::ConfigureCounterpart(ReactComponent *pInstance)
{
if (pInstance)
{
reactInstance = pInstance;
ConfigureCounterpartPriv(*pInstance);
}
}
MKPlayerManager::~MKPlayerManager() {
reactInstance = nullptr;
}
folly::dynamic MKPlayerManager::GetNativeProps()
{
folly::dynamic superProps = IViewManager::GetNativeProps();
folly::dynamic props = folly::dynamic::object("src", "string");
return folly::dynamic::merge(superProps, props);
}
void MKPlayerManager::SetupProperties()
{
IViewManager::SetupProperties();
YI_RN_DEFINE_PROPERTY("src", [this](MKPlayerView &self, std::string src) {
registerEventHandlers();
YI_LOGD(TAG, "Initialize");
Message msg;
yi::rapidjson::Value srcValue(src.data(), msg.messageAllocator);
msg.addArgument(srcValue);
callTizenWithArgs("initialize", std::move(msg));
});
}
void MKPlayerManager::handleRectangleUpdate(const YI_RECT_REL &rVideoRectangle) {
// handleRectangleUpdate is called on every frame.
if(rVideoRectangle == m_previousVideoRectangle) {
return;
}
YI_LOGD(TAG, "handleRectangleUpdate");
m_previousVideoRectangle = rVideoRectangle;
Message msg;
msg.addArgument(yi::rapidjson::Value().SetUint(rVideoRectangle.x));
msg.addArgument(yi::rapidjson::Value().SetUint(rVideoRectangle.y));
msg.addArgument(yi::rapidjson::Value().SetUint(rVideoRectangle.width));
msg.addArgument(yi::rapidjson::Value().SetUint(rVideoRectangle.height));
callTizenWithArgs("setVideoRectangle", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, play)(){
YI_LOGD(TAG, "Play");
callTizenWithoutArgs("play");
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, pause)(){
YI_LOGD(TAG, "Pause");
callTizenWithoutArgs("pause");
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, stop)(){
YI_LOGD(TAG, "stop");
// Check with Varun if we should wait for AMC to destroy then remove event listeners? Current implementation could lead to us not getting any errors if destroy goes bad.
unregisterEventHandlers();
callTizenWithoutArgs("destroy");
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, preload)(){
YI_LOGD(TAG, "Preload");
callTizenWithoutArgs("preload");
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, seek)(uint64_t secondsPosition){
YI_LOGD(TAG, "Preload");
Message msg;
msg.addArgument(yi::rapidjson::Value().SetUint64(secondsPosition));
callTizenWithArgs("preload", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, liveNow)(){
YI_LOGD(TAG, "liveNow");
callTizenWithoutArgs("liveNow");
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, setMaxBandwidth)(uint64_t maxBandwidthKbps){
YI_LOGD(TAG, "setMaxBandwidth");
Message msg;
msg.addArgument(yi::rapidjson::Value().SetUint64(maxBandwidthKbps));
callTizenWithArgs("setMaxBandwidth", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getVideoPosition)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getVideoPosition");
callTizenWithoutArgs("getVideoPosition", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getVideoDuration)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getVideoDuration");
callTizenWithoutArgs("getVideoDuration", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getProgramInfo)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getProgramInfo");
callTizenWithoutArgs("getProgramInfo", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, enableClosedCaptions)(bool enabled){
YI_LOGD(TAG, "enableClosedCaptions");
Message msg;
msg.addArgument(yi::rapidjson::Value().SetBool(enabled));
callTizenWithArgs("enableClosedCaptions", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getClosedCaptionsState)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getClosedCaptionsState");
callTizenWithoutArgs("getClosedCaptionsState", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getSubtitleTracks)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getSubtitleTracks");
callTizenWithoutArgs("getSubtitleTracks", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getCurrentSubtitleTrack)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getCurrentSubtitleTrack");
callTizenWithoutArgs("getCurrentSubtitleTrack", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, setSubtitleTrack)(const std::string& subtitleTrack){
YI_LOGD(TAG, "setSubtitleTrack");
Message msg;
yi::rapidjson::Value subtitleTrackValue(subtitleTrack.data(), msg.messageAllocator);
msg.addArgument(subtitleTrackValue);
callTizenWithArgs("setSubtitleTrack", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, setAudioTrack)(const std::string& audioTrack){
YI_LOGD(TAG, "setAudioTrack");
Message msg;
yi::rapidjson::Value audioTrackValue(audioTrack.data(), msg.messageAllocator);
msg.addArgument(audioTrackValue);
callTizenWithArgs("setAudioTrack", std::move(msg));
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getAudioTracks)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getAudioTracks");
callTizenWithoutArgs("getAudioTracks", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getCurrentAudioTrack)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getCurrentAudioTrack");
callTizenWithoutArgs("getCurrentAudioTrack", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getTimeshiftEnabled)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getTimeshiftEnabled");
callTizenWithoutArgs("getTimeshiftEnabled", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getFFEnabled)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getFFEnabled");
callTizenWithoutArgs("getFFEnabled", resolve, reject);
};
YI_RN_DEFINE_EXPORT_METHOD(MKPlayerManager, getRWEnabled)(Callback resolve, Callback reject){
YI_LOGD(TAG, "getRWEnabled");
callTizenWithoutArgs("getRWEnabled", resolve, reject);
};
void MKPlayerManager::onStateChange(const yi::rapidjson::Value &eventValue) {
reactInstance->EmitDirectEvent(MKPlayerView::onStateChangeName, {ToDynamic(eventValue)});
}
void MKPlayerManager::onPlayerError(const yi::rapidjson::Value &eventValue) {
reactInstance->EmitDirectEvent(MKPlayerView::onErrorName, {ToDynamic(eventValue)});
}
void MKPlayerManager::onPositionChange(const yi::rapidjson::Value &eventValue) {
reactInstance->EmitDirectEvent(MKPlayerView::onPositionChangeName, {ToDynamic(eventValue)});
}
uint64_t MKPlayerManager::registerEventHandler(const CYIString &eventName, CYIWebMessagingBridge::EventCallback &&eventCallback)
{
return CYIWebBridgeLocator::GetWebMessagingBridge()->RegisterEventHandler(TIZEN_CLASS_NAME, eventName.GetData(), std::move(eventCallback));
}
void MKPlayerManager::unregisterEventHandler(uint64_t &eventHandlerId)
{
CYIWebBridgeLocator::GetWebMessagingBridge()->UnregisterEventHandler(eventHandlerId);
eventHandlerId = 0;
}
void MKPlayerManager::registerEventHandlers()
{
if (messageHandlersRegistered)
{
return;
}
registeredEvents.push_back(registerEventHandler("onStateChange", std::bind(&MKPlayerManager::onStateChange, this, std::placeholders::_1)));
registeredEvents.push_back(registerEventHandler("onPlayerError", std::bind(&MKPlayerManager::onPlayerError, this, std::placeholders::_1)));
registeredEvents.push_back(registerEventHandler("onPositionChange", std::bind(&MKPlayerManager::onPositionChange, this, std::placeholders::_1)));
messageHandlersRegistered = true;
}
void MKPlayerManager::unregisterEventHandlers()
{
if (!messageHandlersRegistered)
{
return;
}
for (auto &event : registeredEvents) {
unregisterEventHandler(event);
}
registeredEvents.clear();
messageHandlersRegistered = false;
}
#include "MKPlayerView.h"
#include <youireact/ViewBuilder.h>
#include <youireact/NativeModuleRegistry.h>
#include <youireact/props/DirectEventTypes.h>
#include <youireact/IBridge.h>
using namespace yi::react;
#define LOG_TAG "MKPlayerView"
YI_TYPE_DEF_INST(MKPlayerView, ShadowView)
YI_RN_REGISTER_VIEW_MODULE(MKPlayerView);
YI_RN_DEFINE_DIRECT_EVENT_NAME(MKPlayerView, onStateChangeName);
YI_RN_DEFINE_DIRECT_EVENT_NAME(MKPlayerView, onPositionChangeName);
YI_RN_DEFINE_DIRECT_EVENT_NAME(MKPlayerView, onErrorName);
MKPlayerView::MKPlayerView()
: CYIVideoSurfacePlatform(CYIVideoSurface::Capabilities::Translate | CYIVideoSurface::Capabilities::Scale | CYIVideoSurface::Capabilities::Opacity)
{
SetDirectEvent(MKPlayerView::onStateChangeName, onStateChange);
SetDirectEvent(MKPlayerView::onPositionChangeName, onPositionChange);
SetDirectEvent(MKPlayerView::onErrorName, onError);
}
MKPlayerView::~MKPlayerView()
{
playerManager = nullptr;
}
std::unique_ptr<CYISceneNode> MKPlayerView::CreateCounterpart(CYISceneManager *pSceneManager)
{
return ViewBuilder::CreateVideoView(pSceneManager, glm::vec3(1.0f, 1.0f, 1.0f));
}
bool MKPlayerView::OnInit() {
playerManager = GetBridge().GetModule<MKPlayerManager>();
GetCounterpart()->SetVideoSurface(this);
return true;
}
const CYIVideoSurfaceView *MKPlayerView::GetCounterpart() const
{
return static_cast<const CYIVideoSurfaceView *>(ShadowView::GetCounterpart());
}
CYIVideoSurfaceView *MKPlayerView::GetCounterpart()
{
return static_cast<CYIVideoSurfaceView *>(ShadowView::GetCounterpart());
}
void MKPlayerView::OnLayoutApplied()
{
ShadowView::OnLayoutApplied();
auto pVideoNode = GetCounterpart()->GetNode("_VideoNode");
pVideoNode->SetSize(GetCounterpart()->GetSize());
EmitDirectEvent(DirectEvents::onLayout);
}
void MKPlayerView::SetVideoRectangle(const YI_RECT_REL &rVideoRectangle)
{
if (playerManager) {
playerManager->handleRectangleUpdate(rVideoRectangle);
}
}
#pragma once
#include <youireact/nodes/ShadowView.h>
#include <player/YiVideoSurfaceView.h>
#include <player/YiVideoSurfacePlatform.h>
#include <youireact/props/DirectEventTypes.h>
#include "MKPlayerManager.h"
using namespace yi::react;
class MKPlayerView
: public ShadowView, public CYIVideoSurfacePlatform
{
public:
MKPlayerView();
virtual ~MKPlayerView() final;
YI_RN_EXPORT_NAME(MKPlayerView);
YI_RN_DECLARE_MANAGER(MKPlayerManager);
virtual const CYIVideoSurfaceView *GetCounterpart() const override;
virtual CYIVideoSurfaceView *GetCounterpart() override;
virtual bool OnInit() override;
virtual void SetVideoRectangle(const YI_RECT_REL &rVideoRectangle) override;
MKPlayerManager * playerManager;
YI_RN_EXPORT_DIRECT_EVENT(onStateChange);
YI_RN_EXPORT_DIRECT_EVENT_NAME(onStateChangeName);
YI_RN_EXPORT_DIRECT_EVENT(onPositionChange);
YI_RN_EXPORT_DIRECT_EVENT_NAME(onPositionChangeName);
YI_RN_EXPORT_DIRECT_EVENT(onError);
YI_RN_EXPORT_DIRECT_EVENT_NAME(onErrorName);
private:
virtual std::unique_ptr<CYISceneNode> CreateCounterpart(CYISceneManager *pSceneManager) final;
virtual void OnLayoutApplied() final;
YI_TYPE_BASES(MKPlayerView, ShadowView);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment