diff --git a/VitamioBundle/.classpath b/VitamioBundle/.classpath new file mode 100644 index 0000000..3f9691c --- /dev/null +++ b/VitamioBundle/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/VitamioBundle/.gitignore b/VitamioBundle/.gitignore new file mode 100644 index 0000000..1e3e304 --- /dev/null +++ b/VitamioBundle/.gitignore @@ -0,0 +1,21 @@ +# built application files +*.apk +*.ap_ + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ +obj/ + +# Local configuration file (sdk path, etc) +local.properties + +# Eclipse project files +.classpath +.project diff --git a/VitamioBundle/.project b/VitamioBundle/.project new file mode 100644 index 0000000..4c9c262 --- /dev/null +++ b/VitamioBundle/.project @@ -0,0 +1,33 @@ + + + io.vov.vitamio.activity.InitActivity + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/VitamioBundle/.settings/org.eclipse.jdt.core.prefs b/VitamioBundle/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..8000cd6 --- /dev/null +++ b/VitamioBundle/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/VitamioBundle/AndroidManifest.xml b/VitamioBundle/AndroidManifest.xml new file mode 100644 index 0000000..7c25e07 --- /dev/null +++ b/VitamioBundle/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/README.md b/VitamioBundle/README.md new file mode 100644 index 0000000..5503a53 --- /dev/null +++ b/VitamioBundle/README.md @@ -0,0 +1,4 @@ +Vitamio +======= + +Vitamio for Android \ No newline at end of file diff --git a/VitamioBundle/VitamioBundle.tar.gz b/VitamioBundle/VitamioBundle.tar.gz new file mode 100644 index 0000000..ad39ace --- /dev/null +++ b/VitamioBundle/VitamioBundle.tar.gz diff --git a/VitamioBundle/bin/AndroidManifest.xml b/VitamioBundle/bin/AndroidManifest.xml new file mode 100644 index 0000000..7c25e07 --- /dev/null +++ b/VitamioBundle/bin/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/BuildConfig.class b/VitamioBundle/bin/classes/io/vov/vitamio/BuildConfig.class new file mode 100644 index 0000000..cb1bdb5 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/BuildConfig.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$attr.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$attr.class new file mode 100644 index 0000000..88e927c --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$attr.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$drawable.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$drawable.class new file mode 100644 index 0000000..738d696 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$drawable.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$id.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$id.class new file mode 100644 index 0000000..017cdea --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$id.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$layout.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$layout.class new file mode 100644 index 0000000..4bd1073 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$layout.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$raw.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$raw.class new file mode 100644 index 0000000..14d7425 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$raw.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$string.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$string.class new file mode 100644 index 0000000..92fe851 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$string.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R$style.class b/VitamioBundle/bin/classes/io/vov/vitamio/R$style.class new file mode 100644 index 0000000..3360818 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R$style.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/R.class b/VitamioBundle/bin/classes/io/vov/vitamio/R.class new file mode 100644 index 0000000..8718568 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/R.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$1.class b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$1.class new file mode 100644 index 0000000..d538ee5 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$1.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$UIHandler.class b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$UIHandler.class new file mode 100644 index 0000000..3625d46 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity$UIHandler.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity.class b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity.class new file mode 100644 index 0000000..4ce82e8 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/activity/InitActivity.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout$LayoutParams.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout$LayoutParams.class new file mode 100644 index 0000000..3bc746f --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout$LayoutParams.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout.class new file mode 100644 index 0000000..0175c99 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/CenterLayout.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$1.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$1.class new file mode 100644 index 0000000..66d5f2b --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$1.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$2.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$2.class new file mode 100644 index 0000000..673e1b6 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$2.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$3.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$3.class new file mode 100644 index 0000000..d273923 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$3.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$MediaPlayerControl.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$MediaPlayerControl.class new file mode 100644 index 0000000..2b12538 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$MediaPlayerControl.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnHiddenListener.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnHiddenListener.class new file mode 100644 index 0000000..edff9cc --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnHiddenListener.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnShownListener.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnShownListener.class new file mode 100644 index 0000000..bd54331 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController$OnShownListener.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController.class new file mode 100644 index 0000000..0e1a0eb --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/MediaController.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/OutlineTextView.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/OutlineTextView.class new file mode 100644 index 0000000..1e69893 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/OutlineTextView.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$1.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$1.class new file mode 100644 index 0000000..579ad5a --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$1.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$2.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$2.class new file mode 100644 index 0000000..229bda6 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$2.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$3.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$3.class new file mode 100644 index 0000000..2591158 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$3.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4$1.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4$1.class new file mode 100644 index 0000000..3d68aa8 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4$1.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4.class new file mode 100644 index 0000000..2ee02b2 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$4.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$5.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$5.class new file mode 100644 index 0000000..fb97bfb --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$5.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$6.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$6.class new file mode 100644 index 0000000..fb58c23 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$6.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$7.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$7.class new file mode 100644 index 0000000..67e5b47 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$7.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$8.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$8.class new file mode 100644 index 0000000..a1b9848 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$8.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$9.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$9.class new file mode 100644 index 0000000..24168e4 --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView$9.class diff --git a/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView.class b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView.class new file mode 100644 index 0000000..0d38bdf --- /dev/null +++ b/VitamioBundle/bin/classes/io/vov/vitamio/widget/VideoView.class diff --git a/VitamioBundle/bin/io.vov.vitamio.activity.initactivity.jar b/VitamioBundle/bin/io.vov.vitamio.activity.initactivity.jar new file mode 100644 index 0000000..f5138a3 --- /dev/null +++ b/VitamioBundle/bin/io.vov.vitamio.activity.initactivity.jar diff --git a/VitamioBundle/bin/jarlist.cache b/VitamioBundle/bin/jarlist.cache new file mode 100644 index 0000000..1b5ec3f --- /dev/null +++ b/VitamioBundle/bin/jarlist.cache @@ -0,0 +1,3 @@ +# cache for current jar dependecy. DO NOT EDIT. +# format is +# Encoding is UTF-8 diff --git a/VitamioBundle/bin/res/drawable-hdpi/ic_launcher.png b/VitamioBundle/bin/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..d4f6b86 --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/ic_launcher.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_bg.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_bg.png new file mode 100644 index 0000000..7f6b8be --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_bg.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause01.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause01.png new file mode 100644 index 0000000..87c51ee --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause01.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause02.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause02.png new file mode 100644 index 0000000..4b86a66 --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_pause02.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play01.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play01.png new file mode 100644 index 0000000..c525b82 --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play01.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play02.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play02.png new file mode 100644 index 0000000..69ad5ba --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_play02.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar01.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar01.png new file mode 100644 index 0000000..523df41 --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar01.png diff --git a/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar02.png b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar02.png new file mode 100644 index 0000000..4826b52 --- /dev/null +++ b/VitamioBundle/bin/res/drawable-hdpi/mediacontroller_seekbar02.png diff --git a/VitamioBundle/bin/res/drawable-xhdpi/ic_launcher.png b/VitamioBundle/bin/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..bccfd2b --- /dev/null +++ b/VitamioBundle/bin/res/drawable-xhdpi/ic_launcher.png diff --git a/VitamioBundle/build.xml b/VitamioBundle/build.xml new file mode 100644 index 0000000..759dbc2 --- /dev/null +++ b/VitamioBundle/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VitamioBundle/gen/io/vov/vitamio/BuildConfig.java b/VitamioBundle/gen/io/vov/vitamio/BuildConfig.java new file mode 100644 index 0000000..9ebfacc --- /dev/null +++ b/VitamioBundle/gen/io/vov/vitamio/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package io.vov.vitamio; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/VitamioBundle/gen/io/vov/vitamio/R.java b/VitamioBundle/gen/io/vov/vitamio/R.java new file mode 100644 index 0000000..4a79fc8 --- /dev/null +++ b/VitamioBundle/gen/io/vov/vitamio/R.java @@ -0,0 +1,53 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package io.vov.vitamio; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static int ic_launcher=0x7f020000; + public static int mediacontroller_bg=0x7f020001; + public static int mediacontroller_pause01=0x7f020002; + public static int mediacontroller_pause02=0x7f020003; + public static int mediacontroller_pause_button=0x7f020004; + public static int mediacontroller_play01=0x7f020005; + public static int mediacontroller_play02=0x7f020006; + public static int mediacontroller_play_button=0x7f020007; + public static int mediacontroller_seekbar=0x7f020008; + public static int mediacontroller_seekbar01=0x7f020009; + public static int mediacontroller_seekbar02=0x7f02000a; + public static int mediacontroller_seekbar_thumb=0x7f02000b; + } + public static final class id { + public static int mediacontroller_file_name=0x7f070004; + public static int mediacontroller_play_pause=0x7f070000; + public static int mediacontroller_seekbar=0x7f070003; + public static int mediacontroller_time_current=0x7f070001; + public static int mediacontroller_time_total=0x7f070002; + } + public static final class layout { + public static int mediacontroller=0x7f030000; + } + public static final class raw { + public static int libarm=0x7f040000; + } + public static final class string { + public static int mediacontroller_play_pause=0x7f050006; + public static int vitamio_init_decoders=0x7f050001; + public static int vitamio_name=0x7f050000; + public static int vitamio_videoview_error_button=0x7f050005; + public static int vitamio_videoview_error_text_invalid_progressive_playback=0x7f050003; + public static int vitamio_videoview_error_text_unknown=0x7f050004; + public static int vitamio_videoview_error_title=0x7f050002; + } + public static final class style { + public static int MediaController_SeekBar=0x7f060000; + public static int MediaController_Text=0x7f060001; + } +} diff --git a/VitamioBundle/ic_launcher-web.png b/VitamioBundle/ic_launcher-web.png new file mode 100644 index 0000000..6b45524 --- /dev/null +++ b/VitamioBundle/ic_launcher-web.png diff --git a/VitamioBundle/libs/vitamio.jar b/VitamioBundle/libs/vitamio.jar new file mode 100644 index 0000000..291bd58 --- /dev/null +++ b/VitamioBundle/libs/vitamio.jar diff --git a/VitamioBundle/proguard-project.txt b/VitamioBundle/proguard-project.txt new file mode 100644 index 0000000..f2fe155 --- /dev/null +++ b/VitamioBundle/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/VitamioBundle/project.properties b/VitamioBundle/project.properties new file mode 100644 index 0000000..36f1594 --- /dev/null +++ b/VitamioBundle/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-15 +android.library=true diff --git a/VitamioBundle/res/drawable-hdpi/ic_launcher.png b/VitamioBundle/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..c6ba88c --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/ic_launcher.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_bg.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_bg.png new file mode 100644 index 0000000..63b9aa5 --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_bg.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_pause01.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_pause01.png new file mode 100644 index 0000000..698277a --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_pause01.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_pause02.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_pause02.png new file mode 100644 index 0000000..d954a0e --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_pause02.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_play01.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_play01.png new file mode 100644 index 0000000..81bcb26 --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_play01.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_play02.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_play02.png new file mode 100644 index 0000000..67100f8 --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_play02.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar01.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar01.png new file mode 100644 index 0000000..8bcdcab --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar01.png diff --git a/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar02.png b/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar02.png new file mode 100644 index 0000000..b7fd9dd --- /dev/null +++ b/VitamioBundle/res/drawable-hdpi/mediacontroller_seekbar02.png diff --git a/VitamioBundle/res/drawable-xhdpi/ic_launcher.png b/VitamioBundle/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..5add9b7 --- /dev/null +++ b/VitamioBundle/res/drawable-xhdpi/ic_launcher.png diff --git a/VitamioBundle/res/drawable/mediacontroller_pause_button.xml b/VitamioBundle/res/drawable/mediacontroller_pause_button.xml new file mode 100644 index 0000000..ec96825 --- /dev/null +++ b/VitamioBundle/res/drawable/mediacontroller_pause_button.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/res/drawable/mediacontroller_play_button.xml b/VitamioBundle/res/drawable/mediacontroller_play_button.xml new file mode 100644 index 0000000..eb91676 --- /dev/null +++ b/VitamioBundle/res/drawable/mediacontroller_play_button.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/res/drawable/mediacontroller_seekbar.xml b/VitamioBundle/res/drawable/mediacontroller_seekbar.xml new file mode 100644 index 0000000..cc1ab63 --- /dev/null +++ b/VitamioBundle/res/drawable/mediacontroller_seekbar.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/res/drawable/mediacontroller_seekbar_thumb.xml b/VitamioBundle/res/drawable/mediacontroller_seekbar_thumb.xml new file mode 100644 index 0000000..16f3979 --- /dev/null +++ b/VitamioBundle/res/drawable/mediacontroller_seekbar_thumb.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/res/layout/mediacontroller.xml b/VitamioBundle/res/layout/mediacontroller.xml new file mode 100644 index 0000000..4a4afa0 --- /dev/null +++ b/VitamioBundle/res/layout/mediacontroller.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/res/values/strings.xml b/VitamioBundle/res/values/strings.xml new file mode 100644 index 0000000..02d886d --- /dev/null +++ b/VitamioBundle/res/values/strings.xml @@ -0,0 +1,13 @@ + + + + Vitamio + Initializing decoders… + Cannot play video + Sorry, this video is not valid for streaming to + this device. + Sorry, this video cannot be played. + OK + Play/Pause + + \ No newline at end of file diff --git a/VitamioBundle/res/values/styles.xml b/VitamioBundle/res/values/styles.xml new file mode 100644 index 0000000..7c30deb --- /dev/null +++ b/VitamioBundle/res/values/styles.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/VitamioBundle/src/io/vov/vitamio/activity/InitActivity.java b/VitamioBundle/src/io/vov/vitamio/activity/InitActivity.java new file mode 100644 index 0000000..166296c --- /dev/null +++ b/VitamioBundle/src/io/vov/vitamio/activity/InitActivity.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012 YIXIA.COM + * + * 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 io.vov.vitamio.activity; + +import io.vov.vitamio.R; +import io.vov.vitamio.Vitamio; + +import java.lang.ref.WeakReference; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.view.WindowManager; + +public class InitActivity extends Activity { + public static final String FROM_ME = "fromVitamioInitActivity"; + private ProgressDialog mPD; + private UIHandler uiHandler; + + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + uiHandler = new UIHandler(this); + + new AsyncTask() { + @Override + protected void onPreExecute() { + mPD = new ProgressDialog(InitActivity.this); + mPD.setCancelable(false); + mPD.setMessage(getString(R.string.vitamio_init_decoders)); + mPD.show(); + } + + @Override + protected Boolean doInBackground(Object... params) { + return Vitamio.initialize(InitActivity.this); + } + + @Override + protected void onPostExecute(Boolean inited) { + if (inited) { + uiHandler.sendEmptyMessage(0); + } + } + + }.execute(); + } + + private static class UIHandler extends Handler { + private WeakReference mContext; + + public UIHandler(Context c) { + mContext = new WeakReference(c); + } + + public void handleMessage(Message msg) { + InitActivity ctx = (InitActivity) mContext.get(); + switch (msg.what) { + case 0: + ctx.mPD.dismiss(); + Intent src = ctx.getIntent(); + Intent i = new Intent(); + i.setClassName(src.getStringExtra("package"), src.getStringExtra("className")); + i.setData(src.getData()); + i.putExtras(src); + i.putExtra(FROM_ME, true); + ctx.startActivity(i); + ctx.finish(); + break; + } + } + }; +} diff --git a/VitamioBundle/src/io/vov/vitamio/widget/CenterLayout.java b/VitamioBundle/src/io/vov/vitamio/widget/CenterLayout.java new file mode 100644 index 0000000..69727e8 --- /dev/null +++ b/VitamioBundle/src/io/vov/vitamio/widget/CenterLayout.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2012 YIXIA.COM + * + * 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 io.vov.vitamio.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RemoteViews.RemoteView; + +@RemoteView +public class CenterLayout extends ViewGroup { + private int mPaddingLeft = 0; + private int mPaddingRight = 0; + private int mPaddingTop = 0; + private int mPaddingBottom = 0; + private int mWidth, mHeight; + + public CenterLayout(Context context) { + super(context); + } + + public CenterLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CenterLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + + int maxHeight = 0; + int maxWidth = 0; + + measureChildren(widthMeasureSpec, heightMeasureSpec); + + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getVisibility() != GONE) { + int childRight; + int childBottom; + + CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); + + childRight = lp.x + child.getMeasuredWidth(); + childBottom = lp.y + child.getMeasuredHeight(); + + maxWidth = Math.max(maxWidth, childRight); + maxHeight = Math.max(maxHeight, childBottom); + } + } + + maxWidth += mPaddingLeft + mPaddingRight; + maxHeight += mPaddingTop + mPaddingBottom; + + maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); + maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); + + setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int count = getChildCount(); + mWidth = getMeasuredWidth(); + mHeight = getMeasuredHeight(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getVisibility() != GONE) { + CenterLayout.LayoutParams lp = (CenterLayout.LayoutParams) child.getLayoutParams(); + int childLeft = mPaddingLeft + lp.x; + if (lp.width > 0) + childLeft += (int) ((mWidth - lp.width) / 2.0); + else + childLeft += (int) ((mWidth - child.getMeasuredWidth()) / 2.0); + int childTop = mPaddingTop + lp.y; + if (lp.height > 0) + childTop += (int) ((mHeight - lp.height) / 2.0); + else + childTop += (int) ((mHeight - child.getMeasuredHeight()) / 2.0); + child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); + } + } + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof CenterLayout.LayoutParams; + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + return new LayoutParams(p); + } + + public static class LayoutParams extends ViewGroup.LayoutParams { + public int x; + public int y; + + public LayoutParams(int width, int height, int x, int y) { + super(width, height); + this.x = x; + this.y = y; + } + + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + } +} diff --git a/VitamioBundle/src/io/vov/vitamio/widget/MediaController.java b/VitamioBundle/src/io/vov/vitamio/widget/MediaController.java new file mode 100644 index 0000000..3d2e1f9 --- /dev/null +++ b/VitamioBundle/src/io/vov/vitamio/widget/MediaController.java @@ -0,0 +1,511 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2012 YIXIA.COM + * + * 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 io.vov.vitamio.widget; + +import io.vov.utils.Log; +import io.vov.utils.StringUtils; +import io.vov.vitamio.R; +import android.content.Context; +import android.graphics.Rect; +import android.media.AudioManager; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.PopupWindow; +import android.widget.ProgressBar; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +/** + * A view containing controls for a MediaPlayer. Typically contains the buttons + * like "Play/Pause" and a progress slider. It takes care of synchronizing the + * controls with the state of the MediaPlayer. + *

+ * The way to use this class is to a) instantiate it programatically or b) + * create it in your xml layout. + * + * a) The MediaController will create a default set of controls and put them in + * a window floating above your application. Specifically, the controls will + * float above the view specified with setAnchorView(). By default, the window + * will disappear if left idle for three seconds and reappear when the user + * touches the anchor view. To customize the MediaController's style, layout and + * controls you should extend MediaController and override the {#link + * {@link #makeControllerView()} method. + * + * b) The MediaController is a FrameLayout, you can put it in your layout xml + * and get it through {@link #findViewById(int)}. + * + * NOTES: In each way, if you want customize the MediaController, the SeekBar's + * id must be mediacontroller_progress, the Play/Pause's must be + * mediacontroller_pause, current time's must be mediacontroller_time_current, + * total time's must be mediacontroller_time_total, file name's must be + * mediacontroller_file_name. And your resources must have a pause_button + * drawable and a play_button drawable. + *

+ * Functions like show() and hide() have no effect when MediaController is + * created in an xml layout. + */ +public class MediaController extends FrameLayout { + private MediaPlayerControl mPlayer; + private Context mContext; + private PopupWindow mWindow; + private int mAnimStyle; + private View mAnchor; + private View mRoot; + private ProgressBar mProgress; + private TextView mEndTime, mCurrentTime; + private TextView mFileName; + private OutlineTextView mInfoView; + private String mTitle; + private long mDuration; + private boolean mShowing; + private boolean mDragging; + private boolean mInstantSeeking = true; + private static final int sDefaultTimeout = 3000; + private static final int FADE_OUT = 1; + private static final int SHOW_PROGRESS = 2; + private boolean mFromXml = false; + private ImageButton mPauseButton; + + private AudioManager mAM; + + public MediaController(Context context, AttributeSet attrs) { + super(context, attrs); + mRoot = this; + mFromXml = true; + initController(context); + } + + public MediaController(Context context) { + super(context); + if (!mFromXml && initController(context)) + initFloatingWindow(); + } + + private boolean initController(Context context) { + mContext = context; + mAM = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + return true; + } + + @Override + public void onFinishInflate() { + if (mRoot != null) + initControllerView(mRoot); + } + + private void initFloatingWindow() { + mWindow = new PopupWindow(mContext); + mWindow.setFocusable(false); + mWindow.setBackgroundDrawable(null); + mWindow.setOutsideTouchable(true); + mAnimStyle = android.R.style.Animation; + } + + /** + * Set the view that acts as the anchor for the control view. This can for + * example be a VideoView, or your Activity's main view. + * + * @param view + * The view to which to anchor the controller when it is visible. + */ + public void setAnchorView(View view) { + mAnchor = view; + if (!mFromXml) { + removeAllViews(); + mRoot = makeControllerView(); + mWindow.setContentView(mRoot); + mWindow.setWidth(LayoutParams.MATCH_PARENT); + mWindow.setHeight(LayoutParams.WRAP_CONTENT); + } + initControllerView(mRoot); + } + + /** + * Create the view that holds the widgets that control playback. Derived + * classes can override this to create their own. + * + * @return The controller view. + */ + protected View makeControllerView() { + return ((LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.mediacontroller, this); + } + + private void initControllerView(View v) { + mPauseButton = (ImageButton) v.findViewById(R.id.mediacontroller_play_pause); + if (mPauseButton != null) { + mPauseButton.requestFocus(); + mPauseButton.setOnClickListener(mPauseListener); + } + + mProgress = (ProgressBar) v.findViewById(R.id.mediacontroller_seekbar); + if (mProgress != null) { + if (mProgress instanceof SeekBar) { + SeekBar seeker = (SeekBar) mProgress; + seeker.setOnSeekBarChangeListener(mSeekListener); + seeker.setThumbOffset(1); + } + mProgress.setMax(1000); + } + + mEndTime = (TextView) v.findViewById(R.id.mediacontroller_time_total); + mCurrentTime = (TextView) v.findViewById(R.id.mediacontroller_time_current); + mFileName = (TextView) v.findViewById(R.id.mediacontroller_file_name); + if (mFileName != null) + mFileName.setText(mTitle); + } + + public void setMediaPlayer(MediaPlayerControl player) { + mPlayer = player; + updatePausePlay(); + } + + /** + * Control the action when the seekbar dragged by user + * + * @param seekWhenDragging + * True the media will seek periodically + */ + public void setInstantSeeking(boolean seekWhenDragging) { + mInstantSeeking = seekWhenDragging; + } + + public void show() { + show(sDefaultTimeout); + } + + /** + * Set the content of the file_name TextView + * + * @param name + */ + public void setFileName(String name) { + mTitle = name; + if (mFileName != null) + mFileName.setText(mTitle); + } + + /** + * Set the View to hold some information when interact with the + * MediaController + * + * @param v + */ + public void setInfoView(OutlineTextView v) { + mInfoView = v; + } + + private void disableUnsupportedButtons() { + try { + if (mPauseButton != null && !mPlayer.canPause()) + mPauseButton.setEnabled(false); + } catch (IncompatibleClassChangeError ex) { + } + } + + /** + *

+ * Change the animation style resource for this controller. + *

+ * + *

+ * If the controller is showing, calling this method will take effect only + * the next time the controller is shown. + *

+ * + * @param animationStyle + * animation style to use when the controller appears and + * disappears. Set to -1 for the default animation, 0 for no + * animation, or a resource identifier for an explicit animation. + * + */ + public void setAnimationStyle(int animationStyle) { + mAnimStyle = animationStyle; + } + + /** + * Show the controller on screen. It will go away automatically after + * 'timeout' milliseconds of inactivity. + * + * @param timeout + * The timeout in milliseconds. Use 0 to show the controller + * until hide() is called. + */ + public void show(int timeout) { + if (!mShowing && mAnchor != null && mAnchor.getWindowToken() != null) { + if (mPauseButton != null) + mPauseButton.requestFocus(); + disableUnsupportedButtons(); + + if (mFromXml) { + setVisibility(View.VISIBLE); + } else { + int[] location = new int[2]; + + mAnchor.getLocationOnScreen(location); + Rect anchorRect = new Rect(location[0], location[1], location[0] + mAnchor.getWidth(), location[1] + mAnchor.getHeight()); + + mWindow.setAnimationStyle(mAnimStyle); + mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, anchorRect.left, anchorRect.bottom); + } + mShowing = true; + if (mShownListener != null) + mShownListener.onShown(); + } + updatePausePlay(); + mHandler.sendEmptyMessage(SHOW_PROGRESS); + + if (timeout != 0) { + mHandler.removeMessages(FADE_OUT); + mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_OUT), timeout); + } + } + + public boolean isShowing() { + return mShowing; + } + + public void hide() { + if (mAnchor == null) + return; + + if (mShowing) { + try { + mHandler.removeMessages(SHOW_PROGRESS); + if (mFromXml) + setVisibility(View.GONE); + else + mWindow.dismiss(); + } catch (IllegalArgumentException ex) { + Log.d("MediaController already removed"); + } + mShowing = false; + if (mHiddenListener != null) + mHiddenListener.onHidden(); + } + } + + public interface OnShownListener { + public void onShown(); + } + + private OnShownListener mShownListener; + + public void setOnShownListener(OnShownListener l) { + mShownListener = l; + } + + public interface OnHiddenListener { + public void onHidden(); + } + + private OnHiddenListener mHiddenListener; + + public void setOnHiddenListener(OnHiddenListener l) { + mHiddenListener = l; + } + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + long pos; + switch (msg.what) { + case FADE_OUT: + hide(); + break; + case SHOW_PROGRESS: + pos = setProgress(); + if (!mDragging && mShowing) { + msg = obtainMessage(SHOW_PROGRESS); + sendMessageDelayed(msg, 1000 - (pos % 1000)); + updatePausePlay(); + } + break; + } + } + }; + + private long setProgress() { + if (mPlayer == null || mDragging) + return 0; + + long position = mPlayer.getCurrentPosition(); + long duration = mPlayer.getDuration(); + if (mProgress != null) { + if (duration > 0) { + long pos = 1000L * position / duration; + mProgress.setProgress((int) pos); + } + int percent = mPlayer.getBufferPercentage(); + mProgress.setSecondaryProgress(percent * 10); + } + + mDuration = duration; + + if (mEndTime != null) + mEndTime.setText(StringUtils.generateTime(mDuration)); + if (mCurrentTime != null) + mCurrentTime.setText(StringUtils.generateTime(position)); + + return position; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + show(sDefaultTimeout); + return true; + } + + @Override + public boolean onTrackballEvent(MotionEvent ev) { + show(sDefaultTimeout); + return false; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + int keyCode = event.getKeyCode(); + if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) { + doPauseResume(); + show(sDefaultTimeout); + if (mPauseButton != null) + mPauseButton.requestFocus(); + return true; + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) { + if (mPlayer.isPlaying()) { + mPlayer.pause(); + updatePausePlay(); + } + return true; + } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { + hide(); + return true; + } else { + show(sDefaultTimeout); + } + return super.dispatchKeyEvent(event); + } + + private View.OnClickListener mPauseListener = new View.OnClickListener() { + public void onClick(View v) { + doPauseResume(); + show(sDefaultTimeout); + } + }; + + private void updatePausePlay() { + if (mRoot == null || mPauseButton == null) + return; + + if (mPlayer.isPlaying()) + mPauseButton.setImageResource(R.drawable.mediacontroller_pause_button); + else + mPauseButton.setImageResource(R.drawable.mediacontroller_play_button); + } + + private void doPauseResume() { + if (mPlayer.isPlaying()) + mPlayer.pause(); + else + mPlayer.start(); + updatePausePlay(); + } + + private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { + public void onStartTrackingTouch(SeekBar bar) { + mDragging = true; + show(3600000); + mHandler.removeMessages(SHOW_PROGRESS); + if (mInstantSeeking) + mAM.setStreamMute(AudioManager.STREAM_MUSIC, true); + if (mInfoView != null) { + mInfoView.setText(""); + mInfoView.setVisibility(View.VISIBLE); + } + } + + public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) { + if (!fromuser) + return; + + long newposition = (mDuration * progress) / 1000; + String time = StringUtils.generateTime(newposition); + if (mInstantSeeking) + mPlayer.seekTo(newposition); + if (mInfoView != null) + mInfoView.setText(time); + if (mCurrentTime != null) + mCurrentTime.setText(time); + } + + public void onStopTrackingTouch(SeekBar bar) { + if (!mInstantSeeking) + mPlayer.seekTo((mDuration * bar.getProgress()) / 1000); + if (mInfoView != null) { + mInfoView.setText(""); + mInfoView.setVisibility(View.GONE); + } + show(sDefaultTimeout); + mHandler.removeMessages(SHOW_PROGRESS); + mAM.setStreamMute(AudioManager.STREAM_MUSIC, false); + mDragging = false; + mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000); + } + }; + + @Override + public void setEnabled(boolean enabled) { + if (mPauseButton != null) + mPauseButton.setEnabled(enabled); + if (mProgress != null) + mProgress.setEnabled(enabled); + disableUnsupportedButtons(); + super.setEnabled(enabled); + } + + public interface MediaPlayerControl { + void start(); + + void pause(); + + long getDuration(); + + long getCurrentPosition(); + + void seekTo(long pos); + + boolean isPlaying(); + + int getBufferPercentage(); + + boolean canPause(); + + boolean canSeekBackward(); + + boolean canSeekForward(); + } + +} diff --git a/VitamioBundle/src/io/vov/vitamio/widget/OutlineTextView.java b/VitamioBundle/src/io/vov/vitamio/widget/OutlineTextView.java new file mode 100644 index 0000000..ac02fbc --- /dev/null +++ b/VitamioBundle/src/io/vov/vitamio/widget/OutlineTextView.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011 Cedric Fung (wolfplanet@gmail.com) + * + * 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 io.vov.vitamio.widget; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.AttributeSet; +import android.widget.TextView; + +/** + * Display text with border, use the same XML attrs as + * {@link android.widget.TextView}, except that {@link OutlineTextView} will + * transform the shadow to border + */ +@SuppressLint("DrawAllocation") +public class OutlineTextView extends TextView { + public OutlineTextView(Context context) { + super(context); + initPaint(); + } + + public OutlineTextView(Context context, AttributeSet attrs) { + super(context, attrs); + initPaint(); + } + + public OutlineTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initPaint(); + } + + private void initPaint() { + mTextPaint = new TextPaint(); + mTextPaint.setAntiAlias(true); + mTextPaint.setTextSize(getTextSize()); + mTextPaint.setColor(mColor); + mTextPaint.setStyle(Paint.Style.FILL); + mTextPaint.setTypeface(getTypeface()); + + mTextPaintOutline = new TextPaint(); + mTextPaintOutline.setAntiAlias(true); + mTextPaintOutline.setTextSize(getTextSize()); + mTextPaintOutline.setColor(mBorderColor); + mTextPaintOutline.setStyle(Paint.Style.STROKE); + mTextPaintOutline.setTypeface(getTypeface()); + mTextPaintOutline.setStrokeWidth(mBorderSize); + } + + public void setText(String text) { + super.setText(text); + mText = text.toString(); + requestLayout(); + invalidate(); + } + + public void setTextSize(float size) { + super.setTextSize(size); + requestLayout(); + invalidate(); + initPaint(); + } + + public void setTextColor(int color) { + super.setTextColor(color); + mColor = color; + invalidate(); + initPaint(); + } + + public void setShadowLayer(float radius, float dx, float dy, int color) { + super.setShadowLayer(radius, dx, dy, color); + mBorderSize = radius; + mBorderColor = color; + requestLayout(); + invalidate(); + initPaint(); + } + + public void setTypeface(Typeface tf, int style) { + super.setTypeface(tf, style); + requestLayout(); + invalidate(); + initPaint(); + } + + public void setTypeface(Typeface tf) { + super.setTypeface(tf); + requestLayout(); + invalidate(); + initPaint(); + } + + @Override + protected void onDraw(Canvas canvas) { + Layout layout = new StaticLayout(getText(), mTextPaintOutline, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); + layout.draw(canvas); + layout = new StaticLayout(getText(), mTextPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); + layout.draw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + Layout layout = new StaticLayout(getText(), mTextPaintOutline, measureWidth(widthMeasureSpec), Layout.Alignment.ALIGN_CENTER, mSpacingMult, mSpacingAdd, mIncludePad); + int ex = (int) (mBorderSize * 2 + 1); + setMeasuredDimension(measureWidth(widthMeasureSpec) + ex, measureHeight(heightMeasureSpec) * layout.getLineCount() + ex); + } + + private int measureWidth(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = (int) mTextPaintOutline.measureText(mText) + getPaddingLeft() + getPaddingRight(); + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + + return result; + } + + private int measureHeight(int measureSpec) { + int result = 0; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + mAscent = (int) mTextPaintOutline.ascent(); + if (specMode == MeasureSpec.EXACTLY) { + result = specSize; + } else { + result = (int) (-mAscent + mTextPaintOutline.descent()) + getPaddingTop() + getPaddingBottom(); + if (specMode == MeasureSpec.AT_MOST) { + result = Math.min(result, specSize); + } + } + return result; + } + + private TextPaint mTextPaint; + private TextPaint mTextPaintOutline; + private String mText = ""; + private int mAscent = 0; + private float mBorderSize; + private int mBorderColor; + private int mColor; + private float mSpacingMult = 1.0f; + private float mSpacingAdd = 0; + private boolean mIncludePad = true; +} \ No newline at end of file diff --git a/VitamioBundle/src/io/vov/vitamio/widget/VideoView.java b/VitamioBundle/src/io/vov/vitamio/widget/VideoView.java new file mode 100644 index 0000000..31d61d2 --- /dev/null +++ b/VitamioBundle/src/io/vov/vitamio/widget/VideoView.java @@ -0,0 +1,721 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2012 YIXIA.COM + * + * 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 io.vov.vitamio.widget; + +import io.vov.utils.Log; +import io.vov.vitamio.MediaPlayer; +import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener; +import io.vov.vitamio.MediaPlayer.OnCompletionListener; +import io.vov.vitamio.MediaPlayer.OnErrorListener; +import io.vov.vitamio.MediaPlayer.OnInfoListener; +import io.vov.vitamio.MediaPlayer.OnPreparedListener; +import io.vov.vitamio.MediaPlayer.OnSeekCompleteListener; +import io.vov.vitamio.MediaPlayer.OnSubtitleUpdateListener; +import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener; +import io.vov.vitamio.R; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.media.AudioManager; +import android.net.Uri; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup.LayoutParams; + +/** + * Displays a video file. The VideoView class can load images from various + * sources (such as resources or content providers), takes care of computing its + * measurement from the video so that it can be used in any layout manager, and + * provides various display options such as scaling and tinting. + * + * VideoView also provide many wrapper methods for + * {@link io.vov.vitamio.MediaPlayer}, such as {@link #getVideoWidth()}, + * {@link #setSubShown(boolean)} + */ +public class VideoView extends SurfaceView implements MediaController.MediaPlayerControl { + private Uri mUri; + private long mDuration; + + 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; + private static final int STATE_SUSPEND = 6; + private static final int STATE_RESUME = 7; + private static final int STATE_SUSPEND_UNSUPPORTED = 8; + + private int mCurrentState = STATE_IDLE; + private int mTargetState = STATE_IDLE; + + private float mAspectRatio = 0; + private int mVideoLayout = VIDEO_LAYOUT_SCALE; + public static final int VIDEO_LAYOUT_ORIGIN = 0; + public static final int VIDEO_LAYOUT_SCALE = 1; + public static final int VIDEO_LAYOUT_STRETCH = 2; + public static final int VIDEO_LAYOUT_ZOOM = 3; + + private SurfaceHolder mSurfaceHolder = null; + private MediaPlayer mMediaPlayer = null; + private int mVideoWidth; + private int mVideoHeight; + private float mVideoAspectRatio; + private int mSurfaceWidth; + private int mSurfaceHeight; + private MediaController mMediaController; + private OnCompletionListener mOnCompletionListener; + private OnPreparedListener mOnPreparedListener; + private OnErrorListener mOnErrorListener; + private OnSeekCompleteListener mOnSeekCompleteListener; + private OnSubtitleUpdateListener mOnSubtitleUpdateListener; + private OnInfoListener mOnInfoListener; + private OnBufferingUpdateListener mOnBufferingUpdateListener; + private int mCurrentBufferPercentage; + private long mSeekWhenPrepared; + private boolean mCanPause = true; + private boolean mCanSeekBack = true; + private boolean mCanSeekForward = true; + private Context mContext; + + public VideoView(Context context) { + super(context); + initVideoView(context); + } + + public VideoView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public VideoView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initVideoView(context); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = getDefaultSize(mVideoWidth, widthMeasureSpec); + int height = getDefaultSize(mVideoHeight, heightMeasureSpec); + setMeasuredDimension(width, height); + } + + /** + * Set the display options + * + * @param layout + *
    + *
  • {@link #VIDEO_LAYOUT_ORIGIN} + *
  • {@link #VIDEO_LAYOUT_SCALE} + *
  • {@link #VIDEO_LAYOUT_STRETCH} + *
  • {@link #VIDEO_LAYOUT_ZOOM} + *
+ * @param aspectRatio + * video aspect ratio, will audo detect if 0. + */ + public void setVideoLayout(int layout, float aspectRatio) { + LayoutParams lp = getLayoutParams(); + DisplayMetrics disp = mContext.getResources().getDisplayMetrics(); + int windowWidth = disp.widthPixels, windowHeight = disp.heightPixels; + float windowRatio = windowWidth / (float) windowHeight; + float videoRatio = aspectRatio <= 0.01f ? mVideoAspectRatio : aspectRatio; + mSurfaceHeight = mVideoHeight; + mSurfaceWidth = mVideoWidth; + if (VIDEO_LAYOUT_ORIGIN == layout && mSurfaceWidth < windowWidth && mSurfaceHeight < windowHeight) { + lp.width = (int) (mSurfaceHeight * videoRatio); + lp.height = mSurfaceHeight; + } else if (layout == VIDEO_LAYOUT_ZOOM) { + lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight); + lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio); + } else { + boolean full = layout == VIDEO_LAYOUT_STRETCH; + lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight); + lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio); + } + setLayoutParams(lp); + getHolder().setFixedSize(mSurfaceWidth, mSurfaceHeight); + Log.d("VIDEO: %dx%dx%f, Surface: %dx%d, LP: %dx%d, Window: %dx%dx%f", mVideoWidth, mVideoHeight, mVideoAspectRatio, mSurfaceWidth, mSurfaceHeight, lp.width, lp.height, windowWidth, windowHeight, windowRatio); + mVideoLayout = layout; + mAspectRatio = aspectRatio; + } + + private void initVideoView(Context ctx) { + mContext = ctx; + mVideoWidth = 0; + mVideoHeight = 0; + getHolder().addCallback(mSHCallback); + setFocusable(true); + setFocusableInTouchMode(true); + requestFocus(); + mCurrentState = STATE_IDLE; + mTargetState = STATE_IDLE; + if (ctx instanceof Activity) + ((Activity) ctx).setVolumeControlStream(AudioManager.STREAM_MUSIC); + } + + public boolean isValid() { + return (mSurfaceHolder != null && mSurfaceHolder.getSurface().isValid()); + } + + public void setVideoPath(String path) { + setVideoURI(Uri.parse(path)); + } + + public void setVideoURI(Uri uri) { + mUri = uri; + mSeekWhenPrepared = 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 (mUri == null || mSurfaceHolder == null) + return; + + Intent i = new Intent("com.android.music.musicservicecommand"); + i.putExtra("command", "pause"); + mContext.sendBroadcast(i); + + release(false); + try { + mDuration = -1; + mCurrentBufferPercentage = 0; + mMediaPlayer = new MediaPlayer(mContext); + mMediaPlayer.setOnPreparedListener(mPreparedListener); + mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); + mMediaPlayer.setOnCompletionListener(mCompletionListener); + mMediaPlayer.setOnErrorListener(mErrorListener); + mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); + mMediaPlayer.setOnInfoListener(mInfoListener); + mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener); + mMediaPlayer.setOnSubtitleUpdateListener(mSubtitleUpdateListener); + mMediaPlayer.setDataSource(mContext, mUri); + mMediaPlayer.setDisplay(mSurfaceHolder); + mMediaPlayer.setScreenOnWhilePlaying(true); + mMediaPlayer.prepareAsync(); + mCurrentState = STATE_PREPARING; + attachMediaController(); + } catch (IOException ex) { + Log.e("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.e("Unable to open content: " + mUri, ex); + mCurrentState = STATE_ERROR; + mTargetState = STATE_ERROR; + mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); + return; + } + } + + public void setMediaController(MediaController controller) { + if (mMediaController != null) + mMediaController.hide(); + mMediaController = controller; + attachMediaController(); + } + + private void attachMediaController() { + if (mMediaPlayer != null && mMediaController != null) { + mMediaController.setMediaPlayer(this); + View anchorView = this.getParent() instanceof View ? (View) this.getParent() : this; + mMediaController.setAnchorView(anchorView); + mMediaController.setEnabled(isInPlaybackState()); + + if (mUri != null) { + List paths = mUri.getPathSegments(); + String name = paths == null || paths.isEmpty() ? "null" : paths.get(paths.size() - 1); + mMediaController.setFileName(name); + } + } + } + + OnVideoSizeChangedListener mSizeChangedListener = new OnVideoSizeChangedListener() { + public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { + Log.d("onVideoSizeChanged: (%dx%d)", width, height); + mVideoWidth = mp.getVideoWidth(); + mVideoHeight = mp.getVideoHeight(); + mVideoAspectRatio = mp.getVideoAspectRatio(); + if (mVideoWidth != 0 && mVideoHeight != 0) + setVideoLayout(mVideoLayout, mAspectRatio); + } + }; + + OnPreparedListener mPreparedListener = new OnPreparedListener() { + public void onPrepared(MediaPlayer mp) { + Log.d("onPrepared"); + mCurrentState = STATE_PREPARED; + mTargetState = STATE_PLAYING; + + if (mOnPreparedListener != null) + mOnPreparedListener.onPrepared(mMediaPlayer); + if (mMediaController != null) + mMediaController.setEnabled(true); + mVideoWidth = mp.getVideoWidth(); + mVideoHeight = mp.getVideoHeight(); + mVideoAspectRatio = mp.getVideoAspectRatio(); + + long seekToPosition = mSeekWhenPrepared; + + if (seekToPosition != 0) + seekTo(seekToPosition); + if (mVideoWidth != 0 && mVideoHeight != 0) { + setVideoLayout(mVideoLayout, mAspectRatio); + if (mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) { + if (mTargetState == STATE_PLAYING) { + start(); + if (mMediaController != null) + mMediaController.show(); + } else if (!isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) { + if (mMediaController != null) + mMediaController.show(0); + } + } + } else if (mTargetState == STATE_PLAYING) { + start(); + } + } + }; + + private OnCompletionListener mCompletionListener = new OnCompletionListener() { + public void onCompletion(MediaPlayer mp) { + Log.d("onCompletion"); + mCurrentState = STATE_PLAYBACK_COMPLETED; + mTargetState = STATE_PLAYBACK_COMPLETED; + if (mMediaController != null) + mMediaController.hide(); + if (mOnCompletionListener != null) + mOnCompletionListener.onCompletion(mMediaPlayer); + } + }; + + private OnErrorListener mErrorListener = new OnErrorListener() { + public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { + Log.d("Error: %d, %d", framework_err, impl_err); + mCurrentState = STATE_ERROR; + mTargetState = STATE_ERROR; + if (mMediaController != null) + mMediaController.hide(); + + if (mOnErrorListener != null) { + if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) + return true; + } + + if (getWindowToken() != null) { + int message = framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK ? R.string.vitamio_videoview_error_text_invalid_progressive_playback : R.string.vitamio_videoview_error_text_unknown; + + new AlertDialog.Builder(mContext).setTitle(R.string.vitamio_videoview_error_title).setMessage(message).setPositiveButton(R.string.vitamio_videoview_error_button, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + if (mOnCompletionListener != null) + mOnCompletionListener.onCompletion(mMediaPlayer); + } + }).setCancelable(false).show(); + } + return true; + } + }; + + private OnBufferingUpdateListener mBufferingUpdateListener = new OnBufferingUpdateListener() { + public void onBufferingUpdate(MediaPlayer mp, int percent) { + mCurrentBufferPercentage = percent; + if (mOnBufferingUpdateListener != null) + mOnBufferingUpdateListener.onBufferingUpdate(mp, percent); + } + }; + + private OnInfoListener mInfoListener = new OnInfoListener() { + @Override + public boolean onInfo(MediaPlayer mp, int what, int extra) { + Log.d("onInfo: (%d, %d)", what, extra); + if (mOnInfoListener != null) { + mOnInfoListener.onInfo(mp, what, extra); + } else if (mMediaPlayer != null) { + if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) + mMediaPlayer.pause(); + else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) + mMediaPlayer.start(); + } + + return true; + } + }; + + private OnSeekCompleteListener mSeekCompleteListener = new OnSeekCompleteListener() { + @Override + public void onSeekComplete(MediaPlayer mp) { + Log.d("onSeekComplete"); + if (mOnSeekCompleteListener != null) + mOnSeekCompleteListener.onSeekComplete(mp); + } + }; + + private OnSubtitleUpdateListener mSubtitleUpdateListener = new OnSubtitleUpdateListener() { + @Override + public void onSubtitleUpdate(byte[] pixels, int width, int height) { + Log.i("onSubtitleUpdate: bitmap subtitle, %dx%d", width, height); + if (mOnSubtitleUpdateListener != null) + mOnSubtitleUpdateListener.onSubtitleUpdate(pixels, width, height); + } + + @Override + public void onSubtitleUpdate(String text) { + Log.i("onSubtitleUpdate: %s", text); + if (mOnSubtitleUpdateListener != null) + mOnSubtitleUpdateListener.onSubtitleUpdate(text); + } + }; + + public void setOnPreparedListener(OnPreparedListener l) { + mOnPreparedListener = l; + } + + public void setOnCompletionListener(OnCompletionListener l) { + mOnCompletionListener = l; + } + + public void setOnErrorListener(OnErrorListener l) { + mOnErrorListener = l; + } + + public void setOnBufferingUpdateListener(OnBufferingUpdateListener l) { + mOnBufferingUpdateListener = l; + } + + public void setOnSeekCompleteListener(OnSeekCompleteListener l) { + mOnSeekCompleteListener = l; + } + + public void setOnSubtitleUpdateListener(OnSubtitleUpdateListener l) { + mOnSubtitleUpdateListener = l; + } + + public void setOnInfoListener(OnInfoListener l) { + mOnInfoListener = l; + } + + SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + mSurfaceWidth = w; + mSurfaceHeight = h; + boolean isValidState = (mTargetState == STATE_PLAYING); + boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h); + if (mMediaPlayer != null && isValidState && hasValidSize) { + if (mSeekWhenPrepared != 0) + seekTo(mSeekWhenPrepared); + start(); + if (mMediaController != null) { + if (mMediaController.isShowing()) + mMediaController.hide(); + mMediaController.show(); + } + } + } + + public void surfaceCreated(SurfaceHolder holder) { + mSurfaceHolder = holder; + if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND && mTargetState == STATE_RESUME) { + mMediaPlayer.setDisplay(mSurfaceHolder); + resume(); + } else { + openVideo(); + } + } + + public void surfaceDestroyed(SurfaceHolder holder) { + mSurfaceHolder = null; + if (mMediaController != null) + mMediaController.hide(); + if (mCurrentState != STATE_SUSPEND) + release(true); + } + }; + + private void release(boolean cleartargetstate) { + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + mCurrentState = STATE_IDLE; + if (cleartargetstate) + mTargetState = STATE_IDLE; + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (isInPlaybackState() && mMediaController != null) + toggleMediaControlsVisiblity(); + return false; + } + + @Override + public boolean onTrackballEvent(MotionEvent ev) { + if (isInPlaybackState() && mMediaController != null) + toggleMediaControlsVisiblity(); + return false; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_MENU && keyCode != KeyEvent.KEYCODE_CALL && keyCode != KeyEvent.KEYCODE_ENDCALL; + if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) { + if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE) { + if (mMediaPlayer.isPlaying()) { + pause(); + mMediaController.show(); + } else { + start(); + mMediaController.hide(); + } + return true; + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP && mMediaPlayer.isPlaying()) { + pause(); + mMediaController.show(); + } else { + toggleMediaControlsVisiblity(); + } + } + + return super.onKeyDown(keyCode, event); + } + + private void toggleMediaControlsVisiblity() { + if (mMediaController.isShowing()) { + mMediaController.hide(); + } else { + mMediaController.show(); + } + } + + public void start() { + if (isInPlaybackState()) { + mMediaPlayer.start(); + mCurrentState = STATE_PLAYING; + } + mTargetState = STATE_PLAYING; + } + + public void pause() { + if (isInPlaybackState()) { + if (mMediaPlayer.isPlaying()) { + mMediaPlayer.pause(); + mCurrentState = STATE_PAUSED; + } + } + mTargetState = STATE_PAUSED; + } + + public void suspend() { + if (isInPlaybackState()) { + release(false); + mCurrentState = STATE_SUSPEND_UNSUPPORTED; + Log.d("Unable to suspend video. Release MediaPlayer."); + } + } + + public void resume() { + if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND) { + mTargetState = STATE_RESUME; + } else if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) { + openVideo(); + } + } + + public long getDuration() { + if (isInPlaybackState()) { + if (mDuration > 0) + return mDuration; + mDuration = mMediaPlayer.getDuration(); + return mDuration; + } + mDuration = -1; + return mDuration; + } + + public long getCurrentPosition() { + if (isInPlaybackState()) + return mMediaPlayer.getCurrentPosition(); + return 0; + } + + public void seekTo(long 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 void setVolume(float leftVolume, float rightVolume) { + if (mMediaPlayer != null) + mMediaPlayer.setVolume(leftVolume, rightVolume); + } + + public int getVideoWidth() { + return mVideoWidth; + } + + public int getVideoHeight() { + return mVideoHeight; + } + + public float getVideoAspectRatio() { + return mVideoAspectRatio; + } + + public void setVideoQuality(int quality) { + if (mMediaPlayer != null) + mMediaPlayer.setVideoQuality(quality); + } + + public void setBufferSize(int bufSize) { + if (mMediaPlayer != null) + mMediaPlayer.setBufferSize(bufSize); + } + + public boolean isBuffering() { + if (mMediaPlayer != null) + return mMediaPlayer.isBuffering(); + return false; + } + + public void setMetaEncoding(String encoding) { + if (mMediaPlayer != null) + mMediaPlayer.setMetaEncoding(encoding); + } + + public String getMetaEncoding() { + if (mMediaPlayer != null) + return mMediaPlayer.getMetaEncoding(); + return null; + } + + public HashMap getAudioTrackMap(String encoding) { + if (mMediaPlayer != null) + return mMediaPlayer.getAudioTrackMap(encoding); + return null; + } + + public int getAudioTrack() { + if (mMediaPlayer != null) + return mMediaPlayer.getAudioTrack(); + return -1; + } + + public void setAudioTrack(int audioIndex) { + if (mMediaPlayer != null) + mMediaPlayer.setAudioTrack(audioIndex); + } + + public void setSubShown(boolean shown) { + if (mMediaPlayer != null) + mMediaPlayer.setSubShown(shown); + } + + public void setSubEncoding(String encoding) { + if (mMediaPlayer != null) + mMediaPlayer.setSubEncoding(encoding); + } + + public int getSubLocation() { + if (mMediaPlayer != null) + return mMediaPlayer.getSubLocation(); + return -1; + } + + public void setSubPath(String subPath) { + if (mMediaPlayer != null) + mMediaPlayer.setSubPath(subPath); + } + + public String getSubPath() { + if (mMediaPlayer != null) + return mMediaPlayer.getSubPath(); + return null; + } + + public void setSubTrack(int trackId) { + if (mMediaPlayer != null) + mMediaPlayer.setSubTrack(trackId); + } + + public int getSubTrack() { + if (mMediaPlayer != null) + return mMediaPlayer.getSubTrack(); + return -1; + } + + public HashMap getSubTrackMap(String encoding) { + if (mMediaPlayer != null) + return mMediaPlayer.getSubTrackMap(encoding); + return null; + } + + protected boolean isInPlaybackState() { + return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); + } + + public boolean canPause() { + return mCanPause; + } + + public boolean canSeekBackward() { + return mCanSeekBack; + } + + public boolean canSeekForward() { + return mCanSeekForward; + } +} diff --git a/project.properties b/project.properties index b7c2081..89dee5e 100644 --- a/project.properties +++ b/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-10 +android.library.reference.1=VitamioBundle diff --git a/res/layout/activity_video.xml b/res/layout/activity_video.xml index 5295250..d604eb2 100644 --- a/res/layout/activity_video.xml +++ b/res/layout/activity_video.xml @@ -3,7 +3,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" > -