mirror of https://github.com/axmolengine/axmol.git
Merge pull request #6555 from Dhilan007/v3_video
issue #4859:Add a widget to play video
This commit is contained in:
commit
56622dc765
|
@ -1123,6 +1123,8 @@
|
|||
3E26D40518ACB5D100834404 /* CCImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E26D40418ACB5D100834404 /* CCImage.cpp */; };
|
||||
3E26D40618ACB5D100834404 /* CCImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3E26D40418ACB5D100834404 /* CCImage.cpp */; };
|
||||
3E26D40818ACB63900834404 /* CCDevice.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3E26D40718ACB63900834404 /* CCDevice.mm */; };
|
||||
3EA0FB5B191B92CC00B170C8 /* UIVideoWidget.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EA0FB59191B92CC00B170C8 /* UIVideoWidget.h */; };
|
||||
3EA0FB5C191B92CC00B170C8 /* UIVideoWidgetIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3EA0FB5A191B92CC00B170C8 /* UIVideoWidgetIOS.mm */; };
|
||||
460E468118080832000CDD6D /* cocos-ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A167D21807AF4D005B8026 /* cocos-ext.h */; };
|
||||
460E468218080836000CDD6D /* cocos-ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A167D21807AF4D005B8026 /* cocos-ext.h */; };
|
||||
460E477B180808F5000CDD6D /* ExtensionMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 46A168321807AF4E005B8026 /* ExtensionMacros.h */; };
|
||||
|
@ -2314,6 +2316,8 @@
|
|||
37936A3E1869B76800E974DD /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = "<group>"; };
|
||||
3E26D40418ACB5D100834404 /* CCImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCImage.cpp; sourceTree = "<group>"; };
|
||||
3E26D40718ACB63900834404 /* CCDevice.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CCDevice.mm; sourceTree = "<group>"; };
|
||||
3EA0FB59191B92CC00B170C8 /* UIVideoWidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIVideoWidget.h; sourceTree = "<group>"; };
|
||||
3EA0FB5A191B92CC00B170C8 /* UIVideoWidgetIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIVideoWidgetIOS.mm; sourceTree = "<group>"; };
|
||||
46A15FCC1807A544005B8026 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; name = AUTHORS; path = ../AUTHORS; sourceTree = "<group>"; };
|
||||
46A15FCE1807A544005B8026 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; name = README.md; path = ../README.md; sourceTree = "<group>"; };
|
||||
46A15FE11807A56F005B8026 /* Export.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Export.h; sourceTree = "<group>"; };
|
||||
|
@ -3973,6 +3977,8 @@
|
|||
2905F9E618CF08D000240AA3 /* ui */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA0FB59191B92CC00B170C8 /* UIVideoWidget.h */,
|
||||
3EA0FB5A191B92CC00B170C8 /* UIVideoWidgetIOS.mm */,
|
||||
2905F9E918CF08D000240AA3 /* CocosGUI.cpp */,
|
||||
2905F9EA18CF08D000240AA3 /* CocosGUI.h */,
|
||||
2905F9EB18CF08D000240AA3 /* GUIDefine.h */,
|
||||
|
@ -5468,6 +5474,7 @@
|
|||
1A5701A0180BCB590088DEC7 /* CCFont.h in Headers */,
|
||||
1A5701A4180BCB590088DEC7 /* CCFontAtlas.h in Headers */,
|
||||
1A5701A8180BCB590088DEC7 /* CCFontAtlasCache.h in Headers */,
|
||||
3EA0FB5B191B92CC00B170C8 /* UIVideoWidget.h in Headers */,
|
||||
500DC98919106300007B91BF /* CCNS.h in Headers */,
|
||||
1A5701B4180BCB590088DEC7 /* CCFontFNT.h in Headers */,
|
||||
1A5701B8180BCB5A0088DEC7 /* CCFontFreeType.h in Headers */,
|
||||
|
@ -6557,6 +6564,7 @@
|
|||
50FCEB9818C72017004AD434 /* CheckBoxReader.cpp in Sources */,
|
||||
1A570076180BC5A10088DEC7 /* CCActionGrid3D.cpp in Sources */,
|
||||
500DC99D19106300007B91BF /* CCValue.cpp in Sources */,
|
||||
3EA0FB5C191B92CC00B170C8 /* UIVideoWidgetIOS.mm in Sources */,
|
||||
B37510851823ACA100B3BA6A /* CCPhysicsWorldInfo_chipmunk.cpp in Sources */,
|
||||
1A57007A180BC5A10088DEC7 /* CCActionInstant.cpp in Sources */,
|
||||
1A57007E180BC5A10088DEC7 /* CCActionInterval.cpp in Sources */,
|
||||
|
|
|
@ -812,6 +812,9 @@
|
|||
29080DE4191B595E0066F8DF /* UIWidgetAddNodeTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29080D89191B595E0066F8DF /* UIWidgetAddNodeTest.cpp */; };
|
||||
29080DE5191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29080D8B191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.cpp */; };
|
||||
29080DE6191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29080D8B191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.cpp */; };
|
||||
3EA0FB5E191B92F100B170C8 /* cocosvideo.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 3EA0FB5D191B92F100B170C8 /* cocosvideo.mp4 */; };
|
||||
3EA0FB64191B931500B170C8 /* UIVideoWidgetTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3EA0FB62191B931500B170C8 /* UIVideoWidgetTest.cpp */; };
|
||||
3EA0FB66191B933000B170C8 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EA0FB65191B933000B170C8 /* MediaPlayer.framework */; };
|
||||
A05FCACA177C124500BE600E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C64822165F391E007D4F18 /* Cocoa.framework */; };
|
||||
A07A521E1783A1D20073F6A7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C6482E165F399D007D4F18 /* libz.dylib */; };
|
||||
A07A521F1783A1D20073F6A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15C64832165F3AFD007D4F18 /* Foundation.framework */; };
|
||||
|
@ -1844,6 +1847,10 @@
|
|||
29080D8A191B595E0066F8DF /* UIWidgetAddNodeTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIWidgetAddNodeTest.h; sourceTree = "<group>"; };
|
||||
29080D8B191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIWidgetAddNodeTest_Editor.cpp; sourceTree = "<group>"; };
|
||||
29080D8C191B595E0066F8DF /* UIWidgetAddNodeTest_Editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIWidgetAddNodeTest_Editor.h; sourceTree = "<group>"; };
|
||||
3EA0FB5D191B92F100B170C8 /* cocosvideo.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = cocosvideo.mp4; path = "../tests/cpp-tests/Resources/cocosvideo.mp4"; sourceTree = "<group>"; };
|
||||
3EA0FB62191B931500B170C8 /* UIVideoWidgetTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UIVideoWidgetTest.cpp; sourceTree = "<group>"; };
|
||||
3EA0FB63191B931500B170C8 /* UIVideoWidgetTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIVideoWidgetTest.h; sourceTree = "<group>"; };
|
||||
3EA0FB65191B933000B170C8 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/Frameworks/MediaPlayer.framework; sourceTree = DEVELOPER_DIR; };
|
||||
46A15F9C1807A4F8005B8026 /* cocos2d_libs.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = cocos2d_libs.xcodeproj; sourceTree = "<group>"; };
|
||||
A035A71117822E9E00987F6C /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
|
||||
A07A52291783A1D20073F6A7 /* cpp-tests iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cpp-tests iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -2011,6 +2018,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3EA0FB66191B933000B170C8 /* MediaPlayer.framework in Frameworks */,
|
||||
1AAF53FE180E39D4000584C8 /* libbox2d iOS.a in Frameworks */,
|
||||
1AAF53FF180E39D4000584C8 /* libchipmunk iOS.a in Frameworks */,
|
||||
1AAF5400180E39D4000584C8 /* libcocos2dx iOS.a in Frameworks */,
|
||||
|
@ -3256,6 +3264,7 @@
|
|||
1AC35CA818CED83500F37B72 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA0FB5D191B92F100B170C8 /* cocosvideo.mp4 */,
|
||||
1AC35CA918CED84500F37B72 /* animations */,
|
||||
1AC35CAE18CED84500F37B72 /* ccb */,
|
||||
1A221C9B191771E300FD2BE4 /* ccs-res */,
|
||||
|
@ -3462,6 +3471,7 @@
|
|||
29080D1E191B595E0066F8DF /* CocoStudioGUITest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA0FB61191B931500B170C8 /* UIVideoWidgetTest */,
|
||||
29080D1F191B595E0066F8DF /* CocosGUIScene.cpp */,
|
||||
29080D20191B595E0066F8DF /* CocosGUIScene.h */,
|
||||
29080D21191B595E0066F8DF /* CocoStudioGUITest.cpp */,
|
||||
|
@ -3733,6 +3743,7 @@
|
|||
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA0FB65191B933000B170C8 /* MediaPlayer.framework */,
|
||||
1ABCA3AF18CDA06D0087CE3A /* libz.dylib */,
|
||||
1ABCA3A818CD9F130087CE3A /* AudioToolbox.framework */,
|
||||
1ABCA3A618CD9F0D0087CE3A /* OpenAL.framework */,
|
||||
|
@ -3769,6 +3780,15 @@
|
|||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
3EA0FB61191B931500B170C8 /* UIVideoWidgetTest */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3EA0FB62191B931500B170C8 /* UIVideoWidgetTest.cpp */,
|
||||
3EA0FB63191B931500B170C8 /* UIVideoWidgetTest.h */,
|
||||
);
|
||||
path = UIVideoWidgetTest;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
46A15F9D1807A4F8005B8026 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -4440,6 +4460,7 @@
|
|||
1AC35D0518CED84500F37B72 /* Shaders in Resources */,
|
||||
1AC35CD318CED84500F37B72 /* background.ogg in Resources */,
|
||||
1AC35CCB18CED84500F37B72 /* animations in Resources */,
|
||||
3EA0FB5E191B92F100B170C8 /* cocosvideo.mp4 in Resources */,
|
||||
1AC35C8C18CECF1400F37B72 /* Icon-114.png in Resources */,
|
||||
1AC35CF118CED84500F37B72 /* hd in Resources */,
|
||||
1AC35C9318CECF1400F37B72 /* Icon-57.png in Resources */,
|
||||
|
@ -4774,6 +4795,7 @@
|
|||
1AC35B4218CECF0C00F37B72 /* QuestionContainerSprite.cpp in Sources */,
|
||||
1AC35B6218CECF0C00F37B72 /* DrawPrimitivesTest.cpp in Sources */,
|
||||
29080DDC191B595E0066F8DF /* UITextFieldTest.cpp in Sources */,
|
||||
3EA0FB64191B931500B170C8 /* UIVideoWidgetTest.cpp in Sources */,
|
||||
1AC35C1818CECF0C00F37B72 /* MotionStreakTest.cpp in Sources */,
|
||||
1AC35C0618CECF0C00F37B72 /* FontTest.cpp in Sources */,
|
||||
1AC35C3818CECF0C00F37B72 /* PerformanceTest.cpp in Sources */,
|
||||
|
|
|
@ -43,7 +43,7 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
// Constants
|
||||
// ===========================================================
|
||||
|
||||
private static final String TAG = Cocos2dxActivity.class.getSimpleName();
|
||||
private final static String TAG = Cocos2dxActivity.class.getSimpleName();
|
||||
|
||||
// ===========================================================
|
||||
// Fields
|
||||
|
@ -51,7 +51,8 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
|
||||
private Cocos2dxGLSurfaceView mGLSurfaceView;
|
||||
private Cocos2dxHandler mHandler;
|
||||
private static Context sContext = null;
|
||||
private static Cocos2dxActivity sContext = null;
|
||||
private Cocos2dxVideoHelper mVideoHelper = null;
|
||||
|
||||
public static Context getContext() {
|
||||
return sContext;
|
||||
|
@ -81,9 +82,12 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
sContext = this;
|
||||
this.mHandler = new Cocos2dxHandler(this);
|
||||
|
||||
this.init();
|
||||
|
||||
Cocos2dxHelper.init(this);
|
||||
|
||||
this.init();
|
||||
if (mVideoHelper == null) {
|
||||
mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================
|
||||
|
@ -142,6 +146,7 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
}
|
||||
|
||||
|
||||
protected FrameLayout mFrameLayout = null;
|
||||
// ===========================================================
|
||||
// Methods
|
||||
// ===========================================================
|
||||
|
@ -151,8 +156,8 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
ViewGroup.LayoutParams framelayout_params =
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
FrameLayout framelayout = new FrameLayout(this);
|
||||
framelayout.setLayoutParams(framelayout_params);
|
||||
mFrameLayout = new FrameLayout(this);
|
||||
mFrameLayout.setLayoutParams(framelayout_params);
|
||||
|
||||
// Cocos2dxEditText layout
|
||||
ViewGroup.LayoutParams edittext_layout_params =
|
||||
|
@ -162,13 +167,13 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
edittext.setLayoutParams(edittext_layout_params);
|
||||
|
||||
// ...add to FrameLayout
|
||||
framelayout.addView(edittext);
|
||||
mFrameLayout.addView(edittext);
|
||||
|
||||
// Cocos2dxGLSurfaceView
|
||||
this.mGLSurfaceView = this.onCreateView();
|
||||
|
||||
// ...add to FrameLayout
|
||||
framelayout.addView(this.mGLSurfaceView);
|
||||
mFrameLayout.addView(this.mGLSurfaceView);
|
||||
|
||||
// Switch to supported OpenGL (ARGB888) mode on emulator
|
||||
if (isAndroidEmulator())
|
||||
|
@ -178,7 +183,7 @@ public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelpe
|
|||
this.mGLSurfaceView.setCocos2dxEditText(edittext);
|
||||
|
||||
// Set framelayout as the content view
|
||||
setContentView(framelayout);
|
||||
setContentView(mFrameLayout);
|
||||
}
|
||||
|
||||
public Cocos2dxGLSurfaceView onCreateView() {
|
||||
|
|
|
@ -0,0 +1,386 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.cocos2dx.lib.Cocos2dxVideoView.OnVideoEventListener;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
public class Cocos2dxVideoHelper {
|
||||
|
||||
private FrameLayout mLayout = null;
|
||||
private Cocos2dxActivity mActivity = null;
|
||||
private SparseArray<Cocos2dxVideoView> sVideoViews = null;
|
||||
private static VideoHandler mVideoHandler = null;
|
||||
|
||||
Cocos2dxVideoHelper(Cocos2dxActivity activity,FrameLayout layout)
|
||||
{
|
||||
mActivity = activity;
|
||||
mLayout = layout;
|
||||
|
||||
mVideoHandler = new VideoHandler(this);
|
||||
sVideoViews = new SparseArray<Cocos2dxVideoView>();
|
||||
}
|
||||
|
||||
private static int videoTag = 0;
|
||||
private final static int VideoTaskCreate = 0;
|
||||
private final static int VideoTaskRemove = 1;
|
||||
private final static int VideoTaskSetSource = 2;
|
||||
private final static int VideoTaskSetRect = 3;
|
||||
private final static int VideoTaskStart = 4;
|
||||
private final static int VideoTaskPause = 5;
|
||||
private final static int VideoTaskResume = 6;
|
||||
private final static int VideoTaskStop = 7;
|
||||
private final static int VideoTaskSeek = 8;
|
||||
private final static int VideoTaskSetVisible = 9;
|
||||
private final static int VideoTaskRestart = 10;
|
||||
private final static int VideoTaskKeepRatio = 11;
|
||||
|
||||
static class VideoHandler extends Handler{
|
||||
WeakReference<Cocos2dxVideoHelper> mReference;
|
||||
|
||||
VideoHandler(Cocos2dxVideoHelper helper){
|
||||
mReference = new WeakReference<Cocos2dxVideoHelper>(helper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case VideoTaskCreate: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._createVideoView(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskRemove: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._removeVideoView(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetSource: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._setVideoURL(msg.arg1, msg.arg2, (String)msg.obj);
|
||||
break;
|
||||
}
|
||||
case VideoTaskStart: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._startVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetRect: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
Rect rect = (Rect)msg.obj;
|
||||
helper._setVideoRect(msg.arg1, rect.left, rect.top, rect.right, rect.bottom);
|
||||
break;
|
||||
}
|
||||
case VideoTaskPause: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._pauseVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskResume: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._resumeVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskStop: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._stopVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSeek: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._seekVideoTo(msg.arg1, msg.arg2);
|
||||
break;
|
||||
}
|
||||
case VideoTaskSetVisible: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
if (msg.arg2 == 1) {
|
||||
helper._setVideoVisible(msg.arg1, true);
|
||||
} else {
|
||||
helper._setVideoVisible(msg.arg1, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VideoTaskRestart: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
helper._restartVideo(msg.arg1);
|
||||
break;
|
||||
}
|
||||
case VideoTaskKeepRatio: {
|
||||
Cocos2dxVideoHelper helper = mReference.get();
|
||||
if (msg.arg2 == 1) {
|
||||
helper._setVideoKeepRatio(msg.arg1, true);
|
||||
} else {
|
||||
helper._setVideoKeepRatio(msg.arg1, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
super.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class VideoEventRunnable implements Runnable
|
||||
{
|
||||
private int mVideoTag;
|
||||
private int mVideoEvent;
|
||||
|
||||
public VideoEventRunnable(int tag,int event) {
|
||||
mVideoTag = tag;
|
||||
mVideoEvent = event;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
nativeExecuteVideoCallback(mVideoTag, mVideoEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static native void nativeExecuteVideoCallback(int index,int event);
|
||||
|
||||
OnVideoEventListener videoEventListener = new OnVideoEventListener() {
|
||||
|
||||
@Override
|
||||
public void onVideoEvent(int tag,int event) {
|
||||
mActivity.runOnGLThread(new VideoEventRunnable(tag, event));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static int createVideoWidget() {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskCreate;
|
||||
msg.arg1 = videoTag;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
|
||||
return videoTag++;
|
||||
}
|
||||
|
||||
private void _createVideoView(int index) {
|
||||
Cocos2dxVideoView videoView = new Cocos2dxVideoView(mActivity,index);
|
||||
sVideoViews.put(index, videoView);
|
||||
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
mLayout.addView(videoView, lParams);
|
||||
videoView.setZOrderOnTop(true);
|
||||
videoView.setOnCompletionListener(videoEventListener);
|
||||
}
|
||||
|
||||
public static void removeVideoWidget(int index){
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskRemove;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _removeVideoView(int index) {
|
||||
Cocos2dxVideoView view = sVideoViews.get(index);
|
||||
if (view != null) {
|
||||
view.stopPlayback();
|
||||
sVideoViews.remove(index);
|
||||
mLayout.removeView(view);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoUrl(int index,int videoSource,String videoUrl) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetSource;
|
||||
msg.arg1 = index;
|
||||
msg.arg2 = videoSource;
|
||||
msg.obj = videoUrl;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoURL(int index,int videoSource,String videoUrl) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
switch (videoSource) {
|
||||
case 0:
|
||||
videoView.setVideoFileName(videoUrl);
|
||||
break;
|
||||
case 1:
|
||||
videoView.setVideoURL(videoUrl);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoRect(int index,int left,int top,int maxWidth,int maxHeight) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetRect;
|
||||
msg.arg1 = index;
|
||||
msg.obj = new Rect(left, top, maxWidth, maxHeight);
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoRect(int index,int left,int top,int maxWidth,int maxHeight) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setVideoRect(left,top,maxWidth,maxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskStart;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _startVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void pauseVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskPause;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _pauseVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.pause();
|
||||
}
|
||||
}
|
||||
|
||||
public static void resumeVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskResume;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _resumeVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.resume();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskStop;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _stopVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static void restartVideo(int index) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskRestart;
|
||||
msg.arg1 = index;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _restartVideo(int index) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.restart();
|
||||
}
|
||||
}
|
||||
|
||||
public static void seekVideoTo(int index,int msec) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSeek;
|
||||
msg.arg1 = index;
|
||||
msg.arg2 = msec;
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _seekVideoTo(int index,int msec) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.seekTo(msec);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoVisible(int index, boolean visible) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskSetVisible;
|
||||
msg.arg1 = index;
|
||||
if (visible) {
|
||||
msg.arg2 = 1;
|
||||
} else {
|
||||
msg.arg2 = 0;
|
||||
}
|
||||
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoVisible(int index, boolean visible) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
if (visible) {
|
||||
videoView.fixSize();
|
||||
videoView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
videoView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVideoKeepRatioEnabled(int index, boolean enable) {
|
||||
Message msg = new Message();
|
||||
msg.what = VideoTaskKeepRatio;
|
||||
msg.arg1 = index;
|
||||
if (enable) {
|
||||
msg.arg2 = 1;
|
||||
} else {
|
||||
msg.arg2 = 0;
|
||||
}
|
||||
mVideoHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
private void _setVideoKeepRatio(int index, boolean enable) {
|
||||
Cocos2dxVideoView videoView = sVideoViews.get(index);
|
||||
if (videoView != null) {
|
||||
videoView.setKeepRatio(enable);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,686 @@
|
|||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
* Copyright (c) 2014 Chukong Technologies Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.cocos2dx.lib;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.Resources;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.media.MediaPlayer.OnErrorListener;
|
||||
import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.MediaController.MediaPlayerControl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class Cocos2dxVideoView extends SurfaceView implements MediaPlayerControl {
|
||||
private String TAG = "VideoView";
|
||||
|
||||
private Uri mUri;
|
||||
private int mDuration;
|
||||
|
||||
// all possible internal states
|
||||
private static final int STATE_ERROR = -1;
|
||||
private static final int STATE_IDLE = 0;
|
||||
private static final int STATE_PREPARING = 1;
|
||||
private static final int STATE_PREPARED = 2;
|
||||
private static final int STATE_PLAYING = 3;
|
||||
private static final int STATE_PAUSED = 4;
|
||||
private static final int STATE_PLAYBACK_COMPLETED = 5;
|
||||
|
||||
// mCurrentState is a VideoView object's current state.
|
||||
// mTargetState is the state that a method caller intends to reach.
|
||||
// For instance, regardless the VideoView object's current state,
|
||||
// calling pause() intends to bring the object to a target state
|
||||
// of STATE_PAUSED.
|
||||
private int mCurrentState = STATE_IDLE;
|
||||
private int mTargetState = STATE_IDLE;
|
||||
|
||||
// All the stuff we need for playing and showing a video
|
||||
private SurfaceHolder mSurfaceHolder = null;
|
||||
private MediaPlayer mMediaPlayer = null;
|
||||
private int mVideoWidth = 0;
|
||||
private int mVideoHeight = 0;
|
||||
|
||||
private OnVideoEventListener mOnVideoEventListener;
|
||||
private MediaPlayer.OnPreparedListener mOnPreparedListener;
|
||||
private int mCurrentBufferPercentage;
|
||||
private OnErrorListener mOnErrorListener;
|
||||
|
||||
// recording the seek position while preparing
|
||||
private int mSeekWhenPrepared;
|
||||
|
||||
protected Context mContext = null;
|
||||
|
||||
protected int mViewLeft = 0;
|
||||
protected int mViewTop = 0;
|
||||
protected int mViewWidth = 0;
|
||||
protected int mViewHeight = 0;
|
||||
|
||||
protected int mVisibleLeft = 0;
|
||||
protected int mVisibleTop = 0;
|
||||
protected int mVisibleWidth = 0;
|
||||
protected int mVisibleHeight = 0;
|
||||
|
||||
private int mViewTag = 0;
|
||||
|
||||
public Cocos2dxVideoView(Context context,int tag) {
|
||||
super(context);
|
||||
|
||||
mViewTag = tag;
|
||||
mContext = context;
|
||||
initVideoView();
|
||||
}
|
||||
|
||||
public Cocos2dxVideoView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
|
||||
mContext = context;
|
||||
initVideoView();
|
||||
}
|
||||
|
||||
public Cocos2dxVideoView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
mContext = context;
|
||||
initVideoView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mVideoWidth == 0 || mVideoHeight == 0) {
|
||||
setMeasuredDimension(mViewWidth, mViewHeight);
|
||||
Log.e(TAG, ""+mViewWidth+ ":" +mViewHeight);
|
||||
}
|
||||
else {
|
||||
setMeasuredDimension(mVisibleWidth, mVisibleHeight);
|
||||
Log.e(TAG, ""+mVisibleWidth+ ":" +mVisibleHeight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setVideoRect(int left,int top,int maxWidth,int maxHeight) {
|
||||
mViewLeft = left;
|
||||
mViewTop = top;
|
||||
mViewWidth = maxWidth;
|
||||
mViewHeight = maxHeight;
|
||||
|
||||
if (mVideoWidth != 0 && mVideoHeight != 0) {
|
||||
fixSize();
|
||||
}
|
||||
}
|
||||
|
||||
public int resolveAdjustedSize(int desiredSize, int measureSpec) {
|
||||
int result = desiredSize;
|
||||
int specMode = MeasureSpec.getMode(measureSpec);
|
||||
int specSize = MeasureSpec.getSize(measureSpec);
|
||||
|
||||
switch (specMode) {
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
/* Parent says we can be as big as we want. Just don't be larger
|
||||
* than max size imposed on ourselves.
|
||||
*/
|
||||
result = desiredSize;
|
||||
break;
|
||||
|
||||
case MeasureSpec.AT_MOST:
|
||||
/* Parent says we can be as big as we want, up to specSize.
|
||||
* Don't be larger than specSize, and don't be larger than
|
||||
* the max size imposed on ourselves.
|
||||
*/
|
||||
result = Math.min(desiredSize, specSize);
|
||||
break;
|
||||
|
||||
case MeasureSpec.EXACTLY:
|
||||
// No choice. Do what we are told.
|
||||
result = specSize;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean mNeedResume = false;
|
||||
|
||||
@Override
|
||||
public void setVisibility(int visibility) {
|
||||
if (visibility == INVISIBLE) {
|
||||
mNeedResume = isPlaying();
|
||||
if (mNeedResume) {
|
||||
mSeekWhenPrepared = getCurrentPosition();
|
||||
}
|
||||
}
|
||||
else if (mNeedResume){
|
||||
start();
|
||||
mNeedResume = false;
|
||||
}
|
||||
super.setVisibility(visibility);
|
||||
}
|
||||
|
||||
private void initVideoView() {
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
getHolder().addCallback(mSHCallback);
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
mCurrentState = STATE_IDLE;
|
||||
mTargetState = STATE_IDLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP)
|
||||
{
|
||||
if (isPlaying()) {
|
||||
pause();
|
||||
} else if(mCurrentState == STATE_PAUSED){
|
||||
resume();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isAssetRouse = false;
|
||||
private String fileName = null;
|
||||
|
||||
public void setVideoFileName(String path) {
|
||||
if (path.startsWith("/")) {
|
||||
isAssetRouse = false;
|
||||
setVideoURI(Uri.parse(path),null);
|
||||
}
|
||||
else {
|
||||
fileName = path;
|
||||
isAssetRouse = true;
|
||||
setVideoURI(Uri.parse(path),null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVideoURL(String url) {
|
||||
isAssetRouse = false;
|
||||
setVideoURI(Uri.parse(url), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
private void setVideoURI(Uri uri, Map<String, String> headers) {
|
||||
mUri = uri;
|
||||
mSeekWhenPrepared = 0;
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
openVideo();
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void stopPlayback() {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.stop();
|
||||
mMediaPlayer.release();
|
||||
mMediaPlayer = null;
|
||||
mCurrentState = STATE_IDLE;
|
||||
mTargetState = STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
private void openVideo() {
|
||||
if (mSurfaceHolder == null) {
|
||||
// not ready for playback just yet, will try again later
|
||||
return;
|
||||
}
|
||||
if (isAssetRouse) {
|
||||
if(fileName == null)
|
||||
return;
|
||||
} else {
|
||||
if(mUri == null)
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the music playback service to pause
|
||||
// TODO: these constants need to be published somewhere in the framework.
|
||||
Intent i = new Intent("com.android.music.musicservicecommand");
|
||||
i.putExtra("command", "pause");
|
||||
mContext.sendBroadcast(i);
|
||||
|
||||
// we shouldn't clear the target state, because somebody might have
|
||||
// called start() previously
|
||||
release(false);
|
||||
|
||||
try {
|
||||
//if (mMediaPlayer == null) {
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
mMediaPlayer.setOnPreparedListener(mPreparedListener);
|
||||
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
|
||||
mMediaPlayer.setOnCompletionListener(mCompletionListener);
|
||||
mMediaPlayer.setOnErrorListener(mErrorListener);
|
||||
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
|
||||
|
||||
mMediaPlayer.setDisplay(mSurfaceHolder);
|
||||
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mMediaPlayer.setScreenOnWhilePlaying(true);
|
||||
//}
|
||||
|
||||
mDuration = -1;
|
||||
mCurrentBufferPercentage = 0;
|
||||
if (isAssetRouse) {
|
||||
AssetFileDescriptor afd = mContext.getAssets().openFd(fileName);
|
||||
mMediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());
|
||||
} else {
|
||||
mMediaPlayer.setDataSource(mContext, mUri);
|
||||
}
|
||||
|
||||
mMediaPlayer.prepareAsync();
|
||||
// we don't set the target state here either, but preserve the
|
||||
// target state that was there before.
|
||||
mCurrentState = STATE_PREPARING;
|
||||
} catch (IOException ex) {
|
||||
Log.w(TAG, "Unable to open content: " + mUri, ex);
|
||||
mCurrentState = STATE_ERROR;
|
||||
mTargetState = STATE_ERROR;
|
||||
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
|
||||
return;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Log.w(TAG, "Unable to open content: " + mUri, ex);
|
||||
mCurrentState = STATE_ERROR;
|
||||
mTargetState = STATE_ERROR;
|
||||
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mKeepRatio = false;
|
||||
|
||||
public void setKeepRatio(boolean enabled) {
|
||||
mKeepRatio = enabled;
|
||||
fixSize();
|
||||
}
|
||||
|
||||
public void fixSize() {
|
||||
if (mViewWidth != 0 && mViewHeight != 0) {
|
||||
if (mKeepRatio) {
|
||||
if ( mVideoWidth * mViewHeight > mViewWidth * mVideoHeight ) {
|
||||
mVisibleWidth = mViewWidth;
|
||||
mVisibleHeight = mViewWidth * mVideoHeight / mVideoWidth;
|
||||
} else if ( mVideoWidth * mViewHeight < mViewWidth * mVideoHeight ) {
|
||||
mVisibleWidth = mViewHeight * mVideoWidth / mVideoHeight;
|
||||
mVisibleHeight = mViewHeight;
|
||||
}
|
||||
mVisibleLeft = mViewLeft + (mViewWidth - mVisibleWidth) / 2;
|
||||
mVisibleTop = mViewTop + (mViewHeight - mVisibleHeight) / 2;
|
||||
} else {
|
||||
mVisibleLeft = mViewLeft;
|
||||
mVisibleTop = mViewTop;
|
||||
mVisibleWidth = mViewWidth;
|
||||
mVisibleHeight = mViewHeight;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mVisibleLeft = mViewLeft;
|
||||
mVisibleTop = mViewTop;
|
||||
mVisibleWidth = mVideoWidth;
|
||||
mVisibleHeight = mVideoHeight;
|
||||
}
|
||||
|
||||
getHolder().setFixedSize(mVisibleWidth, mVisibleHeight);
|
||||
|
||||
FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
|
||||
FrameLayout.LayoutParams.WRAP_CONTENT);
|
||||
lParams.leftMargin = mVisibleLeft;
|
||||
lParams.topMargin = mVisibleTop;
|
||||
setLayoutParams(lParams);
|
||||
}
|
||||
|
||||
protected
|
||||
MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
|
||||
new MediaPlayer.OnVideoSizeChangedListener() {
|
||||
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
|
||||
mVideoWidth = mp.getVideoWidth();
|
||||
mVideoHeight = mp.getVideoHeight();
|
||||
if (mVideoWidth != 0 && mVideoHeight != 0) {
|
||||
getHolder().setFixedSize(mVideoWidth, mVideoHeight);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
|
||||
public void onPrepared(MediaPlayer mp) {
|
||||
mCurrentState = STATE_PREPARED;
|
||||
|
||||
if (mOnPreparedListener != null) {
|
||||
mOnPreparedListener.onPrepared(mMediaPlayer);
|
||||
}
|
||||
|
||||
mVideoWidth = mp.getVideoWidth();
|
||||
mVideoHeight = mp.getVideoHeight();
|
||||
|
||||
int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be changed after seekTo() call
|
||||
if (seekToPosition != 0) {
|
||||
seekTo(seekToPosition);
|
||||
}
|
||||
if (mVideoWidth != 0 && mVideoHeight != 0) {
|
||||
fixSize();
|
||||
}
|
||||
|
||||
if (mTargetState == STATE_PLAYING) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private MediaPlayer.OnCompletionListener mCompletionListener =
|
||||
new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mCurrentState = STATE_PLAYBACK_COMPLETED;
|
||||
mTargetState = STATE_PLAYBACK_COMPLETED;
|
||||
|
||||
mp.release();
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag,EVENT_COMPLETED);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static final int EVENT_PLAYING = 0;
|
||||
private static final int EVENT_PAUSED = 1;
|
||||
private static final int EVENT_STOPPED = 2;
|
||||
private static final int EVENT_COMPLETED = 3;
|
||||
|
||||
public interface OnVideoEventListener
|
||||
{
|
||||
void onVideoEvent(int tag,int event);
|
||||
}
|
||||
|
||||
private MediaPlayer.OnErrorListener mErrorListener =
|
||||
new MediaPlayer.OnErrorListener() {
|
||||
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) {
|
||||
Log.d(TAG, "Error: " + framework_err + "," + impl_err);
|
||||
mCurrentState = STATE_ERROR;
|
||||
mTargetState = STATE_ERROR;
|
||||
|
||||
/* If an error handler has been supplied, use it and finish. */
|
||||
if (mOnErrorListener != null) {
|
||||
if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, pop up an error dialog so the user knows that
|
||||
* something bad has happened. Only try and pop up the dialog
|
||||
* if we're attached to a window. When we're going away and no
|
||||
* longer have a window, don't bother showing the user an error.
|
||||
*/
|
||||
if (getWindowToken() != null) {
|
||||
Resources r = mContext.getResources();
|
||||
int messageId;
|
||||
|
||||
if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
|
||||
//messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
|
||||
messageId = r.getIdentifier("VideoView_error_text_invalid_progressive_playback", "string", "android");
|
||||
} else {
|
||||
//messageId = com.android.internal.R.string.VideoView_error_text_unknown;
|
||||
messageId = r.getIdentifier("VideoView_error_text_unknown", "string", "android");
|
||||
}
|
||||
|
||||
int titleId = r.getIdentifier("VideoView_error_title", "string", "android");
|
||||
int buttonStringId = r.getIdentifier("VideoView_error_button", "string", "android");
|
||||
|
||||
new AlertDialog.Builder(mContext)
|
||||
.setTitle(r.getString(titleId))
|
||||
.setMessage(messageId)
|
||||
.setPositiveButton(r.getString(buttonStringId),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
/* If we get here, there is no onError listener, so
|
||||
* at least inform them that the video is over.
|
||||
*/
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag,EVENT_COMPLETED);
|
||||
}
|
||||
}
|
||||
})
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
|
||||
new MediaPlayer.OnBufferingUpdateListener() {
|
||||
public void onBufferingUpdate(MediaPlayer mp, int percent) {
|
||||
mCurrentBufferPercentage = percent;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when the media file
|
||||
* is loaded and ready to go.
|
||||
*
|
||||
* @param l The callback that will be run
|
||||
*/
|
||||
public void setOnPreparedListener(MediaPlayer.OnPreparedListener l)
|
||||
{
|
||||
mOnPreparedListener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when the end of a media file
|
||||
* has been reached during playback.
|
||||
*
|
||||
* @param l The callback that will be run
|
||||
*/
|
||||
public void setOnCompletionListener(OnVideoEventListener l)
|
||||
{
|
||||
mOnVideoEventListener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when an error occurs
|
||||
* during playback or setup. If no listener is specified,
|
||||
* or if the listener returned false, VideoView will inform
|
||||
* the user of any errors.
|
||||
*
|
||||
* @param l The callback that will be run
|
||||
*/
|
||||
public void setOnErrorListener(OnErrorListener l)
|
||||
{
|
||||
mOnErrorListener = l;
|
||||
}
|
||||
|
||||
SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
|
||||
{
|
||||
public void surfaceChanged(SurfaceHolder holder, int format,
|
||||
int w, int h)
|
||||
{
|
||||
boolean isValidState = (mTargetState == STATE_PLAYING);
|
||||
boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
|
||||
if (mMediaPlayer != null && isValidState && hasValidSize) {
|
||||
if (mSeekWhenPrepared != 0) {
|
||||
seekTo(mSeekWhenPrepared);
|
||||
}
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
public void surfaceCreated(SurfaceHolder holder)
|
||||
{
|
||||
mSurfaceHolder = holder;
|
||||
openVideo();
|
||||
}
|
||||
|
||||
public void surfaceDestroyed(SurfaceHolder holder)
|
||||
{
|
||||
// after we return from this we can't use the surface any more
|
||||
mSurfaceHolder = null;
|
||||
|
||||
release(true);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* release the media player in any state
|
||||
*/
|
||||
private void release(boolean cleartargetstate) {
|
||||
if (mMediaPlayer != null) {
|
||||
mMediaPlayer.reset();
|
||||
mMediaPlayer.release();
|
||||
mMediaPlayer = null;
|
||||
mCurrentState = STATE_IDLE;
|
||||
if (cleartargetstate) {
|
||||
mTargetState = STATE_IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (isInPlaybackState()) {
|
||||
mMediaPlayer.start();
|
||||
mCurrentState = STATE_PLAYING;
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag, EVENT_PLAYING);
|
||||
}
|
||||
}
|
||||
mTargetState = STATE_PLAYING;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
if (isInPlaybackState()) {
|
||||
if (mMediaPlayer.isPlaying()) {
|
||||
mMediaPlayer.pause();
|
||||
mCurrentState = STATE_PAUSED;
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag, EVENT_PAUSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
mTargetState = STATE_PAUSED;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (isInPlaybackState()) {
|
||||
if (mMediaPlayer.isPlaying()) {
|
||||
stopPlayback();
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag, EVENT_STOPPED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void suspend() {
|
||||
release(false);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
if (isInPlaybackState()) {
|
||||
if (mCurrentState == STATE_PAUSED) {
|
||||
mMediaPlayer.start();
|
||||
mCurrentState = STATE_PLAYING;
|
||||
if (mOnVideoEventListener != null) {
|
||||
mOnVideoEventListener.onVideoEvent(mViewTag, EVENT_PLAYING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
if (isInPlaybackState()) {
|
||||
mMediaPlayer.seekTo(0);
|
||||
mMediaPlayer.start();
|
||||
mCurrentState = STATE_PLAYING;
|
||||
mTargetState = STATE_PLAYING;
|
||||
}
|
||||
}
|
||||
// cache duration as mDuration for faster access
|
||||
public int getDuration() {
|
||||
if (isInPlaybackState()) {
|
||||
if (mDuration > 0) {
|
||||
return mDuration;
|
||||
}
|
||||
mDuration = mMediaPlayer.getDuration();
|
||||
return mDuration;
|
||||
}
|
||||
mDuration = -1;
|
||||
return mDuration;
|
||||
}
|
||||
|
||||
public int getCurrentPosition() {
|
||||
if (isInPlaybackState()) {
|
||||
return mMediaPlayer.getCurrentPosition();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void seekTo(int msec) {
|
||||
if (isInPlaybackState()) {
|
||||
mMediaPlayer.seekTo(msec);
|
||||
mSeekWhenPrepared = 0;
|
||||
} else {
|
||||
mSeekWhenPrepared = msec;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return isInPlaybackState() && mMediaPlayer.isPlaying();
|
||||
}
|
||||
|
||||
public int getBufferPercentage() {
|
||||
if (mMediaPlayer != null) {
|
||||
return mCurrentBufferPercentage;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isInPlaybackState() {
|
||||
return (mMediaPlayer != null &&
|
||||
mCurrentState != STATE_ERROR &&
|
||||
mCurrentState != STATE_IDLE &&
|
||||
mCurrentState != STATE_PREPARING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPause() {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSeekBackward() {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSeekForward() {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,9 +28,8 @@ UIRichText.cpp \
|
|||
CCProtectedNode.cpp \
|
||||
UIHBox.cpp \
|
||||
UIVBox.cpp \
|
||||
UIRelativeBox.cpp
|
||||
|
||||
|
||||
UIRelativeBox.cpp \
|
||||
UIVideoWidgetAndroid.cpp
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.. \
|
||||
$(LOCAL_PATH)/../editor-support
|
||||
|
|
|
@ -45,6 +45,9 @@ THE SOFTWARE.
|
|||
#include "ui/UIHBox.h"
|
||||
#include "ui/UIVBox.h"
|
||||
#include "ui/UIRelativeBox.h"
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
#include "ui/UIVideoWidget.h"
|
||||
#endif
|
||||
|
||||
NS_CC_BEGIN
|
||||
namespace ui {
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __COCOS2D_UI_VIDEOWEIGTH_H_
|
||||
#define __COCOS2D_UI_VIDEOWEIGTH_H_
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
|
||||
#include "ui/UIWidget.h"
|
||||
|
||||
NS_CC_BEGIN
|
||||
namespace experimental{
|
||||
namespace ui{
|
||||
|
||||
enum class VideoWidgetEvent
|
||||
{
|
||||
PLAYING = 0,
|
||||
PAUSED,
|
||||
STOPPED,
|
||||
COMPLETED
|
||||
};
|
||||
|
||||
typedef std::function<void(Ref*,VideoWidgetEvent)> VideoWidgetCallback;
|
||||
|
||||
class VideoWidget : public cocos2d::ui::Widget
|
||||
{
|
||||
public:
|
||||
|
||||
CREATE_FUNC(VideoWidget);
|
||||
|
||||
//Sets local file[support assets' file on android] as a video source for VideoWidget
|
||||
virtual void setVideoFileName(const std::string& videoPath);
|
||||
virtual const std::string& getVideoFileName() const { return _videoUrl;}
|
||||
|
||||
//Sets network link as a video source for VideoWidget
|
||||
virtual void setVideoURL(const std::string& videoUrl);
|
||||
virtual const std::string& getVideoURL() const { return _videoUrl;}
|
||||
|
||||
virtual void startVideo();
|
||||
virtual void pauseVideo();
|
||||
virtual void resumeVideo();
|
||||
virtual void stopVideo();
|
||||
|
||||
virtual void seekVideoTo(float sec);
|
||||
virtual bool isPlaying() const;
|
||||
|
||||
virtual void setVisible(bool visible) override;
|
||||
|
||||
virtual void setKeepAspectRatioEnabled(bool enable);
|
||||
virtual bool isKeepAspectRatioEnabled() { return _keepAspectRatioEnabled;}
|
||||
|
||||
virtual void setFullScreenEnabled(bool enabled);
|
||||
virtual bool isFullScreenEnabled();
|
||||
|
||||
virtual void setEventListener(const VideoWidgetCallback& callback);
|
||||
|
||||
virtual void onVideoEvent(VideoWidgetEvent event);
|
||||
virtual void draw(Renderer *renderer, const Matrix& transform, bool transformUpdated) override;
|
||||
|
||||
protected:
|
||||
VideoWidget();
|
||||
virtual ~VideoWidget();
|
||||
|
||||
#if CC_VIDEOWIDGET_DEBUG_DRAW
|
||||
CustomCommand _customDebugDrawCommand;
|
||||
void VideoWidget::drawDebugData();
|
||||
#endif
|
||||
|
||||
enum class VideoSource
|
||||
{
|
||||
FILENAME = 0,
|
||||
URL
|
||||
};
|
||||
|
||||
bool _isPlaying;
|
||||
bool _fullScreenDirty;
|
||||
bool _fullScreenEnabled;
|
||||
bool _keepAspectRatioEnabled;
|
||||
|
||||
std::string _videoUrl;
|
||||
VideoSource _videoSource;
|
||||
|
||||
int _videoWidgetIndex;
|
||||
VideoWidgetCallback _callback;
|
||||
|
||||
void* _videiView;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,367 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "UIVideoWidget.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
|
||||
#include <unordered_map>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include "jni/JniHelper.h"
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxVideoHelper"
|
||||
|
||||
void executeVideoCallback(int index,int event);
|
||||
|
||||
USING_NS_CC;
|
||||
|
||||
extern "C" {
|
||||
void Java_org_cocos2dx_lib_Cocos2dxVideoHelper_nativeExecuteVideoCallback(JNIEnv * env, jobject obj, jint index,jint event) {
|
||||
executeVideoCallback(index,event);
|
||||
}
|
||||
}
|
||||
|
||||
int createVideoWidgetJNI()
|
||||
{
|
||||
JniMethodInfo t;
|
||||
int ret = -1;
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "createVideoWidget", "()I")) {
|
||||
ret = t.env->CallStaticIntMethod(t.classID, t.methodID);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void callVideoNonParameterFun(int index,const char* funName)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, funName, "(I)V")) {
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void removeVideoWidgetJNI(int index)
|
||||
{
|
||||
callVideoNonParameterFun(index,"removeVideoWidget");
|
||||
}
|
||||
|
||||
void setVideoRectJNI(int index,int left,int top,int width,int height)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setVideoRect", "(IIIII)V")) {
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index, left, top, width, height);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void setVideoURLJNI(int index,int videoSource,const std::string& videoUrl)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setVideoUrl", "(IILjava/lang/String;)V")) {
|
||||
jstring stringArg = t.env->NewStringUTF(videoUrl.c_str());
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index, videoSource,stringArg);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
t.env->DeleteLocalRef(stringArg);
|
||||
}
|
||||
}
|
||||
|
||||
void startVideoJNI(int index)
|
||||
{
|
||||
callVideoNonParameterFun(index,"startVideo");
|
||||
}
|
||||
|
||||
void pauseVideoJNI(int index)
|
||||
{
|
||||
callVideoNonParameterFun(index,"pauseVideo");
|
||||
}
|
||||
|
||||
void resumeVideoJNI(int index)
|
||||
{
|
||||
callVideoNonParameterFun(index,"resumeVideo");
|
||||
}
|
||||
|
||||
void stopVideoJNI(int index)
|
||||
{
|
||||
callVideoNonParameterFun(index,"stopVideo");
|
||||
}
|
||||
|
||||
void seekVideoToJNI(int index,int msec)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "seekVideoTo", "(II)V")) {
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index, msec);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void setVideoVisible(int index,bool visible)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setVideoVisible", "(IZ)V")) {
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index, visible);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
}
|
||||
|
||||
void setVideoKeepRatioEnabled(int index,bool enabled)
|
||||
{
|
||||
JniMethodInfo t;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "setVideoKeepRatioEnabled", "(IZ)V")) {
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, index, enabled);
|
||||
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
using namespace cocos2d::experimental::ui;
|
||||
|
||||
static std::unordered_map<int, VideoWidget*> s_allVideoWidgets;
|
||||
|
||||
VideoWidget::VideoWidget()
|
||||
: _videoWidgetIndex(-1)
|
||||
, _callback(nullptr)
|
||||
, _fullScreenEnabled(false)
|
||||
, _fullScreenDirty(false)
|
||||
, _keepAspectRatioEnabled(false)
|
||||
{
|
||||
_videoWidgetIndex = createVideoWidgetJNI();
|
||||
s_allVideoWidgets[_videoWidgetIndex] = this;
|
||||
|
||||
auto listener = EventListenerKeyboard::create();
|
||||
listener->onKeyReleased = [&](EventKeyboard::KeyCode keycode, Event* event){
|
||||
if (keycode == EventKeyboard::KeyCode::KEY_BACKSPACE && _fullScreenEnabled)
|
||||
{
|
||||
this->setFullScreenEnabled(false);
|
||||
}
|
||||
};
|
||||
|
||||
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
|
||||
}
|
||||
|
||||
VideoWidget::~VideoWidget()
|
||||
{
|
||||
s_allVideoWidgets.erase(_videoWidgetIndex);
|
||||
removeVideoWidgetJNI(_videoWidgetIndex);
|
||||
}
|
||||
|
||||
void VideoWidget::setVideoFileName(const std::string& fileName)
|
||||
{
|
||||
_videoUrl = fileName;
|
||||
_videoSource = VideoWidget::VideoSource::FILENAME;
|
||||
setVideoURLJNI(_videoWidgetIndex, (int)VideoSource::FILENAME,_videoUrl);
|
||||
}
|
||||
|
||||
void VideoWidget::setVideoURL(const std::string& videoUrl)
|
||||
{
|
||||
_videoUrl = videoUrl;
|
||||
_videoSource = VideoWidget::VideoSource::URL;
|
||||
setVideoURLJNI(_videoWidgetIndex,(int)VideoSource::URL,_videoUrl);
|
||||
}
|
||||
|
||||
void VideoWidget::draw(Renderer* renderer, const Matrix &transform, bool transformUpdated)
|
||||
{
|
||||
cocos2d::ui::Widget::draw(renderer,transform,transformUpdated);
|
||||
|
||||
if (transformUpdated || _fullScreenDirty)
|
||||
{
|
||||
_fullScreenDirty = false;
|
||||
auto directorInstance = Director::getInstance();
|
||||
auto glView = directorInstance->getOpenGLView();
|
||||
auto frameSize = glView->getFrameSize();
|
||||
|
||||
if (_fullScreenEnabled)
|
||||
{
|
||||
setVideoRectJNI(_videoWidgetIndex,0,0,frameSize.width,frameSize.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto winSize = directorInstance->getWinSize();
|
||||
|
||||
auto leftBottom = convertToWorldSpace(Point::ZERO);
|
||||
auto rightTop = convertToWorldSpace(Point(_contentSize.width,_contentSize.height));
|
||||
|
||||
auto uiLeft = frameSize.width / 2 + (leftBottom.x - winSize.width / 2 ) * glView->getScaleX();
|
||||
auto uiTop = frameSize.height /2 - (rightTop.y - winSize.height / 2) * glView->getScaleY();
|
||||
|
||||
setVideoRectJNI(_videoWidgetIndex,uiLeft,uiTop,
|
||||
(rightTop.x - leftBottom.x) * glView->getScaleX(),
|
||||
(rightTop.y - leftBottom.y) * glView->getScaleY());
|
||||
}
|
||||
}
|
||||
|
||||
#if CC_VIDEOWIDGET_DEBUG_DRAW
|
||||
_customDebugDrawCommand.init(_globalZOrder);
|
||||
_customDebugDrawCommand.func = CC_CALLBACK_0(VideoWidget::drawDebugData, this);
|
||||
renderer->addCommand(&_customDebugDrawCommand);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VideoWidget::setFullScreenEnabled(bool enabled)
|
||||
{
|
||||
if (_fullScreenEnabled != enabled)
|
||||
{
|
||||
_fullScreenEnabled = enabled;
|
||||
_fullScreenDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoWidget::isFullScreenEnabled()
|
||||
{
|
||||
return _fullScreenEnabled;
|
||||
}
|
||||
|
||||
void VideoWidget::setKeepAspectRatioEnabled(bool enable)
|
||||
{
|
||||
if (_keepAspectRatioEnabled != enable)
|
||||
{
|
||||
_keepAspectRatioEnabled = enable;
|
||||
setVideoKeepRatioEnabled(_videoWidgetIndex,enable);
|
||||
}
|
||||
}
|
||||
|
||||
#if CC_VIDEOWIDGET_DEBUG_DRAW
|
||||
void VideoWidget::drawDebugData()
|
||||
{
|
||||
Director* director = Director::getInstance();
|
||||
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
|
||||
|
||||
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
||||
|
||||
auto size = getContentSize();
|
||||
|
||||
Point vertices[4]=
|
||||
{
|
||||
Point::ZERO,
|
||||
Point(size.width, 0),
|
||||
Point(size.width, size.height),
|
||||
Point(0, size.height)
|
||||
};
|
||||
|
||||
DrawPrimitives::drawPoly(vertices, 4, true);
|
||||
|
||||
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VideoWidget::startVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
startVideoJNI(_videoWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::pauseVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
pauseVideoJNI(_videoWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::resumeVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
resumeVideoJNI(_videoWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::stopVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
stopVideoJNI(_videoWidgetIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::seekVideoTo(float sec)
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
seekVideoToJNI(_videoWidgetIndex,int(sec * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoWidget::isPlaying() const
|
||||
{
|
||||
return _isPlaying;
|
||||
}
|
||||
|
||||
void VideoWidget::setVisible(bool visible)
|
||||
{
|
||||
cocos2d::ui::Widget::setVisible(visible);
|
||||
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
setVideoVisible(_videoWidgetIndex,visible);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::setEventListener(const VideoWidgetCallback& callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
void VideoWidget::onVideoEvent(VideoWidgetEvent event)
|
||||
{
|
||||
if (event == VideoWidgetEvent::PLAYING) {
|
||||
_isPlaying = true;
|
||||
} else {
|
||||
_isPlaying = false;
|
||||
}
|
||||
|
||||
if (_callback)
|
||||
{
|
||||
_callback(this,event);
|
||||
}
|
||||
}
|
||||
|
||||
void executeVideoCallback(int index,int event)
|
||||
{
|
||||
auto it = s_allVideoWidgets.find(index);
|
||||
if (it != s_allVideoWidgets.end())
|
||||
{
|
||||
s_allVideoWidgets[index]->onVideoEvent((VideoWidgetEvent)event);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,464 @@
|
|||
/****************************************************************************
|
||||
Copyright (c) 2014 Chukong Technologies Inc.
|
||||
|
||||
http://www.cocos2d-x.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "UIVideoWidget.h"
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
//-------------------------------------------------------------------------------------
|
||||
#include "CCEAGLView.h"
|
||||
#import <MediaPlayer/MediaPlayer.h>
|
||||
|
||||
@interface UIVideoViewWrapperIos : NSObject
|
||||
|
||||
@property (strong,nonatomic) MPMoviePlayerController * moviePlayer;
|
||||
|
||||
- (void) setVideoRect:(int) left :(int) top :(int) width :(int) height;
|
||||
- (void) setVideoURL:(int) videoSource :(std::string&) videoUrl;
|
||||
- (void) startVideo;
|
||||
- (void) pauseVideo;
|
||||
- (void) resumeVideo;
|
||||
- (void) stopVideo;
|
||||
- (void) seekVideoTo:(float) sec;
|
||||
- (void) setVideoVisible:(bool) visible;
|
||||
- (void) setVideoKeepRatioEnabled:(bool) enabled;
|
||||
- (void) setFullScreenEnabled:(bool) enabled;
|
||||
- (bool) isFullScreenEnabled;
|
||||
|
||||
-(id) init:(void*) widget;
|
||||
|
||||
-(void) videoFinished:(NSNotification*) notification;
|
||||
-(void) playStateChange;
|
||||
|
||||
+(NSString*) fullPathFromRelativePath:(NSString*) relPath;
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIVideoViewWrapperIos
|
||||
{
|
||||
int _left;
|
||||
int _top;
|
||||
int _width;
|
||||
int _height;
|
||||
bool _keepRatioEnabled;
|
||||
|
||||
cocos2d::experimental::ui::VideoWidget* _widget;
|
||||
}
|
||||
|
||||
-(id)init:(void*)widget
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.moviePlayer = nullptr;
|
||||
_widget = (cocos2d::experimental::ui::VideoWidget*)widget;
|
||||
_keepRatioEnabled = false;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) dealloc
|
||||
{
|
||||
if (self.moviePlayer != nullptr) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePlayer];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackStateDidChangeNotification object:self.moviePlayer];
|
||||
|
||||
[self.moviePlayer stop];
|
||||
[self.moviePlayer.view removeFromSuperview];
|
||||
self.moviePlayer = nullptr;
|
||||
_widget = nullptr;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void) setVideoRect:(int)left :(int)top :(int)width :(int)height
|
||||
{
|
||||
_left = left;
|
||||
_width = width;
|
||||
_top = top;
|
||||
_height = height;
|
||||
if (self.moviePlayer != nullptr) {
|
||||
[self.moviePlayer.view setFrame:CGRectMake(left, top, width, height)];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setFullScreenEnabled:(bool) enabled
|
||||
{
|
||||
if (self.moviePlayer != nullptr) {
|
||||
[self.moviePlayer setFullscreen:enabled animated:(true)];
|
||||
}
|
||||
}
|
||||
|
||||
-(bool) isFullScreenEnabled
|
||||
{
|
||||
if (self.moviePlayer != nullptr) {
|
||||
return [self.moviePlayer isFullscreen];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
-(void) setVideoURL:(int)videoSource :(std::string &)videoUrl
|
||||
{
|
||||
if (self.moviePlayer != nullptr) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePlayer];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackStateDidChangeNotification object:self.moviePlayer];
|
||||
|
||||
[self.moviePlayer stop];
|
||||
[self.moviePlayer.view removeFromSuperview];
|
||||
self.moviePlayer = nullptr;
|
||||
}
|
||||
|
||||
if (videoSource == 1) {
|
||||
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@(videoUrl.c_str())]];
|
||||
self.moviePlayer.movieSourceType = MPMovieSourceTypeStreaming;
|
||||
} else {
|
||||
NSString *path = [UIVideoViewWrapperIos fullPathFromRelativePath:@(videoUrl.c_str())];
|
||||
self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:path]];
|
||||
self.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
|
||||
}
|
||||
self.moviePlayer.allowsAirPlay = false;
|
||||
self.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
|
||||
self.moviePlayer.view.userInteractionEnabled = true;
|
||||
|
||||
auto clearColor = [UIColor clearColor];
|
||||
self.moviePlayer.backgroundView.backgroundColor = clearColor;
|
||||
self.moviePlayer.view.backgroundColor = clearColor;
|
||||
for (UIView * subView in self.moviePlayer.view.subviews) {
|
||||
subView.backgroundColor = clearColor;
|
||||
}
|
||||
|
||||
if (_keepRatioEnabled) {
|
||||
self.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
|
||||
} else {
|
||||
self.moviePlayer.scalingMode = MPMovieScalingModeFill;
|
||||
}
|
||||
|
||||
auto view = cocos2d::Director::getInstance()->getOpenGLView();
|
||||
auto eaglview = (CCEAGLView *) view->getEAGLView();
|
||||
[eaglview addSubview:self.moviePlayer.view];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoFinished:) name:MPMoviePlayerPlaybackDidFinishNotification object:self.moviePlayer];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playStateChange) name:MPMoviePlayerPlaybackStateDidChangeNotification object:self.moviePlayer];
|
||||
}
|
||||
|
||||
-(void) videoFinished:(NSNotification *)notification
|
||||
{
|
||||
if(_widget != nullptr)
|
||||
{
|
||||
if([self.moviePlayer playbackState] != MPMoviePlaybackStateStopped)
|
||||
{
|
||||
_widget->onVideoEvent(cocos2d::experimental::ui::VideoWidgetEvent::COMPLETED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) playStateChange
|
||||
{
|
||||
MPMoviePlaybackState state = [self.moviePlayer playbackState];
|
||||
switch (state) {
|
||||
case MPMoviePlaybackStatePaused:
|
||||
_widget->onVideoEvent(cocos2d::experimental::ui::VideoWidgetEvent::PAUSED);
|
||||
break;
|
||||
case MPMoviePlaybackStateStopped:
|
||||
_widget->onVideoEvent(cocos2d::experimental::ui::VideoWidgetEvent::STOPPED);
|
||||
break;
|
||||
case MPMoviePlaybackStatePlaying:
|
||||
_widget->onVideoEvent(cocos2d::experimental::ui::VideoWidgetEvent::PLAYING);
|
||||
break;
|
||||
case MPMoviePlaybackStateInterrupted:
|
||||
break;
|
||||
case MPMoviePlaybackStateSeekingBackward:
|
||||
break;
|
||||
case MPMoviePlaybackStateSeekingForward:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) seekVideoTo:(float)sec
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
[self.moviePlayer setCurrentPlaybackTime:(sec)];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setVideoVisible:(bool)visible
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
[self.moviePlayer.view setHidden:visible];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) setVideoKeepRatioEnabled:(bool)enabled
|
||||
{
|
||||
_keepRatioEnabled = enabled;
|
||||
if (self.moviePlayer != NULL) {
|
||||
if (enabled) {
|
||||
self.moviePlayer.scalingMode = MPMovieScalingModeAspectFit;
|
||||
} else {
|
||||
self.moviePlayer.scalingMode = MPMovieScalingModeFill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) startVideo
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
[self.moviePlayer.view setFrame:CGRectMake(_left, _top, _width, _height)];
|
||||
[self.moviePlayer play];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) pauseVideo
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
[self.moviePlayer pause];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) resumeVideo
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
if([self.moviePlayer playbackState] == MPMoviePlaybackStatePaused)
|
||||
{
|
||||
[self.moviePlayer play];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void) stopVideo
|
||||
{
|
||||
if (self.moviePlayer != NULL) {
|
||||
[self.moviePlayer stop];
|
||||
}
|
||||
}
|
||||
|
||||
+(NSString*) fullPathFromRelativePath:(NSString*) relPath
|
||||
{
|
||||
// do not convert an absolute path (starting with '/')
|
||||
if(([relPath length] > 0) && ([relPath characterAtIndex:0] == '/'))
|
||||
{
|
||||
return relPath;
|
||||
}
|
||||
|
||||
NSMutableArray *imagePathComponents = [NSMutableArray arrayWithArray:[relPath pathComponents]];
|
||||
NSString *file = [imagePathComponents lastObject];
|
||||
|
||||
[imagePathComponents removeLastObject];
|
||||
NSString *imageDirectory = [NSString pathWithComponents:imagePathComponents];
|
||||
|
||||
NSString *fullpath = [[NSBundle mainBundle] pathForResource:file ofType:nil inDirectory:imageDirectory];
|
||||
if (fullpath == nil)
|
||||
fullpath = relPath;
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
@end
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using namespace cocos2d::experimental::ui;
|
||||
|
||||
VideoWidget::VideoWidget()
|
||||
: _videoWidgetIndex(-1)
|
||||
, _callback(nullptr)
|
||||
, _fullScreenEnabled(false)
|
||||
, _fullScreenDirty(false)
|
||||
, _keepAspectRatioEnabled(false)
|
||||
, _isPlaying(false)
|
||||
{
|
||||
_videiView = [[UIVideoViewWrapperIos alloc] init:this];
|
||||
}
|
||||
|
||||
VideoWidget::~VideoWidget()
|
||||
{
|
||||
if(_videiView)
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) dealloc];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::setVideoFileName(const std::string& fileName)
|
||||
{
|
||||
_videoUrl = fileName;
|
||||
_videoSource = VideoWidget::VideoSource::FILENAME;
|
||||
[((UIVideoViewWrapperIos*)_videiView) setVideoURL:(int)_videoSource :_videoUrl];
|
||||
}
|
||||
|
||||
void VideoWidget::setVideoURL(const std::string& videoUrl)
|
||||
{
|
||||
_videoUrl = videoUrl;
|
||||
_videoSource = VideoWidget::VideoSource::URL;
|
||||
[((UIVideoViewWrapperIos*)_videiView) setVideoURL:(int)_videoSource :_videoUrl];
|
||||
}
|
||||
|
||||
void VideoWidget::draw(Renderer* renderer, const Matrix &transform, bool transformUpdated)
|
||||
{
|
||||
cocos2d::ui::Widget::draw(renderer,transform,transformUpdated);
|
||||
|
||||
if (transformUpdated)
|
||||
{
|
||||
auto directorInstance = Director::getInstance();
|
||||
auto glView = directorInstance->getOpenGLView();
|
||||
auto frameSize = glView->getFrameSize();
|
||||
auto scaleFactor = directorInstance->getContentScaleFactor();
|
||||
|
||||
auto winSize = directorInstance->getWinSize();
|
||||
|
||||
auto leftBottom = convertToWorldSpace(Vector2::ZERO);
|
||||
auto rightTop = convertToWorldSpace(Vector2(_contentSize.width,_contentSize.height));
|
||||
|
||||
auto uiLeft = (frameSize.width / 2 + (leftBottom.x - winSize.width / 2 ) * glView->getScaleX()) / scaleFactor;
|
||||
auto uiTop = (frameSize.height /2 - (rightTop.y - winSize.height / 2) * glView->getScaleY()) / scaleFactor;
|
||||
|
||||
[((UIVideoViewWrapperIos*)_videiView) setVideoRect:uiLeft :uiTop
|
||||
:(rightTop.x - leftBottom.x) * glView->getScaleX() / scaleFactor
|
||||
:( (rightTop.y - leftBottom.y) * glView->getScaleY()/scaleFactor)];
|
||||
}
|
||||
|
||||
#if CC_VIDEOWIDGET_DEBUG_DRAW
|
||||
_customDebugDrawCommand.init(_globalZOrder);
|
||||
_customDebugDrawCommand.func = CC_CALLBACK_0(VideoWidget::drawDebugData, this);
|
||||
renderer->addCommand(&_customDebugDrawCommand);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool VideoWidget::isFullScreenEnabled()
|
||||
{
|
||||
return [((UIVideoViewWrapperIos*)_videiView) isFullScreenEnabled];
|
||||
}
|
||||
|
||||
void VideoWidget::setFullScreenEnabled(bool enabled)
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) setFullScreenEnabled:enabled];
|
||||
}
|
||||
|
||||
void VideoWidget::setKeepAspectRatioEnabled(bool enable)
|
||||
{
|
||||
if (_keepAspectRatioEnabled != enable)
|
||||
{
|
||||
_keepAspectRatioEnabled = enable;
|
||||
[((UIVideoViewWrapperIos*)_videiView) setVideoKeepRatioEnabled:enable];
|
||||
}
|
||||
}
|
||||
|
||||
#if CC_VIDEOWIDGET_DEBUG_DRAW
|
||||
void VideoWidget::drawDebugData()
|
||||
{
|
||||
Director* director = Director::getInstance();
|
||||
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
|
||||
|
||||
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
||||
|
||||
auto size = getContentSize();
|
||||
|
||||
Point vertices[4]=
|
||||
{
|
||||
Point::ZERO,
|
||||
Point(size.width, 0),
|
||||
Point(size.width, size.height),
|
||||
Point(0, size.height)
|
||||
};
|
||||
|
||||
DrawPrimitives::drawPoly(vertices, 4, true);
|
||||
|
||||
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VideoWidget::startVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) startVideo];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::pauseVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) pauseVideo];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::resumeVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) resumeVideo];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::stopVideo()
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) stopVideo];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::seekVideoTo(float sec)
|
||||
{
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) seekVideoTo:sec];
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoWidget::isPlaying() const
|
||||
{
|
||||
return _isPlaying;
|
||||
}
|
||||
|
||||
void VideoWidget::setVisible(bool visible)
|
||||
{
|
||||
cocos2d::ui::Widget::setVisible(visible);
|
||||
|
||||
if (! _videoUrl.empty())
|
||||
{
|
||||
[((UIVideoViewWrapperIos*)_videiView) setVideoVisible:visible];
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidget::setEventListener(const VideoWidgetCallback& callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
void VideoWidget::onVideoEvent(VideoWidgetEvent event)
|
||||
{
|
||||
if (event == VideoWidgetEvent::PLAYING) {
|
||||
_isPlaying = true;
|
||||
} else {
|
||||
_isPlaying = false;
|
||||
}
|
||||
|
||||
if (_callback)
|
||||
{
|
||||
_callback(this,event);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -98,6 +98,7 @@ Classes/UITest/CocoStudioGUITest/UITextAtlasTest/UITextAtlasTest_Editor.cpp \
|
|||
Classes/UITest/CocoStudioGUITest/UITextBMFontTest/UITextBMFontTest_Editor.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/UITextFieldTest/UITextFieldTest_Editor.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest_Editor.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/UIVideoWidgetTest/UIVideoWidgetTest.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/CustomWidget/CustomImageView.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/CustomWidget/CustomImageViewReader.cpp \
|
||||
Classes/UITest/CocoStudioGUITest/CustomWidget/CustomParticleWidget.cpp \
|
||||
|
|
|
@ -279,7 +279,20 @@ g_guisTests[] =
|
|||
Director::getInstance()->replaceScene(pScene);
|
||||
}
|
||||
},
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
{
|
||||
"gui VideoWidgetTest",
|
||||
[](Ref* sender)
|
||||
{
|
||||
UISceneManager* pManager = UISceneManager::sharedUISceneManager();
|
||||
pManager->setCurrentUISceneId(kUIVideoWidgetTest);
|
||||
pManager->setMinUISceneId(kUIVideoWidgetTest);
|
||||
pManager->setMaxUISceneId(kUIVideoWidgetTest);
|
||||
Scene* pScene = pManager->currentUIScene();
|
||||
Director::getInstance()->replaceScene(pScene);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int g_maxTests = sizeof(g_guisTests) / sizeof(g_guisTests[0]);
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "UIWidgetAddNodeTest/UIWidgetAddNodeTest.h"
|
||||
#include "UIRichTextTest/UIRichTextTest.h"
|
||||
#include "UIFocusTest/UIFocusTest.h"
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
#include "UIVideoWidgetTest/UIVideoWidgetTest.h"
|
||||
#endif
|
||||
/*
|
||||
#include "UISwitchTest/UISwitchTest.h"
|
||||
*/
|
||||
|
@ -114,7 +117,10 @@ static const char* s_testArray[] =
|
|||
"UIFocusTest-VBox",
|
||||
"UIFocusTest-NestedLayout1",
|
||||
"UIFocusTest-NestedLayout2",
|
||||
"UIFocusTest-NestedLayout3"
|
||||
"UIFocusTest-NestedLayout3",
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
"UIVideoWidgetTest"
|
||||
#endif
|
||||
};
|
||||
|
||||
static UISceneManager *sharedInstance = NULL;
|
||||
|
@ -375,7 +381,10 @@ Scene *UISceneManager::currentUIScene()
|
|||
return UIFocusTestNestedLayout2::sceneWithTitle(s_testArray[_currentUISceneId]);
|
||||
case KUIFocusTest_NestedLayout3:
|
||||
return UIFocusTestNestedLayout3::sceneWithTitle(s_testArray[_currentUISceneId]);
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
case kUIVideoWidgetTest:
|
||||
return VideoWidgetTest::sceneWithTitle(s_testArray[_currentUISceneId]);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -106,6 +106,9 @@ enum
|
|||
KUIFocusTest_NestedLayout1,
|
||||
KUIFocusTest_NestedLayout2,
|
||||
KUIFocusTest_NestedLayout3,
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
kUIVideoWidgetTest,
|
||||
#endif
|
||||
kUITestMax
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
#include "UiVideoWidgetTest.h"
|
||||
|
||||
USING_NS_CC;
|
||||
using namespace cocos2d::experimental::ui;
|
||||
|
||||
bool VideoWidgetTest::init()
|
||||
{
|
||||
if ( !UIScene::init() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_visibleRect = Director::getInstance()->getOpenGLView()->getVisibleRect();
|
||||
|
||||
MenuItemFont::setFontSize(16);
|
||||
|
||||
auto fullSwitch = MenuItemFont::create("FullScreenSwitch", CC_CALLBACK_1(VideoWidgetTest::menuFullScreenCallback, this));
|
||||
fullSwitch->setAnchorPoint(Vector2::ANCHOR_BOTTOM_LEFT);
|
||||
fullSwitch->setPosition(Vector2(_visibleRect.origin.x + 10,_visibleRect.origin.y + 50));
|
||||
|
||||
auto pauseItem = MenuItemFont::create("Pause", CC_CALLBACK_1(VideoWidgetTest::menuPauseCallback, this));
|
||||
pauseItem->setAnchorPoint(Vector2::ANCHOR_BOTTOM_LEFT);
|
||||
pauseItem->setPosition(Vector2(_visibleRect.origin.x + 10,_visibleRect.origin.y + 100));
|
||||
|
||||
auto resumeItem = MenuItemFont::create("Resume", CC_CALLBACK_1(VideoWidgetTest::menuResumeCallback, this));
|
||||
resumeItem->setAnchorPoint(Vector2::ANCHOR_BOTTOM_LEFT);
|
||||
resumeItem->setPosition(Vector2(_visibleRect.origin.x + 10,_visibleRect.origin.y + 150));
|
||||
|
||||
auto stopItem = MenuItemFont::create("Stop", CC_CALLBACK_1(VideoWidgetTest::menuStopCallback, this));
|
||||
stopItem->setAnchorPoint(Vector2::ANCHOR_BOTTOM_LEFT);
|
||||
stopItem->setPosition(Vector2(_visibleRect.origin.x + 10,_visibleRect.origin.y + 200));
|
||||
|
||||
auto hintItem = MenuItemFont::create("Hint", CC_CALLBACK_1(VideoWidgetTest::menuHintCallback, this));
|
||||
hintItem->setAnchorPoint(Vector2::ANCHOR_BOTTOM_LEFT);
|
||||
hintItem->setPosition(Vector2(_visibleRect.origin.x + 10,_visibleRect.origin.y + 250));
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
auto resourceVideo = MenuItemFont::create("Play resource video", CC_CALLBACK_1(VideoWidgetTest::menuResourceVideoCallback, this));
|
||||
resourceVideo->setAnchorPoint(Vector2::ANCHOR_MIDDLE_RIGHT);
|
||||
resourceVideo->setPosition(Vector2(_visibleRect.origin.x + _visibleRect.size.width - 10,_visibleRect.origin.y + 50));
|
||||
|
||||
auto onlineVideo = MenuItemFont::create("Play online video", CC_CALLBACK_1(VideoWidgetTest::menuOnlineVideoCallback, this));
|
||||
onlineVideo->setAnchorPoint(Vector2::ANCHOR_MIDDLE_RIGHT);
|
||||
onlineVideo->setPosition(Vector2(_visibleRect.origin.x + _visibleRect.size.width - 10,_visibleRect.origin.y + 100));
|
||||
|
||||
auto ratioSwitch = MenuItemFont::create("KeepRatioSwitch", CC_CALLBACK_1(VideoWidgetTest::menuRatioCallback, this));
|
||||
ratioSwitch->setAnchorPoint(Vector2::ANCHOR_MIDDLE_RIGHT);
|
||||
ratioSwitch->setPosition(Vector2(_visibleRect.origin.x + _visibleRect.size.width - 10,_visibleRect.origin.y + 150));
|
||||
|
||||
auto menu = Menu::create(resourceVideo,onlineVideo,ratioSwitch,fullSwitch,pauseItem,resumeItem,stopItem,hintItem,nullptr);
|
||||
menu->setPosition(Vector2::ZERO);
|
||||
_uiLayer->addChild(menu);
|
||||
|
||||
_videoStateLabel = Label::createWithSystemFont("IDLE","Arial",16);
|
||||
_videoStateLabel->setAnchorPoint(Vector2::ANCHOR_MIDDLE_RIGHT);
|
||||
_videoStateLabel->setPosition(Vector2(_visibleRect.origin.x + _visibleRect.size.width - 10,_visibleRect.origin.y + 200));
|
||||
_uiLayer->addChild(_videoStateLabel);
|
||||
createVideo();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuCloseCallback(Ref* sender)
|
||||
{
|
||||
Director::getInstance()->end();
|
||||
|
||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuFullScreenCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->setFullScreenEnabled(! _videoWidget->isFullScreenEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuRatioCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->setKeepAspectRatioEnabled(! _videoWidget->isKeepAspectRatioEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuResourceVideoCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->setVideoFileName("cocosvideo.mp4");
|
||||
_videoWidget->startVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuOnlineVideoCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->setVideoURL("http://video001.smgbb.cn/gslb/program/FDN/FDN1190949/HLSVodService.m3u8?_mdCode=6065719&_cdnCode=B2B_XL_TEST&_type=0&_rCode=TerOut_18865&_userId=020341000456068&_categoryCode=SMG_HUAYU&_categoryPath=SMG_1002,SMG_HUAYU,&_adPositionId=01001000&_adCategorySource=0&_flag=.m3u8&_enCode=m3u8&taskID=ysh_ps_002-ott_1397459105893_020341000456068&_client=103&_cms=ctv&_CDNToken=76C043FD4969501754DC19E54EC8DC2C");
|
||||
_videoWidget->startVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuPauseCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->pauseVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuResumeCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->resumeVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuStopCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->stopVideo();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::menuHintCallback(Ref* sender)
|
||||
{
|
||||
if (_videoWidget)
|
||||
{
|
||||
_videoWidget->setVisible(! _videoWidget->isVisible());
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::createVideo()
|
||||
{
|
||||
auto centerPos = Vector2(_visibleRect.origin.x + _visibleRect.size.width / 2,_visibleRect.origin.y + _visibleRect.size.height /2);
|
||||
|
||||
auto widgetSize = _widget->getSize();
|
||||
|
||||
_videoWidget = VideoWidget::create();
|
||||
_videoWidget->setPosition(centerPos);
|
||||
_videoWidget->setAnchorPoint(Vector2::ANCHOR_MIDDLE);
|
||||
_videoWidget->setContentSize(Size(widgetSize.width * 0.4f,widgetSize.height * 0.4f));
|
||||
_uiLayer->addChild(_videoWidget);
|
||||
|
||||
_videoWidget->setEventListener(CC_CALLBACK_2(VideoWidgetTest::videoEventCallback, this));
|
||||
}
|
||||
|
||||
void VideoWidgetTest::createSlider()
|
||||
{
|
||||
auto centerPos = Vector2(_visibleRect.origin.x + _visibleRect.size.width / 2,_visibleRect.origin.y + _visibleRect.size.height /2);
|
||||
|
||||
auto hSlider = ui::Slider::create();
|
||||
hSlider->setTouchEnabled(true);
|
||||
hSlider->loadBarTexture("cocosui/sliderTrack.png");
|
||||
hSlider->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "");
|
||||
hSlider->loadProgressBarTexture("cocosui/sliderProgress.png");
|
||||
hSlider->setPosition(Vector2(centerPos.x, _visibleRect.origin.y + _visibleRect.size.height * 0.15f));
|
||||
hSlider->setPercent(50);
|
||||
hSlider->addEventListenerSlider(this, sliderpercentchangedselector(VideoWidgetTest::sliderCallback));
|
||||
_uiLayer->addChild(hSlider,0,1);
|
||||
|
||||
auto vSlider = ui::Slider::create();
|
||||
vSlider->setTouchEnabled(true);
|
||||
vSlider->loadBarTexture("cocosui/sliderTrack.png");
|
||||
vSlider->loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "");
|
||||
vSlider->loadProgressBarTexture("cocosui/sliderProgress.png");
|
||||
vSlider->setPosition(Vector2(_visibleRect.origin.x + _visibleRect.size.width * 0.15f, centerPos.y));
|
||||
vSlider->setRotation(90);
|
||||
vSlider->setPercent(50);
|
||||
vSlider->addEventListenerSlider(this, sliderpercentchangedselector(VideoWidgetTest::sliderCallback));
|
||||
_uiLayer->addChild(vSlider,0,2);
|
||||
}
|
||||
|
||||
void VideoWidgetTest::sliderCallback(Ref *sender, ui::SliderEventType eventType)
|
||||
{
|
||||
if (eventType == SLIDER_PERCENTCHANGED && _videoWidget)
|
||||
{
|
||||
Slider* hSlider = (Slider*)this->getChildByTag(1);
|
||||
Slider* vSlider = (Slider*)this->getChildByTag(2);
|
||||
|
||||
auto newPosX = _visibleRect.origin.x + _visibleRect.size.width / 2 + hSlider->getPercent() - 50;
|
||||
auto newPosY = _visibleRect.origin.y + _visibleRect.size.height / 2 + 50 - vSlider->getPercent();
|
||||
|
||||
_videoWidget->setPosition(Vector2(newPosX,newPosY));
|
||||
}
|
||||
}
|
||||
|
||||
void VideoWidgetTest::videoEventCallback(Ref* sender, VideoWidgetEvent eventType)
|
||||
{
|
||||
switch (eventType) {
|
||||
case VideoWidgetEvent::PLAYING:
|
||||
_videoStateLabel->setString("PLAYING");
|
||||
break;
|
||||
case VideoWidgetEvent::PAUSED:
|
||||
_videoStateLabel->setString("PAUSED");
|
||||
break;
|
||||
case VideoWidgetEvent::STOPPED:
|
||||
_videoStateLabel->setString("STOPPED");
|
||||
break;
|
||||
case VideoWidgetEvent::COMPLETED:
|
||||
_videoStateLabel->setString("COMPLETED");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef __tests__VideoWidgetTest__
|
||||
#define __tests__VideoWidgetTest__
|
||||
|
||||
#include "../UIScene.h"
|
||||
|
||||
USING_NS_CC;
|
||||
|
||||
class VideoWidgetTest : public UIScene
|
||||
{
|
||||
public:
|
||||
UI_SCENE_CREATE_FUNC(VideoWidgetTest);
|
||||
|
||||
virtual bool init();
|
||||
|
||||
void menuCloseCallback(Ref* sender);
|
||||
|
||||
void menuRatioCallback(Ref* sender);
|
||||
void menuResourceVideoCallback(Ref* sender);
|
||||
void menuOnlineVideoCallback(Ref* sender);
|
||||
|
||||
void menuFullScreenCallback(Ref* sender);
|
||||
void menuPauseCallback(Ref* sender);
|
||||
void menuResumeCallback(Ref* sender);
|
||||
void menuStopCallback(Ref* sender);
|
||||
void menuHintCallback(Ref* sender);
|
||||
|
||||
void sliderCallback(Ref *sender, ui::SliderEventType eventType);
|
||||
|
||||
void videoEventCallback(Ref* sender, experimental::ui::VideoWidgetEvent eventType);
|
||||
|
||||
private:
|
||||
void createVideo();
|
||||
void createSlider();
|
||||
|
||||
MenuItemFont* _hintItem;
|
||||
experimental::ui::VideoWidget* _videoWidget;
|
||||
Label* _videoStateLabel;
|
||||
Rect _visibleRect;
|
||||
|
||||
Layer* _rootLayer;
|
||||
|
||||
};
|
||||
|
||||
#endif // __tests__VideoWidgetTest__
|
Binary file not shown.
Loading…
Reference in New Issue