summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLikai Ding <likaid@codeaurora.org>2013-08-19 16:33:24 +0800
committerXiaojing Zhang <zhangx@codeaurora.org>2014-11-04 20:38:02 -0800
commitd42e6dcbee24b917936c1d670ca659970c76d4d1 (patch)
tree518ec0bbbd08a24abdb8e415d9de0f301fb4a095
parent9bc105fca37faf4c868987b3a22992e39e4348f2 (diff)
downloadandroid_packages_apps_Gallery2-d42e6dcbee24b917936c1d670ca659970c76d4d1.tar.gz
android_packages_apps_Gallery2-d42e6dcbee24b917936c1d670ca659970c76d4d1.tar.bz2
android_packages_apps_Gallery2-d42e6dcbee24b917936c1d670ca659970c76d4d1.zip
Gallery2: support live streaming and bookmarks
Users can input a URL for streaming display. URL bookmarking is supported. Change-Id: Ia69497cdcfee963ba2209119a5b9dc82b64497da
-rwxr-xr-x[-rw-r--r--]Android.mk6
-rw-r--r--AndroidManifest.xml29
-rw-r--r--proguard.flags3
-rw-r--r--[-rwxr-xr-x]res/drawable-hdpi/ic_menu_display_bookmark.pngbin1717 -> 1717 bytes
-rw-r--r--[-rwxr-xr-x]res/drawable-mdpi/ic_menu_display_bookmark.pngbin1709 -> 1709 bytes
-rw-r--r--[-rwxr-xr-x]res/drawable-xhdpi/ic_menu_display_bookmark.pngbin2460 -> 2460 bytes
-rw-r--r--[-rwxr-xr-x]res/layout/bookmark.xml17
-rw-r--r--[-rwxr-xr-x]res/layout/bookmark_edit_dialog.xml46
-rw-r--r--[-rwxr-xr-x]res/layout/bookmark_item.xml20
-rw-r--r--res/layout/movie_view.xml2
-rw-r--r--res/values-zh-rCN/codeaurora_strings.xml64
-rw-r--r--res/values-zh-rTW/codeaurora_strings.xml64
-rwxr-xr-xres/values/bool.xml1
-rw-r--r--res/values/codeaurora_strings.xml64
-rw-r--r--[-rwxr-xr-x]res/xml/rtsp_settings_preferences.xml98
-rw-r--r--src/com/android/gallery3d/app/ControllerOverlay.java2
-rw-r--r--src/com/android/gallery3d/app/MovieActivity.java228
-rwxr-xr-x[-rw-r--r--]src/com/android/gallery3d/app/MoviePlayer.java782
-rw-r--r--src/com/android/gallery3d/app/TrimVideo.java6
-rwxr-xr-xsrc/com/qcom/gallery3d/video/DmReceiver.java82
-rwxr-xr-xsrc/com/qcom/gallery3d/video/QcomVideoView.java721
-rw-r--r--src/org/codeaurora/gallery3d/ext/IMoviePlayer.java18
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/gallery3d/video/BookmarkActivity.java (renamed from src/com/qcom/gallery3d/video/BookmarkActivity.java)106
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/gallery3d/video/BookmarkEnhance.java (renamed from src/com/qcom/gallery3d/video/BookmarkEnhance.java)66
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/gallery3d/video/BookmarkHooker.java (renamed from src/com/qcom/gallery3d/video/BookmarkHooker.java)42
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/CodeauroraVideoView.java1032
-rw-r--r--src/org/codeaurora/gallery3d/video/DmReceiver.java65
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/ExtensionHelper.java6
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/gallery3d/video/MovieTitleHelper.java (renamed from src/com/qcom/gallery3d/video/MovieTitleHelper.java)48
-rwxr-xr-xsrc/org/codeaurora/gallery3d/video/SettingsActivity.java (renamed from src/com/qcom/gallery3d/video/SettingsActivity.java)158
-rw-r--r--[-rwxr-xr-x]src/org/codeaurora/gallery3d/video/StreamingHooker.java (renamed from src/com/qcom/gallery3d/video/StreamingHooker.java)67
31 files changed, 2576 insertions, 1267 deletions
diff --git a/Android.mk b/Android.mk
index 3d5663e6b..0edfca54d 100644..100755
--- a/Android.mk
+++ b/Android.mk
@@ -4,6 +4,8 @@ include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := telephony-common
+
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v13
LOCAL_STATIC_JAVA_LIBRARIES += com.android.gallery3d.common2
LOCAL_STATIC_JAVA_LIBRARIES += xmp_toolkit
@@ -29,9 +31,11 @@ LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_PACKAGE_NAME := Gallery2
+LOCAL_CERTIFICATE := platform
+
LOCAL_OVERRIDES_PACKAGES := Gallery Gallery3D GalleryNew3D
-LOCAL_SDK_VERSION := current
+#LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libjni_eglfence libjni_filtershow_filters librsjni libjni_jpegstream
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 52048895b..58b2a1a6f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -29,6 +29,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="com.android.gallery3d.permission.GALLERY_PROVIDER" />
@@ -364,5 +365,33 @@
</receiver>
<service android:name="com.android.camera.MediaSaveService" />
+
+ <activity android:name="org.codeaurora.gallery3d.video.SettingsActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:label="@string/streaming_settings" >
+ <intent-filter>
+ <action android:name="org.codeaurora.settings.streaming" />
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <receiver android:name="org.codeaurora.gallery3d.video.DmReceiver" >
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="streaming.action.WRITE_SETTINGS" />
+ </intent-filter>
+ </receiver>
+
+ <activity android:name="org.codeaurora.gallery3d.video.BookmarkActivity"
+ android:configChanges="keyboardHidden|orientation|screenSize"
+ android:icon="@drawable/ic_menu_display_bookmark"
+ android:label="@string/bookmark_list"
+ android:theme="@android:style/Theme.Holo" >
+ <intent-filter>
+ <action android:name="org.codeaurora.bookmark.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/proguard.flags b/proguard.flags
index 65104ec1e..7b6195bd2 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,6 +1,9 @@
# Disable the warnings of using dynamic method call in common library.
-dontnote com.android.gallery3d.common.*
+#Avoid the library class dependency error
+-dontwarn android.view.inputmethod.InputMethodManager
+
# Keep all classes extended from com.android.gallery3d.common.Entry
# Since we annotate on the fields and use reflection to create SQL
# according to those field.
diff --git a/res/drawable-hdpi/ic_menu_display_bookmark.png b/res/drawable-hdpi/ic_menu_display_bookmark.png
index a5118ea85..a5118ea85 100755..100644
--- a/res/drawable-hdpi/ic_menu_display_bookmark.png
+++ b/res/drawable-hdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_display_bookmark.png b/res/drawable-mdpi/ic_menu_display_bookmark.png
index a3acdd64b..a3acdd64b 100755..100644
--- a/res/drawable-mdpi/ic_menu_display_bookmark.png
+++ b/res/drawable-mdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_display_bookmark.png b/res/drawable-xhdpi/ic_menu_display_bookmark.png
index 4ad8414be..4ad8414be 100755..100644
--- a/res/drawable-xhdpi/ic_menu_display_bookmark.png
+++ b/res/drawable-xhdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/layout/bookmark.xml b/res/layout/bookmark.xml
index 9b765d4d9..ac4ac34a4 100755..100644
--- a/res/layout/bookmark.xml
+++ b/res/layout/bookmark.xml
@@ -1,22 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
+ android:layout_height="match_parent" >
+
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
+ android:layout_height="match_parent" />
+
<TextView
android:id="@android:id/empty"
- android:layout_width="match_parent"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
+ android:gravity="center"
android:paddingBottom="30dip"
- android:gravity ="center"
- android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/bookmark_empty"
- android:visibility="gone"
- />
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:visibility="gone" />
</FrameLayout>
diff --git a/res/layout/bookmark_edit_dialog.xml b/res/layout/bookmark_edit_dialog.xml
index fa1439cdb..8282d39af 100755..100644
--- a/res/layout/bookmark_edit_dialog.xml
+++ b/res/layout/bookmark_edit_dialog.xml
@@ -1,37 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
<LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="8dip"
- android:orientation="vertical">
- <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="8dip" >
+
+ <TextView
+ style="?android:attr/textAppearanceSmallInverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="?android:attr/textAppearanceSmallInverse"
android:text="@string/bookmark_title" />
- <EditText
+
+ <EditText
android:id="@+id/title"
- android:layout_width="match_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dip"
- android:singleLine="true"
android:inputType="text"
- android:scrollHorizontally="true" />
- <TextView
+ android:scrollHorizontally="true"
+ android:singleLine="true" />
+
+ <TextView
+ style="?android:attr/textAppearanceSmallInverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- style="?android:attr/textAppearanceSmallInverse"
android:text="@string/bookmark_location" />
- <EditText
+
+ <EditText
android:id="@+id/data"
- android:layout_width="match_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dip"
- android:singleLine="true"
android:inputType="textUri"
- android:scrollHorizontally="true" />
- </LinearLayout>
-</ScrollView> \ No newline at end of file
+ android:scrollHorizontally="true"
+ android:singleLine="true" />
+ </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/bookmark_item.xml b/res/layout/bookmark_item.xml
index a743e9e17..3fb2fab89 100755..100644
--- a/res/layout/bookmark_item.xml
+++ b/res/layout/bookmark_item.xml
@@ -3,19 +3,19 @@
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="6dip"
android:orientation="vertical"
- >
+ android:padding="6dip" >
+
<TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:textAppearance="?android:attr/textAppearanceMedium"
android:singleLine="true"
- />
- <TextView
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- />
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent" />
+
</LinearLayout>
diff --git a/res/layout/movie_view.xml b/res/layout/movie_view.xml
index 75b8dfd4f..a08679280 100644
--- a/res/layout/movie_view.xml
+++ b/res/layout/movie_view.xml
@@ -19,7 +19,7 @@
android:background="@android:color/black"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <VideoView android:id="@+id/surface_view"
+ <org.codeaurora.gallery3d.video.CodeauroraVideoView android:id="@+id/surface_view"
android:visibility="invisible"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/values-zh-rCN/codeaurora_strings.xml b/res/values-zh-rCN/codeaurora_strings.xml
index cdf3c7811..ad4aefc6a 100644
--- a/res/values-zh-rCN/codeaurora_strings.xml
+++ b/res/values-zh-rCN/codeaurora_strings.xml
@@ -1,7 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="loop">"循环"</string>
<string name="single">"单次"</string>
<string name="stereo">"立体声"</string>
<string name="single_track">"单声道"</string>
+ <string name="media_detail">"媒体详情"</string>
+ <string name="input_url">"输入 URL"</string>
+ <string name="streaming_settings">"流媒体设置"</string>
+
+ <string name="rtp">RTP</string>
+ <string name="rtcp">RTCP</string>
+ <string name="min_port">最小端口:</string>
+ <string name="max_port">最大端口:</string>
+ <string name="buffer_size">缓存大小</string>
+ <string name="apn">优先接入点</string>
+ <string name="rtp_min_port">RTP最小端口</string>
+ <string name="rtp_max_port">RTP最大端口</string>
+ <string name="rtcp_min_port">RTCP最小端口</string>
+ <string name="rtcp_max_port">RTCP最大端口</string>
+ <string name="set_rtp_min_port">设置RTP最小端口</string>
+ <string name="set_rtp_max_port">设置RTP最大端口</string>
+ <string name="set_rtcp_min_port">设置RTCP最小端口</string>
+ <string name="set_rtcp_max_port">设置RTCP最大端口</string>
+ <string name="set_buffer_size">设置缓冲大小</string>
+ <string name="set_apn">选择接入优先点</string>
+ <string name="setting">设置</string>
+
+ <string name="server_timeout_title">"服务器超时"</string>
+ <string name="server_timeout_message">"是否重新连接服务器以播放该视频?"</string>
+
+ <string name="bookmark_add">"添加书签"</string>
+ <string name="bookmark_display">"显示书签"</string>
+ <string name="bookmark_empty">"无书签"</string>
+ <string name="bookmark_exist">"已存在相同书签"</string>
+ <string name="bookmark_add_success">"添加书签成功"</string>
+ <string name="bookmark_list">"书签列表"</string>
+ <string name="bookmark_title">"标题"</string>
+ <string name="bookmark_location">"地址"</string>
+ <string name="delete_all">"删除所有"</string>
+ <string name="default_title">"默认标题"</string>
</resources>
diff --git a/res/values-zh-rTW/codeaurora_strings.xml b/res/values-zh-rTW/codeaurora_strings.xml
index 8af6493d4..d72a86ecb 100644
--- a/res/values-zh-rTW/codeaurora_strings.xml
+++ b/res/values-zh-rTW/codeaurora_strings.xml
@@ -1,7 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="loop">"循環"</string>
<string name="single">"單次"</string>
<string name="stereo">"立體聲"</string>
<string name="single_track">"單聲道"</string>
+ <string name="media_detail">"媒體詳情"</string>
+ <string name="input_url">"輸入 URL"</string>
+ <string name="streaming_settings">"串流設定"</string>
+
+ <string name="rtp">RTP</string>
+ <string name="rtcp">RTCP</string>
+ <string name="min_port">最小端口:</string>
+ <string name="max_port">最大端口:</string>
+ <string name="buffer_size">緩存大小</string>
+ <string name="apn">優先接入點</string>
+ <string name="rtp_min_port">RTP最小端口</string>
+ <string name="rtp_max_port">RTP最大端口</string>
+ <string name="rtcp_min_port">RTCP最小端口</string>
+ <string name="rtcp_max_port">RTCP最大端口</string>
+ <string name="set_rtp_min_port">設置RTP最小端口</string>
+ <string name="set_rtp_max_port">設置RTP最大端口</string>
+ <string name="set_rtcp_min_port">設置RTCP最小端口</string>
+ <string name="set_rtcp_max_port">設置RTCP最大端口</string>
+ <string name="set_buffer_size">設置緩衝大小</string>
+ <string name="set_apn">選擇接入優先點</string>
+ <string name="setting">設置</string>
+
+ <string name="server_timeout_title">"伺服器逾時"</string>
+ <string name="server_timeout_message">"是否重新連線伺服器並播放視訊?"</string>
+
+ <string name="bookmark_add">"添加書簽"</string>
+ <string name="bookmark_display">"顯示書簽"</string>
+ <string name="bookmark_empty">"無書簽"</string>
+ <string name="bookmark_exist">"已存在相同書簽"</string>
+ <string name="bookmark_add_success">"添加書簽成功"</string>
+ <string name="bookmark_list">"書簽列表"</string>
+ <string name="bookmark_title">"標題"</string>
+ <string name="bookmark_location">"位置"</string>
+ <string name="delete_all">"刪除所有"</string>
+ <string name="default_title">"默認標題"</string>
</resources>
diff --git a/res/values/bool.xml b/res/values/bool.xml
index 802388e94..8d2a9f9bc 100755
--- a/res/values/bool.xml
+++ b/res/values/bool.xml
@@ -17,4 +17,5 @@
<bool name="show_action_bar_title">false</bool>
<bool name="loop">false</bool>
<bool name="stereo">false</bool>
+ <bool name="streaming">false</bool>
</resources> \ No newline at end of file
diff --git a/res/values/codeaurora_strings.xml b/res/values/codeaurora_strings.xml
index 5d918b522..09de79cae 100644
--- a/res/values/codeaurora_strings.xml
+++ b/res/values/codeaurora_strings.xml
@@ -1,7 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="loop">"Loop"</string>
<string name="single">"Single"</string>
<string name="stereo">"Stereo"</string>
<string name="single_track">"Single track"</string>
+ <string name="media_detail">"Media details"</string>
+ <string name="input_url">"Input URL"</string>
+ <string name="streaming_settings">"Streaming Settings"</string>
+
+ <string name="rtp">RTP</string>
+ <string name="rtcp">RTCP</string>
+ <string name="min_port">min port:</string>
+ <string name="max_port">max port:</string>
+ <string name="buffer_size">Buffer Size</string>
+ <string name="apn">Prefered APN</string>
+ <string name="rtp_min_port">Min port</string>
+ <string name="rtp_max_port">Max port</string>
+ <string name="rtcp_min_port">Min port</string>
+ <string name="rtcp_max_port">Max port</string>
+ <string name="set_rtp_min_port">Set min port</string>
+ <string name="set_rtp_max_port">Set max port</string>
+ <string name="set_rtcp_min_port">Set min port</string>
+ <string name="set_rtcp_max_port">Set max port</string>
+ <string name="set_buffer_size">Set buffer size</string>
+ <string name="set_apn">Select prefered apn</string>
+ <string name="setting">Settings</string>
+
+ <string name="server_timeout_title">"Server Timeout"</string>
+ <string name="server_timeout_message">"Reconnect the server to play the video or not?"</string>
+
+ <string name="bookmark_add">"Add bookmark"</string>
+ <string name="bookmark_display">"Show bookmarks"</string>
+ <string name="bookmark_empty">"No bookmarks"</string>
+ <string name="bookmark_exist">"Same bookmark in history"</string>
+ <string name="bookmark_add_success">"Add bookmark success"</string>
+ <string name="bookmark_list">"Bookmarks"</string>
+ <string name="bookmark_title">"Title"</string>
+ <string name="bookmark_location">"Location"</string>
+ <string name="delete_all">"Delete all"</string>
+ <string name="default_title">"Default title"</string>
</resources>
diff --git a/res/xml/rtsp_settings_preferences.xml b/res/xml/rtsp_settings_preferences.xml
index b15080dfa..a5853808b 100755..100644
--- a/res/xml/rtsp_settings_preferences.xml
+++ b/res/xml/rtsp_settings_preferences.xml
@@ -1,89 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
-write by lhy
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-
- <PreferenceCategory
- android:title="@string/rtp">
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+ <PreferenceCategory android:title="@string/rtp" >
<EditTextPreference
- android:order="1"
+ android:dialogTitle="@string/set_rtp_min_port"
+ android:inputType="number"
android:key="rtp_min_port"
- android:title="@string/rtp_min_port"
+ android:maxLength="5"
+ android:order="1"
android:summary=""
- android:inputType="number"
- android:maxLength="5"
- android:dialogTitle="@string/set_rtp_min_port" />
-
+ android:title="@string/rtp_min_port" />
<EditTextPreference
- android:order="2"
+ android:dialogTitle="@string/rtp_max_port"
+ android:inputType="number"
android:key="rtp_max_port"
- android:title="@string/rtp_max_port"
+ android:maxLength="5"
+ android:order="2"
android:summary=""
- android:inputType="number"
- android:maxLength="5"
- android:dialogTitle="@string/rtp_max_port" />
+ android:title="@string/rtp_max_port" />
</PreferenceCategory>
-
- <PreferenceCategory
- android:title="@string/rtcp">
-
+ <PreferenceCategory android:title="@string/rtcp" >
<EditTextPreference
- android:order="3"
+ android:dialogTitle="@string/set_rtcp_min_port"
+ android:inputType="number"
android:key="rtcp_min_port"
- android:title="@string/rtcp_min_port"
+ android:maxLength="5"
+ android:order="3"
android:summary=""
- android:inputType="number"
- android:maxLength="5"
- android:dialogTitle="@string/set_rtcp_min_port" />
-
+ android:title="@string/rtcp_min_port" />
<EditTextPreference
- android:order="4"
+ android:dialogTitle="@string/rtcp_max_port"
+ android:inputType="number"
android:key="rtcp_max_port"
- android:title="@string/rtcp_max_port"
+ android:maxLength="5"
+ android:order="4"
android:summary=""
- android:inputType="number"
- android:maxLength="5"
- android:dialogTitle="@string/rtcp_max_port" />
+ android:title="@string/rtcp_max_port" />
</PreferenceCategory>
-
- <PreferenceCategory
- android:title="@string/buffer_size">
-
+ <PreferenceCategory android:title="@string/buffer_size" >
<EditTextPreference
- android:order="5"
+ android:dialogTitle="@string/set_buffer_size"
+ android:inputType="number"
android:key="buffer_size"
- android:title="@string/buffer_size"
+ android:maxLength="5"
+ android:order="5"
android:summary=""
- android:inputType="number"
- android:maxLength="5"
- android:dialogTitle="@string/set_buffer_size" />
-
+ android:title="@string/buffer_size" />
</PreferenceCategory>
-
- <PreferenceCategory android:title="@string/apn">
- <PreferenceScreen
- android:key="apn"
- android:title="@string/apn">
- <!--
- <intent
- android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.settings"
- android:targetClass="com.android.settings.ApnSettings" />
- -->
- </PreferenceScreen>
- <!--
- <ListPreference
- android:order="6"
+ <PreferenceCategory android:title="@string/apn" >
+ <PreferenceScreen
android:key="apn"
- android:title="@string/apn"
- android:entries="@array/apn_entries"
- android:entryValues="@array/apn_values"
- android:dialogTitle="@string/set_apn" />
- -->
+ android:title="@string/apn" >
+ </PreferenceScreen>
</PreferenceCategory>
-
</PreferenceScreen>
diff --git a/src/com/android/gallery3d/app/ControllerOverlay.java b/src/com/android/gallery3d/app/ControllerOverlay.java
index 078f59e28..36eda6257 100644
--- a/src/com/android/gallery3d/app/ControllerOverlay.java
+++ b/src/com/android/gallery3d/app/ControllerOverlay.java
@@ -27,6 +27,8 @@ public interface ControllerOverlay {
void onSeekEnd(int time, int trimStartTime, int trimEndTime);
void onShown();
void onHidden();
+ // get current video is from RTSP
+ boolean onIsRTSP();
void onReplay();
}
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
index 937d309bc..6577fe271 100644
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ b/src/com/android/gallery3d/app/MovieActivity.java
@@ -20,6 +20,7 @@ import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.KeyguardManager;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.content.AsyncQueryHandler;
@@ -41,6 +42,7 @@ import android.media.audiofx.BassBoost;
import android.media.audiofx.Virtualizer;
import android.media.MediaPlayer;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
@@ -66,6 +68,7 @@ import org.codeaurora.gallery3d.ext.IActivityHooker;
import org.codeaurora.gallery3d.ext.MovieItem;
import org.codeaurora.gallery3d.ext.IMovieItem;
import org.codeaurora.gallery3d.video.ExtensionHelper;
+import org.codeaurora.gallery3d.video.MovieTitleHelper;
/**
* This activity plays a video from a specified URI.
@@ -77,8 +80,13 @@ import org.codeaurora.gallery3d.video.ExtensionHelper;
public class MovieActivity extends Activity {
@SuppressWarnings("unused")
private static final String TAG = "MovieActivity";
+ private static final boolean LOG = true;
public static final String KEY_LOGO_BITMAP = "logo-bitmap";
public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
+ private static final String VIDEO_SDP_MIME_TYPE = "application/sdp";
+ private static final String VIDEO_SDP_TITLE = "rtsp://";
+ private static final String VIDEO_FILE_SCHEMA = "file";
+ private static final String VIDEO_MIME_TYPE = "video/*";
private MoviePlayer mPlayer;
private boolean mFinishOnCompletion;
@@ -105,6 +113,9 @@ public class MovieActivity extends Activity {
private IMovieItem mMovieItem;
private IActivityHooker mMovieHooker;
+ private KeyguardManager mKeyguardManager;
+ private boolean mResumed = false;
+ private boolean mControlResumed = false;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -214,27 +225,8 @@ public class MovieActivity extends Activity {
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
- int sessionId = mp.getAudioSessionId();
- if (mBassBoostSupported) {
- mBassBoostEffect = new BassBoost(0, sessionId);
- }
- if (mVirtualizerSupported) {
- mVirtualizerEffect = new Virtualizer(0, sessionId);
- }
- if (mIsHeadsetOn) {
- if (mPrefs.getBoolean(Key.global_enabled.toString(), false)) {
- if (mBassBoostSupported) {
- mBassBoostEffect.setStrength((short)
- mPrefs.getInt(Key.bb_strength.toString(), 0));
- mBassBoostEffect.setEnabled(true);
- }
- if (mVirtualizerSupported) {
- mVirtualizerEffect.setStrength((short)
- mPrefs.getInt(Key.virt_strength.toString(), 0));
- mVirtualizerEffect.setEnabled(true);
- }
- }
- }
+ mPlayer.onPrepared(mp);
+ initEffects(mp.getAudioSessionId());
}
});
}
@@ -413,10 +405,59 @@ public class MovieActivity extends Activity {
}
}
+ public void initEffects(int sessionId) {
+ // Singleton instance
+ if ((mBassBoostEffect == null) && mBassBoostSupported) {
+ mBassBoostEffect = new BassBoost(0, sessionId);
+ }
+
+ if ((mVirtualizerEffect == null) && mVirtualizerSupported) {
+ mVirtualizerEffect = new Virtualizer(0, sessionId);
+ }
+
+ if (mIsHeadsetOn) {
+ if (mPrefs.getBoolean(Key.global_enabled.toString(), false)) {
+ if (mBassBoostSupported) {
+ mBassBoostEffect.setStrength((short)
+ mPrefs.getInt(Key.bb_strength.toString(), 0));
+ mBassBoostEffect.setEnabled(true);
+ }
+ if (mVirtualizerSupported) {
+ mVirtualizerEffect.setStrength((short)
+ mPrefs.getInt(Key.virt_strength.toString(), 0));
+ mVirtualizerEffect.setEnabled(true);
+ }
+ } else {
+ if (mBassBoostSupported) {
+ mBassBoostEffect.setStrength((short)
+ mPrefs.getInt(Key.bb_strength.toString(), 0));
+ }
+ if (mVirtualizerSupported) {
+ mVirtualizerEffect.setStrength((short)
+ mPrefs.getInt(Key.virt_strength.toString(), 0));
+ }
+ }
+ }
+
+ }
+
+ public void releaseEffects() {
+ if (mBassBoostEffect != null) {
+ mBassBoostEffect.setEnabled(false);
+ mBassBoostEffect.release();
+ mBassBoostEffect = null;
+ }
+ if (mVirtualizerEffect != null) {
+ mVirtualizerEffect.setEnabled(false);
+ mVirtualizerEffect.release();
+ mVirtualizerEffect = null;
+ }
+ }
+
private Intent createShareIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("video/*");
- intent.putExtra(Intent.EXTRA_STREAM, mUri);
+ intent.putExtra(Intent.EXTRA_STREAM, mMovieItem.getUri());
return intent;
}
@@ -450,6 +491,7 @@ public class MovieActivity extends Activity {
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
super.onStart();
mMovieHooker.onStart();
+ registerScreenOff();
}
@Override
@@ -457,24 +499,36 @@ public class MovieActivity extends Activity {
((AudioManager) getSystemService(AUDIO_SERVICE))
.abandonAudioFocus(null);
super.onStop();
+ if (mControlResumed && mPlayer != null) {
+ mPlayer.onStop();
+ mControlResumed = false;
+ }
mMovieHooker.onStop();
+ unregisterScreenOff();
}
@Override
public void onPause() {
- mPlayer.onPause();
+ // Audio track will be deallocated for local video playback,
+ // thus recycle effect here.
+ releaseEffects();
try {
unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
// Do nothing
}
+ mResumed = false;
+ if (mControlResumed && mPlayer != null) {
+ mControlResumed = !mPlayer.onPause();
+ }
super.onPause();
mMovieHooker.onPause();
}
@Override
public void onResume() {
- mPlayer.onResume();
+ invalidateOptionsMenu();
+
if ((mVirtualizerSupported) || (mBassBoostSupported)) {
final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
@@ -482,6 +536,14 @@ public class MovieActivity extends Activity {
intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(mReceiver, intentFilter);
}
+
+ initEffects(mPlayer.getAudioSessionId());
+ mResumed = true;
+ if (!isKeyguardLocked() && !mControlResumed && mPlayer != null) {
+ mPlayer.onResume();
+ mControlResumed = true;
+ }
+ enhanceActionBar();
super.onResume();
mMovieHooker.onResume();
}
@@ -508,6 +570,20 @@ public class MovieActivity extends Activity {
}
@Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+ if (LOG) {
+ Log.v(TAG, "onWindowFocusChanged(" + hasFocus + ") isKeyguardLocked="
+ + isKeyguardLocked()
+ + ", mResumed=" + mResumed + ", mControlResumed=" + mControlResumed);
+ }
+ if (hasFocus && !isKeyguardLocked() && mResumed && !mControlResumed && mPlayer != null) {
+ mPlayer.onResume();
+ mControlResumed = true;
+ }
+ }
+
+ @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return mPlayer.onKeyDown(keyCode, event)
|| super.onKeyDown(keyCode, event);
@@ -528,7 +604,109 @@ public class MovieActivity extends Activity {
private void initMovieInfo(Intent intent) {
Uri original = intent.getData();
String mimeType = intent.getType();
- mMovieItem = new MovieItem(original, mimeType, null);
+ if (VIDEO_SDP_MIME_TYPE.equalsIgnoreCase(mimeType)
+ && VIDEO_FILE_SCHEMA.equalsIgnoreCase(original.getScheme())) {
+ mMovieItem = new MovieItem(VIDEO_SDP_TITLE + original, mimeType, null);
+ } else {
+ mMovieItem = new MovieItem(original, mimeType, null);
+ }
mMovieItem.setOriginalUri(original);
}
+
+ // we do not stop live streaming when other dialog overlays it.
+ private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (LOG) {
+ Log.v(TAG, "onReceive(" + intent.getAction() + ") mControlResumed="
+ + mControlResumed);
+ }
+ if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ // Only stop video.
+ if (mControlResumed) {
+ mPlayer.onStop();
+ mControlResumed = false;
+ }
+ }
+ }
+
+ };
+
+ private void registerScreenOff() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ registerReceiver(mScreenOffReceiver, filter);
+ }
+
+ private void unregisterScreenOff() {
+ unregisterReceiver(mScreenOffReceiver);
+ }
+
+ private boolean isKeyguardLocked() {
+ if (mKeyguardManager == null) {
+ mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ }
+ // isKeyguardSecure excludes the slide lock case.
+ boolean locked = (mKeyguardManager != null)
+ && mKeyguardManager.inKeyguardRestrictedInputMode();
+ if (LOG) {
+ Log.v(TAG, "isKeyguardLocked() locked=" + locked + ", mKeyguardManager="
+ + mKeyguardManager);
+ }
+ return locked;
+ }
+
+ private void enhanceActionBar() {
+ final IMovieItem movieItem = mMovieItem;// remember original item
+ final Uri uri = mMovieItem.getUri();
+ final String scheme = mMovieItem.getUri().getScheme();
+ final String authority = mMovieItem.getUri().getAuthority();
+ new AsyncTask<Void, Void, String>() {
+ @Override
+ protected String doInBackground(Void... params) {
+ String title = null;
+ if (ContentResolver.SCHEME_FILE.equals(scheme)) {
+ title = MovieTitleHelper.getTitleFromMediaData(MovieActivity.this, uri);
+ } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
+ title = MovieTitleHelper.getTitleFromDisplayName(MovieActivity.this, uri);
+ if (title == null) {
+ title = MovieTitleHelper.getTitleFromData(MovieActivity.this, uri);
+ }
+ }
+ if (title == null) {
+ title = MovieTitleHelper.getTitleFromUri(uri);
+ }
+ if (LOG) {
+ Log.v(TAG, "enhanceActionBar() task return " + title);
+ }
+ return title;
+ }
+
+ @Override
+ protected void onPostExecute(String result) {
+ if (LOG) {
+ Log.v(TAG, "onPostExecute(" + result + ") movieItem=" + movieItem
+ + ", mMovieItem=" + mMovieItem);
+ }
+ movieItem.setTitle(result);
+ if (movieItem == mMovieItem) {
+ setActionBarTitle(result);
+ }
+ };
+ }.execute();
+ if (LOG) {
+ Log.v(TAG, "enhanceActionBar() " + mMovieItem);
+ }
+ }
+
+ public void setActionBarTitle(String title) {
+ if (LOG) {
+ Log.v(TAG, "setActionBarTitle(" + title + ")");
+ }
+ ActionBar actionBar = getActionBar();
+ if (title != null) {
+ actionBar.setTitle(title);
+ }
+ }
}
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
index 09fd272ae..e632a826f 100644..100755
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -23,10 +23,14 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.Color;
import android.media.AudioManager;
import android.media.MediaPlayer;
+import android.media.Metadata;
import android.media.audiofx.AudioEffect;
import android.media.audiofx.Virtualizer;
import android.net.Uri;
@@ -39,6 +43,7 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.VideoView;
+import android.widget.Toast;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
@@ -47,18 +52,27 @@ import com.android.gallery3d.util.CacheManager;
import com.android.gallery3d.util.GalleryUtils;
import org.codeaurora.gallery3d.ext.IMoviePlayer;
import org.codeaurora.gallery3d.ext.IMovieItem;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+import org.codeaurora.gallery3d.video.BookmarkEnhance;
import org.codeaurora.gallery3d.video.ExtensionHelper;
+import org.codeaurora.gallery3d.video.CodeauroraVideoView;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
+import java.util.HashMap;
+import java.util.Map;
public class MoviePlayer implements
MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener,
- ControllerOverlay.Listener {
+ ControllerOverlay.Listener,
+ MediaPlayer.OnInfoListener,
+ MediaPlayer.OnPreparedListener,
+ MediaPlayer.OnSeekCompleteListener {
@SuppressWarnings("unused")
private static final String TAG = "MoviePlayer";
+ private static final boolean LOG = false;
private static final String KEY_VIDEO_POSITION = "video-position";
private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout";
@@ -72,18 +86,30 @@ public class MoviePlayer implements
private static final String CMDNAME = "command";
private static final String CMDPAUSE = "pause";
+ private static final String KEY_VIDEO_CAN_SEEK = "video_can_seek";
+ private static final String KEY_VIDEO_CAN_PAUSE = "video_can_pause";
+ private static final String KEY_VIDEO_LAST_DURATION = "video_last_duration";
+ private static final String KEY_VIDEO_LAST_DISCONNECT_TIME = "last_disconnect_time";
+ private static final String KEY_VIDEO_STREAMING_TYPE = "video_streaming_type";
+ private static final String KEY_VIDEO_STATE = "video_state";
+
private static final String VIRTUALIZE_EXTRA = "virtualize";
private static final long BLACK_TIMEOUT = 500;
+ private static final int DELAY_REMOVE_MS = 10000;
+ public static final int SERVER_TIMEOUT = 8801;
// If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing.
// Otherwise, we pause the player.
private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins
public static final int STREAMING_LOCAL = 0;
+ public static final int STREAMING_HTTP = 1;
+ public static final int STREAMING_RTSP = 2;
+ public static final int STREAMING_SDP = 3;
private int mStreamingType = STREAMING_LOCAL;
private Context mContext;
- private final VideoView mVideoView;
+ private final CodeauroraVideoView mVideoView;
private final View mRootView;
private final Bookmarker mBookmarker;
private final Uri mUri;
@@ -94,6 +120,10 @@ public class MoviePlayer implements
private long mResumeableTime = Long.MAX_VALUE;
private int mVideoPosition = 0;
private boolean mHasPaused = false;
+ private boolean mVideoHasPaused = false;
+ private boolean mCanResumed = false;
+ private boolean mFirstBePlayed = false;
+ private boolean mKeyguardLocked = false;
private int mLastSystemUiVis = 0;
// If the time bar is being dragged.
@@ -104,10 +134,18 @@ public class MoviePlayer implements
private Virtualizer mVirtualizer;
+ private MovieActivity mActivityContext;//for dialog and toast context
private MoviePlayerExtension mPlayerExt = new MoviePlayerExtension();
+ private RetryExtension mRetryExt = new RetryExtension();
+ private ServerTimeoutExtension mServerTimeoutExt = new ServerTimeoutExtension();
private boolean mCanReplay;
+ private boolean mVideoCanSeek = false;
+ private boolean mVideoCanPause = false;
+ private boolean mWaitMetaData;
+ private boolean mIsShowResumingDialog;
private TState mTState = TState.PLAYING;
private IMovieItem mMovieItem;
+ private int mVideoLastDuration;//for duration displayed in init state
private enum TState {
PLAYING,
@@ -141,11 +179,36 @@ public class MoviePlayer implements
}
};
+ private Runnable mDelayVideoRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (LOG) {
+ Log.v(TAG, "mDelayVideoRunnable.run()");
+ }
+ mVideoView.setVisibility(View.VISIBLE);
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ mKeyguardLocked = true;
+ } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+ if ((mCanResumed) && (!mVideoHasPaused)) {
+ playVideo();
+ }
+ mKeyguardLocked = false;
+ mCanResumed = false;
+ }
+ }
+ };
+
public MoviePlayer(View rootView, final MovieActivity movieActivity,
IMovieItem info, Bundle savedInstance, boolean canReplay) {
mContext = movieActivity.getApplicationContext();
mRootView = rootView;
- mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
+ mVideoView = (CodeauroraVideoView) rootView.findViewById(R.id.surface_view);
mBookmarker = new Bookmarker(movieActivity);
mController = new MovieControllerOverlay(mContext);
@@ -153,7 +216,7 @@ public class MoviePlayer implements
mController.setListener(this);
mController.setCanReplay(canReplay);
- init(info, canReplay);
+ init(movieActivity, info, canReplay);
mUri = mMovieItem.getUri();
mVideoView.setOnErrorListener(this);
@@ -209,6 +272,12 @@ public class MoviePlayer implements
mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver();
mAudioBecomingNoisyReceiver.register();
+ // Listen for broadcasts related to user-presence
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_USER_PRESENT);
+ mContext.registerReceiver(mReceiver, filter);
+
Intent i = new Intent(SERVICECMD);
i.putExtra(CMDNAME, CMDPAUSE);
movieActivity.sendBroadcast(i);
@@ -221,11 +290,13 @@ public class MoviePlayer implements
onRestoreInstanceState(savedInstance);
mHasPaused = true;
} else {
- final Integer bookmark = mBookmarker.getBookmark(mUri);
+ mTState = TState.PLAYING;
+ mFirstBePlayed = true;
+ final BookmarkerInfo bookmark = mBookmarker.getBookmark(mMovieItem.getUri());
if (bookmark != null) {
showResumeDialog(movieActivity, bookmark);
} else {
- startVideo();
+ doStartVideo(false, 0, 0);
}
}
}
@@ -273,12 +344,12 @@ public class MoviePlayer implements
onSaveInstanceStateMore(outState);
}
- private void showResumeDialog(Context context, final int bookmark) {
+ private void showResumeDialog(Context context, final BookmarkerInfo bookmark) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.resume_playing_title);
builder.setMessage(String.format(
context.getString(R.string.resume_playing_message),
- GalleryUtils.formatDuration(context, bookmark / 1000)));
+ GalleryUtils.formatDuration(context, bookmark.mBookmark / 1000)));
builder.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
@@ -289,42 +360,146 @@ public class MoviePlayer implements
R.string.resume_playing_resume, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- mVideoView.seekTo(bookmark);
- startVideo();
+ // here try to seek for bookmark
+ mVideoCanSeek = true;
+ doStartVideo(true, bookmark.mBookmark, bookmark.mDuration);
}
});
builder.setNegativeButton(
R.string.resume_playing_restart, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- startVideo();
+ doStartVideo(true, 0, bookmark.mDuration);
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.setOnShowListener(new OnShowListener() {
+ @Override
+ public void onShow(DialogInterface arg0) {
+ mIsShowResumingDialog = true;
}
});
- builder.show();
+ dialog.setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface arg0) {
+ mIsShowResumingDialog = false;
+ }
+ });
+ dialog.show();
}
- public void onPause() {
+ public boolean onPause() {
+ if (LOG) {
+ Log.v(TAG, "onPause() isLiveStreaming()=" + isLiveStreaming());
+ }
+ boolean pause = false;
+ if (isLiveStreaming()) {
+ pause = false;
+ } else {
+ doOnPause();
+ pause = true;
+ }
+ if (LOG) {
+ Log.v(TAG, "onPause() , return " + pause);
+ }
+ return pause;
+ }
+
+ // we should stop video anyway after this function called.
+ public void onStop() {
+ if (LOG) {
+ Log.v(TAG, "onStop() mHasPaused=" + mHasPaused);
+ }
+ if (!mHasPaused) {
+ doOnPause();
+ }
+ }
+
+ private void doOnPause() {
+ long start = System.currentTimeMillis();
+ addBackground();
mHasPaused = true;
mHandler.removeCallbacksAndMessages(null);
- mVideoPosition = mVideoView.getCurrentPosition();
- mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration());
- mVideoView.suspend();
+ int position = mVideoView.getCurrentPosition();
+ mVideoPosition = position >= 0 ? position : mVideoPosition;
+ Log.v(TAG, "mVideoPosition is " + mVideoPosition);
+ int duration = mVideoView.getDuration();
+ mVideoLastDuration = duration > 0 ? duration : mVideoLastDuration;
+ mBookmarker.setBookmark(mMovieItem.getUri(), mVideoPosition, mVideoLastDuration);
+ long end1 = System.currentTimeMillis();
+ // change suspend to release for sync paused and killed case
+ mVideoView.stopPlayback();
mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT;
+ mVideoView.setResumed(false);// avoid start after surface created
+ // Workaround for last-seek frame difference
+ mVideoView.setVisibility(View.INVISIBLE);
+ long end2 = System.currentTimeMillis();
+ // TODO comments by sunlei
+ mServerTimeoutExt.recordDisconnectTime();
+ if (LOG) {
+ Log.v(TAG, "doOnPause() save video info consume:" + (end1 - start));
+ Log.v(TAG, "doOnPause() suspend video consume:" + (end2 - end1));
+ Log.v(TAG, "doOnPause() mVideoPosition=" + mVideoPosition + ", mResumeableTime="
+ + mResumeableTime
+ + ", mVideoLastDuration=" + mVideoLastDuration + ", mIsShowResumingDialog="
+ + mIsShowResumingDialog);
+ }
}
public void onResume() {
+ mDragging = false;// clear drag info
if (mHasPaused) {
- mVideoView.seekTo(mVideoPosition);
- mVideoView.resume();
+ //M: same as launch case to delay transparent.
+ mVideoView.removeCallbacks(mDelayVideoRunnable);
+ mVideoView.postDelayed(mDelayVideoRunnable, BLACK_TIMEOUT);
- // If we have slept for too long, pause the play
- if (System.currentTimeMillis() > mResumeableTime) {
- pauseVideo();
+ if (mServerTimeoutExt.handleOnResume() || mIsShowResumingDialog) {
+ mHasPaused = false;
+ return;
}
+ switch (mTState) {
+ case RETRY_ERROR:
+ mRetryExt.showRetry();
+ break;
+ case STOPED:
+ mPlayerExt.stopVideo();
+ break;
+ case COMPELTED:
+ mController.showEnded();
+ if (mVideoCanSeek || mVideoView.canSeekForward()) {
+ mVideoView.seekTo(mVideoPosition);
+ }
+ mVideoView.setDuration(mVideoLastDuration);
+ break;
+ case PAUSED:
+ // if video was paused, so it should be started.
+ doStartVideo(true, mVideoPosition, mVideoLastDuration, false);
+ pauseVideo();
+ break;
+ default:
+ doStartVideo(true, mVideoPosition, mVideoLastDuration);
+ pauseVideoMoreThanThreeMinutes();
+ break;
+ }
+ mHasPaused = false;
}
mHandler.post(mProgressChecker);
}
+ private void pauseVideoMoreThanThreeMinutes() {
+ // If we have slept for too long, pause the play
+ // If is live streaming, do not pause it too
+ long now = System.currentTimeMillis();
+ if (now > mResumeableTime && !isLiveStreaming()) {
+ if (mVideoCanPause || mVideoView.canPause()) {
+ pauseVideo();
+ }
+ }
+ if (LOG) {
+ Log.v(TAG, "pauseVideoMoreThanThreeMinutes() now=" + now);
+ }
+ }
+
public void onDestroy() {
if (mVirtualizer != null) {
mVirtualizer.release();
@@ -332,6 +507,8 @@ public class MoviePlayer implements
}
mVideoView.stopPlayback();
mAudioBecomingNoisyReceiver.unregister();
+ mContext.unregisterReceiver(mReceiver);
+ mServerTimeoutExt.clearTimeoutDialog();
}
// This updates the time bar display (if necessary). It is called every
@@ -347,11 +524,13 @@ public class MoviePlayer implements
return position;
}
- private void startVideo() {
+ private void doStartVideo(final boolean enableFasten, final int position, final int duration,
+ boolean start) {
// For streams that we expect to be slow to start up, show a
// progress spinner until playback starts.
- String scheme = mUri.getScheme();
- if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) {
+ String scheme = mMovieItem.getUri().getScheme();
+ if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)
+ || "https".equalsIgnoreCase(scheme)) {
mController.showLoading();
mHandler.removeCallbacks(mPlayingChecker);
mHandler.postDelayed(mPlayingChecker, 250);
@@ -360,22 +539,53 @@ public class MoviePlayer implements
mController.hide();
}
- mVideoView.start();
+ if (onIsRTSP()) {
+ Map<String, String> header = new HashMap<String, String>(1);
+ header.put("CODEAURORA-ASYNC-RTSP-PAUSE-PLAY", "true");
+ mVideoView.setVideoURI(mMovieItem.getUri(), header, !mWaitMetaData);
+ } else {
+ mVideoView.setVideoURI(mMovieItem.getUri(), null, !mWaitMetaData);
+ }
+ if (start) {
+ mVideoView.start();
+ }
//we may start video from stopVideo,
//this case, we should reset canReplay flag according canReplay and loop
boolean loop = mPlayerExt.getLoop();
boolean canReplay = loop ? loop : mCanReplay;
mController.setCanReplay(canReplay);
+ if (position > 0 && (mVideoCanSeek || mVideoView.canSeekBackward()
+ || mVideoView.canSeekForward())) {
+ mVideoView.seekTo(position);
+ }
+ if (enableFasten) {
+ mVideoView.setDuration(duration);
+ }
setProgress();
}
+ private void doStartVideo(boolean enableFasten, int position, int duration) {
+ ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)).requestAudioFocus(
+ null, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ doStartVideo(enableFasten, position, duration, true);
+ }
+
private void playVideo() {
+ if (LOG) {
+ Log.v(TAG, "playVideo()");
+ }
+ mTState = TState.PLAYING;
mVideoView.start();
mController.showPlaying();
setProgress();
}
private void pauseVideo() {
+ if (LOG) {
+ Log.v(TAG, "pauseVideo()");
+ }
+ mTState = TState.PAUSED;
mVideoView.pause();
mController.showPaused();
}
@@ -383,6 +593,13 @@ public class MoviePlayer implements
// Below are notifications from VideoView
@Override
public boolean onError(MediaPlayer player, int arg1, int arg2) {
+ mMovieItem.setError();
+ if (mServerTimeoutExt.onError(player, arg1, arg2)) {
+ return true;
+ }
+ if (mRetryExt.onError(player, arg1, arg2)) {
+ return true;
+ }
mHandler.removeCallbacksAndMessages(null);
// VideoView will show an error dialog if we return false, so no need
// to show more message.
@@ -392,6 +609,14 @@ public class MoviePlayer implements
@Override
public void onCompletion(MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "onCompletion() mCanReplay=" + mCanReplay);
+ }
+ if (mMovieItem.getError()) {
+ Log.w(TAG, "error occured, exit the video player!");
+ mActivityContext.finish();
+ return;
+ }
if (mPlayerExt.getLoop()) {
onReplay();
} else { //original logic
@@ -434,6 +659,11 @@ public class MoviePlayer implements
}
@Override
+ public void onSeekComplete(MediaPlayer mp) {
+ setProgress();
+ }
+
+ @Override
public void onShown() {
mShowing = true;
setProgress();
@@ -447,8 +677,57 @@ public class MoviePlayer implements
}
@Override
+ public boolean onInfo(MediaPlayer mp, int what, int extra) {
+ if (LOG) {
+ Log.v(TAG, "onInfo() what:" + what + " extra:" + extra);
+ }
+ if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE && mServerTimeoutExt != null) {
+ Log.e(TAG, "setServerTimeout " + extra);
+ mServerTimeoutExt.setTimeout(extra * 1000);
+ }
+ if (mRetryExt.onInfo(mp, what, extra)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onPrepared(MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "onPrepared(" + mp + ")");
+ }
+ getVideoInfo(mp);
+ boolean canPause = mVideoView.canPause();
+ boolean canSeek = mVideoView.canSeekBackward() && mVideoView.canSeekForward();
+ if (!canPause && !mVideoView.isTargetPlaying()) {
+ mVideoView.start();
+ }
+ if (LOG) {
+ Log.v(TAG, "onPrepared() canPause=" + canPause + ", canSeek=" + canSeek);
+ }
+ }
+
+ public boolean onIsRTSP() {
+ if (MovieUtils.isRtspStreaming(mMovieItem.getUri(), mMovieItem
+ .getMimeType())) {
+ Log.v(TAG, "onIsRTSP() is RTSP");
+ return true;
+ }
+ Log.v(TAG, "onIsRTSP() is not RTSP");
+ return false;
+ }
+
+ @Override
public void onReplay() {
- startVideo();
+ if (LOG) {
+ Log.v(TAG, "onReplay()");
+ }
+ mTState = TState.PLAYING;
+ mFirstBePlayed = true;
+ if (mRetryExt.handleOnReplay()) {
+ return;
+ }
+ doStartVideo(false, 0, 0);
}
// Below are key events passed from MovieActivity.
@@ -462,14 +741,14 @@ public class MoviePlayer implements
switch (keyCode) {
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- if (mVideoView.isPlaying()) {
+ if (mVideoView.isPlaying() && mVideoView.canPause()) {
pauseVideo();
} else {
playVideo();
}
return true;
case KEYCODE_MEDIA_PAUSE:
- if (mVideoView.isPlaying()) {
+ if (mVideoView.isPlaying() && mVideoView.canPause()) {
pauseVideo();
}
return true;
@@ -500,9 +779,14 @@ public class MoviePlayer implements
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE;
}
- private void init(IMovieItem info, boolean canReplay) {
+ private void init(MovieActivity movieActivity, IMovieItem info, boolean canReplay) {
+ mActivityContext = movieActivity;
mCanReplay = canReplay;
mMovieItem = info;
+ judgeStreamingType(info.getUri(), info.getMimeType());
+
+ mVideoView.setOnInfoListener(this);
+ mVideoView.setOnPreparedListener(this);
}
// We want to pause when the headset is unplugged.
@@ -531,6 +815,13 @@ public class MoviePlayer implements
mVideoView.setOnPreparedListener(listener);
}
+ public boolean isFullBuffer() {
+ if (mStreamingType == STREAMING_RTSP || mStreamingType == STREAMING_SDP) {
+ return false;
+ }
+ return true;
+ }
+
public boolean isLocalFile() {
if (mStreamingType == STREAMING_LOCAL) {
return true;
@@ -538,6 +829,58 @@ public class MoviePlayer implements
return false;
}
+ private void getVideoInfo(MediaPlayer mp) {
+ if (!MovieUtils.isLocalFile(mMovieItem.getUri(), mMovieItem.getMimeType())) {
+ Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
+ MediaPlayer.BYPASS_METADATA_FILTER);
+ if (data != null) {
+ // TODO comments by sunlei
+ mServerTimeoutExt.setVideoInfo(data);
+ } else {
+ Log.w(TAG, "Metadata is null!");
+ }
+ }
+ }
+
+ private void judgeStreamingType(Uri uri, String mimeType) {
+ if (LOG) {
+ Log.v(TAG, "judgeStreamingType(" + uri + ")");
+ }
+ if (uri == null) {
+ return;
+ }
+ String scheme = uri.getScheme();
+ mWaitMetaData = true;
+ if (MovieUtils.isSdpStreaming(uri, mimeType)) {
+ mStreamingType = STREAMING_SDP;
+ mWaitMetaData = false;
+ } else if (MovieUtils.isRtspStreaming(uri, mimeType)) {
+ mStreamingType = STREAMING_RTSP;
+ mWaitMetaData = false;
+ } else if (MovieUtils.isHttpStreaming(uri, mimeType)) {
+ mStreamingType = STREAMING_HTTP;
+ mWaitMetaData = false;
+ } else {
+ mStreamingType = STREAMING_LOCAL;
+ mWaitMetaData = false;
+ }
+ if (LOG) {
+ Log.v(TAG, "mStreamingType=" + mStreamingType
+ + " mCanGetMetaData=" + mWaitMetaData);
+ }
+ }
+
+ public boolean isLiveStreaming() {
+ boolean isLive = false;
+ if (mStreamingType == STREAMING_SDP) {
+ isLive = true;
+ }
+ if (LOG) {
+ Log.v(TAG, "isLiveStreaming() return " + isLive);
+ }
+ return isLive;
+ }
+
public IMoviePlayer getMoviePlayerExt() {
return mPlayerExt;
}
@@ -546,13 +889,62 @@ public class MoviePlayer implements
return mVideoView;
}
- private void onSaveInstanceStateMore(Bundle outState) {
+ // Wait for any animation, ten seconds should be enough
+ private final Runnable mRemoveBackground = new Runnable() {
+ @Override
+ public void run() {
+ if (LOG) {
+ Log.v(TAG, "mRemoveBackground.run()");
+ }
+ mRootView.setBackground(null);
+ }
+ };
+
+ private void removeBackground() {
+ if (LOG) {
+ Log.v(TAG, "removeBackground()");
+ }
+ mHandler.removeCallbacks(mRemoveBackground);
+ mHandler.postDelayed(mRemoveBackground, DELAY_REMOVE_MS);
+ }
+ // add background for removing ghost image.
+ private void addBackground() {
+ if (LOG) {
+ Log.v(TAG, "addBackground()");
+ }
+ mHandler.removeCallbacks(mRemoveBackground);
+ mRootView.setBackgroundColor(Color.BLACK);
+ }
+
+ private void clearVideoInfo() {
+ mVideoPosition = 0;
+ mVideoLastDuration = 0;
+
+ if (mServerTimeoutExt != null) {
+ mServerTimeoutExt.clearServerInfo();
+ }
+ }
+
+ private void onSaveInstanceStateMore(Bundle outState) {
+ outState.putInt(KEY_VIDEO_LAST_DURATION, mVideoLastDuration);
+ outState.putBoolean(KEY_VIDEO_CAN_SEEK, mVideoView.canSeekForward());
+ outState.putBoolean(KEY_VIDEO_CAN_PAUSE, mVideoView.canPause());
+ outState.putInt(KEY_VIDEO_STREAMING_TYPE, mStreamingType);
+ outState.putString(KEY_VIDEO_STATE, String.valueOf(mTState));
+ mServerTimeoutExt.onSaveInstanceState(outState);
+ mRetryExt.onSaveInstanceState(outState);
mPlayerExt.onSaveInstanceState(outState);
}
private void onRestoreInstanceState(Bundle icicle) {
-
+ mVideoLastDuration = icicle.getInt(KEY_VIDEO_LAST_DURATION);
+ mVideoCanSeek = icicle.getBoolean(KEY_VIDEO_CAN_SEEK);
+ mVideoCanPause = icicle.getBoolean(KEY_VIDEO_CAN_PAUSE);
+ mStreamingType = icicle.getInt(KEY_VIDEO_STREAMING_TYPE);
+ mTState = TState.valueOf(icicle.getString(KEY_VIDEO_STATE));
+ mServerTimeoutExt.onRestoreInstanceState(icicle);
+ mRetryExt.onRestoreInstanceState(icicle);
mPlayerExt.onRestoreInstanceState(icicle);
}
@@ -560,7 +952,10 @@ public class MoviePlayer implements
private static final String KEY_VIDEO_IS_LOOP = "video_is_loop";
+ private BookmarkEnhance mBookmark;//for bookmark
private boolean mIsLoop;
+ private boolean mLastPlaying;
+ private boolean mLastCanPaused;
@Override
public boolean getLoop() {
@@ -587,7 +982,301 @@ public class MoviePlayer implements
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_VIDEO_IS_LOOP, mIsLoop);
}
+
+ @Override
+ public void stopVideo() {
+ if (LOG) {
+ Log.v(TAG, "stopVideo()");
+ }
+ mTState = TState.STOPED;
+ mVideoView.clearSeek();
+ mVideoView.clearDuration();
+ mVideoView.stopPlayback();
+ mVideoView.setResumed(false);
+ mVideoView.setVisibility(View.INVISIBLE);
+ mVideoView.setVisibility(View.VISIBLE);
+ clearVideoInfo();
+ mFirstBePlayed = false;
+ mController.setCanReplay(true);
+ mController.showEnded();
+ setProgress();
+ }
+
+ @Override
+ public boolean canStop() {
+ boolean stopped = false;
+ if (mController != null) {
+ //stopped = mOverlayExt.isPlayingEnd();
+ }
+ if (LOG) {
+ Log.v(TAG, "canStop() stopped=" + stopped);
+ }
+ return !stopped;
+ }
+
+ @Override
+ public void addBookmark() {
+ if (mBookmark == null) {
+ mBookmark = new BookmarkEnhance(mActivityContext);
+ }
+ String uri = String.valueOf(mMovieItem.getUri());
+ if (mBookmark.exists(uri)) {
+ Toast.makeText(mActivityContext, R.string.bookmark_exist, Toast.LENGTH_SHORT)
+ .show();
+ } else {
+ mBookmark.insert(mMovieItem.getTitle(), uri,
+ mMovieItem.getMimeType(), 0);
+ Toast.makeText(mActivityContext, R.string.bookmark_add_success, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
};
+
+ private class RetryExtension implements Restorable, MediaPlayer.OnErrorListener,
+ MediaPlayer.OnInfoListener {
+ private static final String KEY_VIDEO_RETRY_COUNT = "video_retry_count";
+ private int mRetryDuration;
+ private int mRetryPosition;
+ private int mRetryCount;
+
+ public void retry() {
+ doStartVideo(true, mRetryPosition, mRetryDuration);
+ if (LOG) {
+ Log.v(TAG, "retry() mRetryCount=" + mRetryCount + ", mRetryPosition="
+ + mRetryPosition);
+ }
+ }
+
+ public void clearRetry() {
+ if (LOG) {
+ Log.v(TAG, "clearRetry() mRetryCount=" + mRetryCount);
+ }
+ mRetryCount = 0;
+ }
+
+ public boolean reachRetryCount() {
+ if (LOG) {
+ Log.v(TAG, "reachRetryCount() mRetryCount=" + mRetryCount);
+ }
+ if (mRetryCount > 3) {
+ return true;
+ }
+ return false;
+ }
+
+ public int getRetryCount() {
+ if (LOG) {
+ Log.v(TAG, "getRetryCount() return " + mRetryCount);
+ }
+ return mRetryCount;
+ }
+
+ public boolean isRetrying() {
+ boolean retry = false;
+ if (mRetryCount > 0) {
+ retry = true;
+ }
+ if (LOG) {
+ Log.v(TAG, "isRetrying() mRetryCount=" + mRetryCount);
+ }
+ return retry;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle icicle) {
+ mRetryCount = icicle.getInt(KEY_VIDEO_RETRY_COUNT);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putInt(KEY_VIDEO_RETRY_COUNT, mRetryCount);
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ return false;
+ }
+
+ @Override
+ public boolean onInfo(MediaPlayer mp, int what, int extra) {
+ return false;
+ }
+
+ public boolean handleOnReplay() {
+ if (isRetrying()) { // from connecting error
+ clearRetry();
+ int errorPosition = mVideoView.getCurrentPosition();
+ int errorDuration = mVideoView.getDuration();
+ doStartVideo(errorPosition > 0, errorPosition, errorDuration);
+ if (LOG) {
+ Log.v(TAG, "onReplay() errorPosition=" + errorPosition + ", errorDuration="
+ + errorDuration);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void showRetry() {
+ if (mVideoCanSeek || mVideoView.canSeekForward()) {
+ mVideoView.seekTo(mVideoPosition);
+ }
+ mVideoView.setDuration(mVideoLastDuration);
+ mRetryPosition = mVideoPosition;
+ mRetryDuration = mVideoLastDuration;
+ }
+ }
+ private class ServerTimeoutExtension implements Restorable, MediaPlayer.OnErrorListener {
+ // for cmcc server timeout case
+ // please remember to clear this value when changed video.
+ private int mServerTimeout = -1;
+ private long mLastDisconnectTime;
+ private boolean mIsShowDialog = false;
+ private AlertDialog mServerTimeoutDialog;
+
+ // check whether disconnect from server timeout or not.
+ // if timeout, return false. otherwise, return true.
+ private boolean passDisconnectCheck() {
+ if (!isFullBuffer()) {
+ // record the time disconnect from server
+ long now = System.currentTimeMillis();
+ if (LOG) {
+ Log.v(TAG, "passDisconnectCheck() now=" + now + ", mLastDisconnectTime="
+ + mLastDisconnectTime
+ + ", mServerTimeout=" + mServerTimeout);
+ }
+ if (mServerTimeout > 0 && (now - mLastDisconnectTime) > mServerTimeout) {
+ // disconnect time more than server timeout, notify user
+ notifyServerTimeout();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void recordDisconnectTime() {
+ if (!isFullBuffer()) {
+ // record the time disconnect from server
+ mLastDisconnectTime = System.currentTimeMillis();
+ }
+ if (LOG) {
+ Log.v(TAG, "recordDisconnectTime() mLastDisconnectTime=" + mLastDisconnectTime);
+ }
+ }
+
+ private void clearServerInfo() {
+ mServerTimeout = -1;
+ }
+
+ private void notifyServerTimeout() {
+ if (mServerTimeoutDialog == null) {
+ // for updating last position and duration.
+ if (mVideoCanSeek || mVideoView.canSeekForward()) {
+ mVideoView.seekTo(mVideoPosition);
+ }
+ mVideoView.setDuration(mVideoLastDuration);
+ AlertDialog.Builder builder = new AlertDialog.Builder(mActivityContext);
+ mServerTimeoutDialog = builder.setTitle(R.string.server_timeout_title)
+ .setMessage(R.string.server_timeout_message)
+ .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (LOG) {
+ Log.v(TAG, "NegativeButton.onClick() mIsShowDialog="
+ + mIsShowDialog);
+ }
+ mController.showEnded();
+ onCompletion();
+ }
+
+ })
+ .setPositiveButton(R.string.resume_playing_resume, new OnClickListener() {
+
+ public void onClick(DialogInterface dialog, int which) {
+ if (LOG) {
+ Log.v(TAG, "PositiveButton.onClick() mIsShowDialog="
+ + mIsShowDialog);
+ }
+ doStartVideo(true, mVideoPosition, mVideoLastDuration);
+ }
+
+ })
+ .create();
+ mServerTimeoutDialog.setOnDismissListener(new OnDismissListener() {
+
+ public void onDismiss(DialogInterface dialog) {
+ if (LOG) {
+ Log.v(TAG, "mServerTimeoutDialog.onDismiss()");
+ }
+ mIsShowDialog = false;
+ }
+
+ });
+ mServerTimeoutDialog.setOnShowListener(new OnShowListener() {
+
+ public void onShow(DialogInterface dialog) {
+ if (LOG) {
+ Log.v(TAG, "mServerTimeoutDialog.onShow()");
+ }
+ mIsShowDialog = true;
+ }
+
+ });
+ }
+ mServerTimeoutDialog.show();
+ }
+
+ private void clearTimeoutDialog() {
+ if (mServerTimeoutDialog != null && mServerTimeoutDialog.isShowing()) {
+ mServerTimeoutDialog.dismiss();
+ }
+ mServerTimeoutDialog = null;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle icicle) {
+ mLastDisconnectTime = icicle.getLong(KEY_VIDEO_LAST_DISCONNECT_TIME);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putLong(KEY_VIDEO_LAST_DISCONNECT_TIME, mLastDisconnectTime);
+ }
+
+ public boolean handleOnResume() {
+ if (mIsShowDialog && !isLiveStreaming()) {
+ // wait for user's operation
+ return true;
+ }
+ if (!passDisconnectCheck()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setVideoInfo(Metadata data) {
+ if (data.has(SERVER_TIMEOUT)) {
+ mServerTimeout = data.getInt(SERVER_TIMEOUT);
+ if (LOG) {
+ Log.v(TAG, "get server timeout from metadata. mServerTimeout="
+ + mServerTimeout);
+ }
+ }
+ }
+
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ // if we are showing a dialog, cancel the error dialog
+ if (mIsShowDialog) {
+ return true;
+ }
+ return false;
+ }
+
+ public void setTimeout(int timeout) {
+ mServerTimeout = timeout;
+ }
+ }
}
class Bookmarker {
@@ -609,6 +1298,10 @@ class Bookmarker {
public void setBookmark(Uri uri, int bookmark, int duration) {
try {
+ // do not record or override bookmark if duration is not valid.
+ if (duration <= 0) {
+ return;
+ }
BlobCache cache = CacheManager.getCache(mContext,
BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION);
@@ -617,7 +1310,7 @@ class Bookmarker {
DataOutputStream dos = new DataOutputStream(bos);
dos.writeUTF(uri.toString());
dos.writeInt(bookmark);
- dos.writeInt(duration);
+ dos.writeInt(Math.abs(duration));
dos.flush();
cache.insert(uri.hashCode(), bos.toByteArray());
} catch (Throwable t) {
@@ -625,7 +1318,7 @@ class Bookmarker {
}
}
- public Integer getBookmark(Uri uri) {
+ public BookmarkerInfo getBookmark(Uri uri) {
try {
BlobCache cache = CacheManager.getCache(mContext,
BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
@@ -649,10 +1342,31 @@ class Bookmarker {
|| (bookmark > (duration - HALF_MINUTE))) {
return null;
}
- return Integer.valueOf(bookmark);
+ return new BookmarkerInfo(bookmark, duration);
} catch (Throwable t) {
Log.w(TAG, "getBookmark failed", t);
}
return null;
}
}
+
+class BookmarkerInfo {
+ public final int mBookmark;
+ public final int mDuration;
+
+ public BookmarkerInfo(int bookmark, int duration) {
+ this.mBookmark = bookmark;
+ this.mDuration = duration;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("BookmarkInfo(bookmark=")
+ .append(mBookmark)
+ .append(", duration=")
+ .append(mDuration)
+ .append(")")
+ .toString();
+ }
+}
diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java
index a1fd26c4a..c5d721274 100644
--- a/src/com/android/gallery3d/app/TrimVideo.java
+++ b/src/com/android/gallery3d/app/TrimVideo.java
@@ -342,6 +342,12 @@ public class TrimVideo extends Activity implements
}
@Override
+ public boolean onIsRTSP() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
public void onReplay() {
mVideoView.seekTo(mTrimStartTime);
playVideo();
diff --git a/src/com/qcom/gallery3d/video/DmReceiver.java b/src/com/qcom/gallery3d/video/DmReceiver.java
deleted file mode 100755
index b8d661e1f..000000000
--- a/src/com/qcom/gallery3d/video/DmReceiver.java
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-package com.qcom.gallery3d.video;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.net.Uri;
-import android.os.PowerManager;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-public class DmReceiver extends BroadcastReceiver {
- private static final String TAG = "DmReceiver";
- public static final String WRITE_SETTING_ACTION = "streaming.action.WRITE_SETTINGS";
- public static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
-
- private SharedPreferences mPref;
- static final int STREAMING_CONNPROFILE_IO_HANDLER_TYPE = 1;
- static final int STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE = 3;
- static final int STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE = 4;
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "z32 ### onReceive ###");
- if (mPref == null) {
- mPref = PreferenceManager.getDefaultSharedPreferences(context);
- }
- if (BOOT_COMPLETED.equals(intent.getAction()) )
- {
- Log.d(TAG, "z46 onReceive BOOT_COMPLETED ###");
- String rtpMaxport
- = mPref.getString(SettingsActivity.PREFERENCE_RTP_MAXPORT, "65535");
- String rtpMinport
- = mPref.getString(SettingsActivity.PREFERENCE_RTP_MINPORT, "8192");
- String apn
- = mPref.getString(SettingsActivity.PREFERENCE_APN, "CMWAP");
- Log.d(TAG, "z43 rtpMinport = " + rtpMinport + ";rtpMaxport = " + rtpMaxport);
-
- android.provider.Settings.System.putString(context.getContentResolver(), "streaming_max_udp_port", rtpMaxport);
- android.provider.Settings.System.putString(context.getContentResolver(), "streaming_min_udp_port", rtpMinport);
- android.provider.Settings.System.putString(context.getContentResolver(), "apn", apn);
- }
- else if (WRITE_SETTING_ACTION.equals(intent.getAction()))
- {
- Log.d(TAG, "z52 onReceive WRITE_SETTING_ACTION ###");
- int valueType = intent.getIntExtra("type", 0);
- String value = intent.getStringExtra("value");
- if (valueType == STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE)
- {
- mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MAXPORT,
- value).commit();
- android.provider.Settings.System.putString(context.getContentResolver(),
- "streaming_max_udp_port", value);
- }
- else if (valueType == STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE)
- {
- mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MINPORT,
- value).commit();
- android.provider.Settings.System.putString(context.getContentResolver(),
- "streaming_min_udp_port", value);
- }
- else if (valueType == STREAMING_CONNPROFILE_IO_HANDLER_TYPE)
- {
- mPref.edit().putString(SettingsActivity.PREFERENCE_APN,
- // "CMWAP").commit();
- value).commit();
- android.provider.Settings.System.putString(context.getContentResolver(),
- "apn", value);
- }
- }
- }
-}
-
diff --git a/src/com/qcom/gallery3d/video/QcomVideoView.java b/src/com/qcom/gallery3d/video/QcomVideoView.java
deleted file mode 100755
index ba5485544..000000000
--- a/src/com/qcom/gallery3d/video/QcomVideoView.java
+++ /dev/null
@@ -1,721 +0,0 @@
-package com.qcom.gallery3d.video;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteException;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnBufferingUpdateListener;
-import android.media.MediaPlayer.OnInfoListener;
-import android.media.MediaPlayer.OnVideoSizeChangedListener;
-import android.media.Metadata;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.SurfaceHolder;
-import android.widget.VideoView;
-
-import com.android.gallery3d.ui.Log;
-import com.qcom.gallery3d.ext.QcomLog;
-import com.qcom.gallery3d.video.ScreenModeManager.ScreenModeListener;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * QcomVideoView enhance the streaming videoplayer process and UI.
- * It only supports QcomMediaController.
- * If you set android's default MediaController,
- * some state will not be shown well.
- * Moved from the package android.widget
- */
-public class QcomVideoView extends VideoView implements ScreenModeListener {
- private static final String TAG = "QcomVideoView";
- private static final boolean LOG = true;
-
- //add info listener to get info whether can get meta data or not for rtsp.
- private MediaPlayer.OnInfoListener mOnInfoListener;
- private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener;
- private MediaPlayer.OnVideoSizeChangedListener mVideoSizeListener;
-
- //when the streaming type is live, metadata maybe not right when prepared.
- private boolean mHasGotMetaData = false;
- private boolean mHasGotPreparedCallBack = false;
-
- private final MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
-
- public boolean onInfo(final MediaPlayer mp, final int what, final int extra) {
- if (LOG) {
- QcomLog.v(TAG, "onInfo() what:" + what + " extra:" + extra);
- }
- if (mOnInfoListener != null && mOnInfoListener.onInfo(mp, what, extra)) {
- return true;
- } else {
- // TODO comments by sunlei
-// if (what == MediaPlayer.MEDIA_INFO_METADATA_CHECK_COMPLETE) {
-// mHasGotMetaData = true;
-// doPreparedIfReady(mMediaPlayer);
-// return true;
-// }
- }
- return false;
- }
-
- };
-
- private void doPreparedIfReady(final MediaPlayer mp) {
- if (LOG) {
- QcomLog.v(TAG, "doPreparedIfReady() mHasGotPreparedCallBack=" + mHasGotPreparedCallBack
- + ", mHasGotMetaData=" + mHasGotMetaData + ", mNeedWaitLayout=" + mNeedWaitLayout
- + ", mCurrentState=" + mCurrentState);
- }
- if (mHasGotPreparedCallBack && mHasGotMetaData && !mNeedWaitLayout) {
- doPrepared(mp);
- }
- }
-
- public QcomVideoView(final Context context) {
- super(context);
- initialize();
- }
-
- public QcomVideoView(final Context context, final AttributeSet attrs) {
- super(context, attrs);
- initialize();
- }
-
- public QcomVideoView(final Context context, final AttributeSet attrs, final int defStyle) {
- super(context, attrs, defStyle);
- initialize();
- }
-
- private void initialize() {
- mPreparedListener = new MediaPlayer.OnPreparedListener() {
- public void onPrepared(final MediaPlayer mp) {
- if (LOG) {
- QcomLog.v(TAG, "mPreparedListener.onPrepared(" + mp + ")");
- }
- //Here we can get meta data from mediaplayer.
- // Get the capabilities of the player for this stream
- final Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
- MediaPlayer.BYPASS_METADATA_FILTER);
- if (data != null) {
- mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
- || data.getBoolean(Metadata.PAUSE_AVAILABLE);
- mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
- || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
- mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
- || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
- } else {
- mCanPause = true;
- mCanSeekBack = true;
- mCanSeekForward = true;
- QcomLog.w(TAG, "Metadata is null!");
- }
- if (LOG) {
- QcomLog.v(TAG, "mPreparedListener.onPrepared() mCanPause=" + mCanPause);
- }
- mHasGotPreparedCallBack = true;
- doPreparedIfReady(mMediaPlayer);
- }
- };
-
- mErrorListener = new MediaPlayer.OnErrorListener() {
- public boolean onError(final MediaPlayer mp, final int frameworkErr, final int implErr) {
- Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
- if (mCurrentState == STATE_ERROR) {
- Log.w(TAG, "Duplicate error message. error message has been sent! " +
- "error=(" + frameworkErr + "," + implErr + ")");
- return true;
- }
- //record error position and duration
- //here disturb the original logic
- mSeekWhenPrepared = getCurrentPosition();
- if (LOG) {
- Log.v(TAG, "onError() mSeekWhenPrepared=" + mSeekWhenPrepared + ", mDuration=" + mDuration);
- }
- //for old version Streaming server, getduration is not valid.
- mDuration = Math.abs(mDuration);
- mCurrentState = STATE_ERROR;
- mTargetState = STATE_ERROR;
- if (mMediaController != null) {
- mMediaController.hide();
- }
-
- /* If an error handler has been supplied, use it and finish. */
- if (mOnErrorListener != null) {
- if (mOnErrorListener.onError(mMediaPlayer, frameworkErr, implErr)) {
- 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) {
- final Resources r = mContext.getResources();
- int messageId;
-
- // TODO comments by sunlei
-// if (frameworkErr == MediaPlayer.MEDIA_ERROR_BAD_FILE) {
-// messageId = com.mediatek.R.string.VideoView_error_text_bad_file;
-// } else if (frameworkErr == MediaPlayer.MEDIA_ERROR_CANNOT_CONNECT_TO_SERVER) {
-// messageId = com.mediatek.R.string.VideoView_error_text_cannot_connect_to_server;
-// } else if (frameworkErr == MediaPlayer.MEDIA_ERROR_TYPE_NOT_SUPPORTED) {
-// messageId = com.mediatek.R.string.VideoView_error_text_type_not_supported;
-// } else if (frameworkErr == MediaPlayer.MEDIA_ERROR_DRM_NOT_SUPPORTED) {
-// messageId = com.mediatek.R.string.VideoView_error_text_drm_not_supported;
-// } else if (frameworkErr == MediaPlayer.MEDIA_ERROR_INVALID_CONNECTION) {
-// messageId = com.mediatek.internal.R.string.VideoView_error_text_invalid_connection;
-// } else if (frameworkErr == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
-// messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
-// } else {
-// messageId = com.android.internal.R.string.VideoView_error_text_unknown;
-// }
-
- if (frameworkErr == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
- messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
- } else {
- messageId = com.android.internal.R.string.VideoView_error_text_unknown;
- }
-
- final String errorDialogTag = "ERROR_DIALOG_TAG";
- FragmentManager fragmentManager = ((Activity)mContext).getFragmentManager();
- DialogFragment oldFragment = (DialogFragment) fragmentManager
- .findFragmentByTag(errorDialogTag);
- if (null != oldFragment) {
- oldFragment.dismissAllowingStateLoss();
- }
- DialogFragment newFragment = ErrorDialogFragment.newInstance(messageId);
- newFragment.show(fragmentManager, errorDialogTag);
- fragmentManager.executePendingTransactions();
- }
- return true;
- }
- };
-
- mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
- public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
- mCurrentBufferPercentage = percent;
- if (mOnBufferingUpdateListener != null) {
- mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
- }
- if (LOG) {
- QcomLog.v(TAG, "onBufferingUpdate() Buffering percent: " + percent);
- }
- if (LOG) {
- QcomLog.v(TAG, "onBufferingUpdate() mTargetState=" + mTargetState);
- }
- if (LOG) {
- QcomLog.v(TAG, "onBufferingUpdate() mCurrentState=" + mCurrentState);
- }
- }
- };
-
- mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
- public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
- mVideoWidth = mp.getVideoWidth();
- mVideoHeight = mp.getVideoHeight();
- if (LOG) {
- QcomLog.v(TAG, "OnVideoSizeChagned(" + width + "," + height + ")");
- }
- if (LOG) {
- QcomLog.v(TAG, "OnVideoSizeChagned(" + mVideoWidth + "," + mVideoHeight + ")");
- }
- if (LOG) {
- QcomLog.v(TAG, "OnVideoSizeChagned() mCurrentState=" + mCurrentState);
- }
- if (mVideoWidth != 0 && mVideoHeight != 0) {
- getHolder().setFixedSize(mVideoWidth, mVideoHeight);
- if (mCurrentState == STATE_PREPARING) {
- mNeedWaitLayout = true;
- }
- }
- if (mVideoSizeListener != null) {
- mVideoSizeListener.onVideoSizeChanged(mp, width, height);
- }
- QcomVideoView.this.requestLayout();
- }
- };
-
- getHolder().removeCallback(mSHCallback);
- mSHCallback = new SurfaceHolder.Callback() {
- public void surfaceChanged(final SurfaceHolder holder, final int format, final int w, final int h) {
- if (LOG) {
- Log.v(TAG, "surfaceChanged(" + holder + ", " + format + ", " + w + ", " + h + ")");
- }
- if (LOG) {
- Log.v(TAG, "surfaceChanged() mMediaPlayer=" + mMediaPlayer + ", mTargetState=" + mTargetState
- + ", mVideoWidth=" + mVideoWidth + ", mVideoHeight=" + mVideoHeight);
- }
- mSurfaceWidth = w;
- mSurfaceHeight = h;
- final boolean isValidState = (mTargetState == STATE_PLAYING);
- final boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
- if (mMediaPlayer != null && isValidState && hasValidSize) {
- if (mSeekWhenPrepared != 0) {
- seekTo(mSeekWhenPrepared);
- }
- Log.v(TAG, "surfaceChanged() start()");
- start();
- }
- }
-
- public void surfaceCreated(final SurfaceHolder holder) {
- if (LOG) {
- Log.v(TAG, "surfaceCreated(" + holder + ")");
- }
- mSurfaceHolder = holder;
- openVideo();
- }
-
- public void surfaceDestroyed(final SurfaceHolder holder) {
- // after we return from this we can't use the surface any more
- if (LOG) {
- Log.v(TAG, "surfaceDestroyed(" + holder + ")");
- }
- mSurfaceHolder = null;
- if (mMediaController != null) {
- mMediaController.hide();
- }
- release(true);
- }
- };
- getHolder().addCallback(mSHCallback);
- }
-
- @Override
- protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
- //Log.i("@@@@", "onMeasure");
- int width = 0;
- int height = 0;
- int screenMode = ScreenModeManager.SCREENMODE_BIGSCREEN;
- if (mScreenManager != null) {
- screenMode = mScreenManager.getScreenMode();
- }
- switch (screenMode) {
- case ScreenModeManager.SCREENMODE_BIGSCREEN:
- width = getDefaultSize(mVideoWidth, widthMeasureSpec);
- height = getDefaultSize(mVideoHeight, heightMeasureSpec);
- if (mVideoWidth > 0 && mVideoHeight > 0) {
- if (mVideoWidth * height > width * mVideoHeight) {
- //Log.i("@@@", "image too tall, correcting");
- height = width * mVideoHeight / mVideoWidth;
- } else if (mVideoWidth * height < width * mVideoHeight) {
- //Log.i("@@@", "image too wide, correcting");
- width = height * mVideoWidth / mVideoHeight;
- } /*else {
- //Log.i("@@@", "aspect ratio is correct: " +
- //width+"/"+height+"="+
- //mVideoWidth+"/"+mVideoHeight);
- }*/
- }
- break;
- case ScreenModeManager.SCREENMODE_FULLSCREEN:
- width = getDefaultSize(mVideoWidth, widthMeasureSpec);
- height = getDefaultSize(mVideoHeight, heightMeasureSpec);
- break;
- case ScreenModeManager.SCREENMODE_CROPSCREEN:
- width = getDefaultSize(mVideoWidth, widthMeasureSpec);
- height = getDefaultSize(mVideoHeight, heightMeasureSpec);
- if (mVideoWidth > 0 && mVideoHeight > 0) {
- if (mVideoWidth * height > width * mVideoHeight) {
- //extend width to be cropped
- width = height * mVideoWidth / mVideoHeight;
- } else if (mVideoWidth * height < width * mVideoHeight) {
- //extend height to be cropped
- height = width * mVideoHeight / mVideoWidth;
- }
- }
- break;
- default:
- QcomLog.w(TAG, "wrong screen mode : " + screenMode);
- break;
- }
- if (LOG) {
- QcomLog.v(TAG, "onMeasure() set size: " + width + 'x' + height);
- QcomLog.v(TAG, "onMeasure() video size: " + mVideoWidth + 'x' + mVideoHeight);
- QcomLog.v(TAG, "onMeasure() mNeedWaitLayout=" + mNeedWaitLayout);
- }
- setMeasuredDimension(width, height);
- if (mNeedWaitLayout) { //when OnMeasure ok, start video.
- mNeedWaitLayout = false;
- mHandler.sendEmptyMessage(MSG_LAYOUT_READY);
- }
- }
-
-// @Override
-// public boolean onTouchEvent(MotionEvent ev) {
-// if (LOG) Log.v(TAG, "onTouchEvent(" + ev + ")");
-// if (mMediaController != null) {
-// toggleMediaControlsVisiblity();
-// }
-// return false;
-// }
-
- @Override
- public boolean onKeyDown(final int keyCode, final KeyEvent event) {
- final boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
- keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
- keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
- keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
- keyCode != KeyEvent.KEYCODE_MENU &&
- keyCode != KeyEvent.KEYCODE_CALL &&
- keyCode != KeyEvent.KEYCODE_ENDCALL &&
- keyCode != KeyEvent.KEYCODE_CAMERA;
- if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
- if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
- keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)) {
- if (mMediaPlayer.isPlaying()) {
- pause();
- mMediaController.show();
- } else {
- start();
- mMediaController.hide();
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
- if (!mMediaPlayer.isPlaying()) {
- start();
- mMediaController.hide();
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
- || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
- if (mMediaPlayer.isPlaying()) {
- pause();
- mMediaController.show();
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD ||
- keyCode == KeyEvent.KEYCODE_MEDIA_NEXT ||
- keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
- keyCode == KeyEvent.KEYCODE_MEDIA_REWIND ||
- keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
- keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
- //consume media action, so if video view if front,
- //other media player will not play any sounds.
- return true;
- } else {
- toggleMediaControlsVisiblity();
- }
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void setVideoURI(final Uri uri, final Map<String, String> headers) {
- mDuration = -1;
- setResumed(true);
- super.setVideoURI(uri, headers);
- }
-
- public void setVideoURI(final Uri uri, final Map<String, String> headers, final boolean hasGotMetaData) {
- if (LOG) {
- QcomLog.v(TAG, "setVideoURI(" + uri + ", " + headers + ")");
- }
- //clear the flags
- mHasGotMetaData = hasGotMetaData;
- setVideoURI(uri, headers);
- }
-
- private void clearVideoInfo() {
- if (LOG) {
- Log.v(TAG, "clearVideoInfo()");
- }
- mHasGotPreparedCallBack = false;
- mNeedWaitLayout = false;
- }
-
- @Override
- protected void openVideo() {
- if (LOG) {
- Log.v(TAG, "openVideo() mUri=" + mUri + ", mSurfaceHolder=" + mSurfaceHolder
- + ", mSeekWhenPrepared=" + mSeekWhenPrepared + ", mMediaPlayer=" + mMediaPlayer
- + ", mOnResumed=" + mOnResumed);
- }
- clearVideoInfo();
- if (!mOnResumed || mUri == null || mSurfaceHolder == null) {
- // not ready for playback just yet, will try again later
- return;
- }
-
- // Tell the music playback service to pause
- // TODO: these constants need to be published somewhere in the framework.
- final 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);
- if ("".equalsIgnoreCase(String.valueOf(mUri))) {
- Log.w(TAG, "Unable to open content: " + mUri);
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
- return;
- }
- try {
- mMediaPlayer = new MediaPlayer();
- //end update status.
- mMediaPlayer.setOnPreparedListener(mPreparedListener);
- mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
- //mDuration = -1;
- mMediaPlayer.setOnCompletionListener(mCompletionListener);
- mMediaPlayer.setOnErrorListener(mErrorListener);
- mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
- mMediaPlayer.setOnInfoListener(mInfoListener);
- mCurrentBufferPercentage = 0;
- Log.w(TAG, "openVideo setDataSource()");
- mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
- mMediaPlayer.setDisplay(mSurfaceHolder);
- mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- mMediaPlayer.setScreenOnWhilePlaying(true);
- Log.w(TAG, "openVideo prepareAsync()");
- mMediaPlayer.prepareAsync();
- // we don't set the target state here either, but preserve the
- // target state that was there before.
- mCurrentState = STATE_PREPARING;
- //attachMediaController();
- } catch (final IOException ex) {
- Log.w(TAG, "Unable to open content: " + mUri, ex);
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
- return;
- } catch (final IllegalArgumentException ex) {
- Log.w(TAG, "Unable to open content: " + mUri, ex);
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
- return;
- } catch (final SQLiteException ex) {
- Log.w(TAG, "Unable to open content: " + mUri, ex);
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
- return;
- }
- if (LOG) {
- Log.v(TAG, "openVideo() mUri=" + mUri + ", mSurfaceHolder=" + mSurfaceHolder
- + ", mSeekWhenPrepared=" + mSeekWhenPrepared + ", mMediaPlayer=" + mMediaPlayer);
- }
- }
-
- private void doPrepared(final MediaPlayer mp) {
- if (LOG) {
- QcomLog.v(TAG, "doPrepared(" + mp + ") start");
- }
- mCurrentState = STATE_PREPARED;
- if (mOnPreparedListener != null) {
- mOnPreparedListener.onPrepared(mMediaPlayer);
- }
- mVideoWidth = mp.getVideoWidth();
- mVideoHeight = mp.getVideoHeight();
-
- final int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be changed after seekTo() call
- if (seekToPosition != 0) {
- seekTo(seekToPosition);
- }
- if (mVideoWidth != 0 && mVideoHeight != 0) {
- getHolder().setFixedSize(mVideoWidth, mVideoHeight);
- }
-
- if (mTargetState == STATE_PLAYING) {
- start();
- }
- if (LOG) {
- QcomLog.v(TAG, "doPrepared() end video size: " + mVideoWidth + "," + mVideoHeight
- + ", mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
- }
- }
-
- private boolean mOnResumed;
- /**
- * surfaceCreate will invoke openVideo after the activity stoped.
- * Here set this flag to avoid openVideo after the activity stoped.
- * @param resume
- */
- public void setResumed(final boolean resume) {
- if (LOG) {
- QcomLog.v(TAG, "setResumed(" + resume + ") mUri=" + mUri + ", mOnResumed=" + mOnResumed);
- }
- mOnResumed = resume;
- }
-
- @Override
- public void resume() {
- if (LOG) {
- QcomLog.v(TAG, "resume() mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
- }
- setResumed(true);
- openVideo();
- }
-
- @Override
- public void suspend() {
- if (LOG) {
- QcomLog.v(TAG, "suspend() mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
- }
- super.suspend();
- }
-
- public void setOnInfoListener(final OnInfoListener l) {
- mOnInfoListener = l;
- if (LOG) {
- QcomLog.v(TAG, "setInfoListener(" + l + ")");
- }
- }
-
- public void setOnBufferingUpdateListener(final OnBufferingUpdateListener l) {
- mOnBufferingUpdateListener = l;
- if (LOG) {
- QcomLog.v(TAG, "setOnBufferingUpdateListener(" + l + ")");
- }
- }
-
- public void setOnVideoSizeChangedListener(final OnVideoSizeChangedListener l) {
- mVideoSizeListener = l;
- if (LOG) {
- Log.i(TAG, "setOnVideoSizeChangedListener(" + l + ")");
- }
- }
-
- @Override
- public int getCurrentPosition() {
- int position = 0;
- if (mSeekWhenPrepared > 0) {
- //if connecting error before seek,
- //we should remember this position for retry
- position = mSeekWhenPrepared;
- ///M: if player not started, getCurrentPosition() will lead to NE.
- } else if (isInPlaybackState() && mCurrentState != STATE_PREPARED) {
- position = mMediaPlayer.getCurrentPosition();
- }
- if (LOG) {
- QcomLog.v(TAG, "getCurrentPosition() return " + position
- + ", mSeekWhenPrepared=" + mSeekWhenPrepared);
- }
- return position;
- }
-
- //clear the seek position any way.
- //this will effect the case: stop video before it's seek completed.
- public void clearSeek() {
- if (LOG) {
- QcomLog.v(TAG, "clearSeek() mSeekWhenPrepared=" + mSeekWhenPrepared);
- }
- mSeekWhenPrepared = 0;
- }
-
- public boolean isTargetPlaying() {
- if (LOG) {
- Log.v(TAG, "isTargetPlaying() mTargetState=" + mTargetState);
- }
- return mTargetState == STATE_PLAYING;
- }
-
- public void dump() {
- if (LOG) {
- Log.v(TAG, "dump() mUri=" + mUri
- + ", mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState
- + ", mSeekWhenPrepared=" + mSeekWhenPrepared
- + ", mVideoWidth=" + mVideoWidth + ", mVideoHeight=" + mVideoHeight
- + ", mMediaPlayer=" + mMediaPlayer + ", mSurfaceHolder=" + mSurfaceHolder);
- }
- }
-
- @Override
- public void seekTo(final int msec) {
- if (LOG) {
- Log.v(TAG, "seekTo(" + msec + ") isInPlaybackState()=" + isInPlaybackState());
- }
- super.seekTo(msec);
- }
-
- @Override
- protected void release(final boolean cleartargetstate) {
- if (LOG) {
- Log.v(TAG, "release(" + cleartargetstate + ") mMediaPlayer=" + mMediaPlayer);
- }
- super.release(cleartargetstate);
- }
-
- //for duration displayed
- public void setDuration(final int duration) {
- if (LOG) {
- Log.v(TAG, "setDuration(" + duration + ")");
- }
- mDuration = (duration > 0 ? -duration : duration);
- }
-
- @Override
- public int getDuration() {
- final boolean inPlaybackState = isInPlaybackState();
- if (LOG) {
- Log.v(TAG, "getDuration() mDuration=" + mDuration + ", inPlaybackState=" + inPlaybackState);
- }
- if (inPlaybackState) {
- if (mDuration > 0) {
- return mDuration;
- }
- mDuration = mMediaPlayer.getDuration();
- return mDuration;
- }
- //mDuration = -1;
- return mDuration;
- }
-
- public void clearDuration() {
- if (LOG) {
- QcomLog.v(TAG, "clearDuration() mDuration=" + mDuration);
- }
- mDuration = -1;
- }
-
- //for video size changed before started issue
- private static final int MSG_LAYOUT_READY = 1;
- private boolean mNeedWaitLayout = false;
- private final Handler mHandler = new Handler() {
- public void handleMessage(final Message msg) {
- if (LOG) {
- QcomLog.v(TAG, "handleMessage() to do prepare. msg=" + msg);
- }
- switch(msg.what) {
- case MSG_LAYOUT_READY:
- if (mMediaPlayer == null || mUri == null) {
- QcomLog.w(TAG, "Cannot prepare play! mMediaPlayer=" + mMediaPlayer + ", mUri=" + mUri);
- } else {
- doPreparedIfReady(mMediaPlayer);
- }
- break;
- default:
- QcomLog.w(TAG, "Unhandled message " + msg);
- break;
- }
- }
- };
-
- private ScreenModeManager mScreenManager;
- public void setScreenModeManager(final ScreenModeManager manager) {
- mScreenManager = manager;
- if (mScreenManager != null) {
- mScreenManager.addListener(this);
- }
- if (LOG) {
- QcomLog.v(TAG, "setScreenModeManager(" + manager + ")");
- }
- }
-
- @Override
- public void onScreenModeChanged(final int newMode) {
- this.requestLayout();
- }
-}
diff --git a/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java b/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java
index 9248ebdf4..3013cbcb1 100644
--- a/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java
+++ b/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java
@@ -1,6 +1,12 @@
package org.codeaurora.gallery3d.ext;
public interface IMoviePlayer {
+
+ /**
+ * add new bookmark Uri.
+ */
+ void addBookmark();
+
/**
* Loop current video.
*
@@ -14,4 +20,16 @@ public interface IMoviePlayer {
* @return
*/
boolean getLoop();
+
+ /**
+ * Can stop current video or not.
+ *
+ * @return
+ */
+ boolean canStop();
+
+ /**
+ * Stop current video.
+ */
+ void stopVideo();
}
diff --git a/src/com/qcom/gallery3d/video/BookmarkActivity.java b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
index 8e792815c..ed653f63a 100755..100644
--- a/src/com/qcom/gallery3d/video/BookmarkActivity.java
+++ b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
@@ -1,4 +1,4 @@
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.app.Activity;
import android.app.AlertDialog;
@@ -11,6 +11,7 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
+import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
@@ -29,63 +30,63 @@ import android.widget.TextView;
import com.android.gallery3d.R;
import com.android.gallery3d.app.MovieActivity;
-import com.qcom.gallery3d.ext.QcomLog;
public class BookmarkActivity extends Activity implements OnItemClickListener {
private static final String TAG = "BookmarkActivity";
private static final boolean LOG = true;
-
+
private BookmarkEnhance mBookmark;
private BookmarkAdapter mAdapter;
private Cursor mCursor;
private ListView mListView;
private TextView mEmptyView;
-
+
private static final int MENU_DELETE_ALL = 1;
private static final int MENU_DELETE_ONE = 2;
private static final int MENU_EDIT = 3;
-
+
public static final String KEY_LOGO_BITMAP = "logo-bitmap";
-
+
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bookmark);
-
+
Bitmap logo = getIntent().getParcelableExtra(KEY_LOGO_BITMAP);
if (logo != null) {
getActionBar().setLogo(new BitmapDrawable(getResources(), logo));
}
-
+
mListView = (ListView) findViewById(android.R.id.list);
mEmptyView = (TextView) findViewById(android.R.id.empty);
-
+
mBookmark = new BookmarkEnhance(this);
mCursor = mBookmark.query();
- mAdapter = new BookmarkAdapter(this, R.layout.bookmark_item, null, new String[]{}, new int[]{});
+ mAdapter = new BookmarkAdapter(this, R.layout.bookmark_item, null, new String[] {},
+ new int[] {});
mListView.setEmptyView(mEmptyView);
mListView.setAdapter(mAdapter);
mAdapter.changeCursor(mCursor);
-
+
mListView.setOnItemClickListener(this);
registerForContextMenu(mListView);
}
-
+
@Override
protected void onStart() {
super.onStart();
}
-
+
@Override
protected void onResume() {
super.onResume();
}
-
+
@Override
protected void onPause() {
super.onPause();
}
-
+
@Override
protected void onDestroy() {
if (mAdapter != null) {
@@ -93,34 +94,34 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
}
super.onDestroy();
}
-
+
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, MENU_DELETE_ALL, 0, R.string.delete_all)
- .setIcon(android.R.drawable.ic_menu_delete);
+ .setIcon(android.R.drawable.ic_menu_delete);
return true;
}
-
+
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
- switch(item.getItemId()) {
- case MENU_DELETE_ALL:
- mBookmark.deleteAll();
- return true;
- default:
- break;
+ switch (item.getItemId()) {
+ case MENU_DELETE_ALL:
+ mBookmark.deleteAll();
+ return true;
+ default:
+ break;
}
return super.onOptionsItemSelected(item);
}
-
+
private class BookmarkAdapter extends SimpleCursorAdapter {
public BookmarkAdapter(final Context context, final int layout, final Cursor c,
final String[] from, final int[] to) {
super(context, layout, c, from, to);
}
-
+
@Override
public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
final View view = super.newView(context, cursor, parent);
@@ -130,7 +131,7 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
view.setTag(holder);
return view;
}
-
+
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
final ViewHolder holder = (ViewHolder) view.getTag();
@@ -141,14 +142,14 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
holder.mTitleView.setText(holder.mTitle);
holder.mDataView.setText(holder.mData);
}
-
+
@Override
public void changeCursor(final Cursor c) {
super.changeCursor(c);
}
-
+
}
-
+
private class ViewHolder {
long mId;
String mTitle;
@@ -159,7 +160,8 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
}
@Override
- public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
+ public void onItemClick(final AdapterView<?> parent, final View view, final int position,
+ final long id) {
final Object o = view.getTag();
if (o instanceof ViewHolder) {
final ViewHolder holder = (ViewHolder) o;
@@ -174,7 +176,7 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
startActivity(intent);
}
if (LOG) {
- QcomLog.v(TAG, "onItemClick(" + position + ", " + id + ")");
+ Log.v(TAG, "onItemClick(" + position + ", " + id + ")");
}
}
@@ -185,41 +187,41 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
menu.add(0, MENU_DELETE_ONE, 0, R.string.delete);
menu.add(0, MENU_EDIT, 0, R.string.edit);
}
-
+
@Override
public boolean onContextItemSelected(final MenuItem item) {
final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
- case MENU_DELETE_ONE:
- mBookmark.delete(info.id);
- return true;
- case MENU_EDIT:
- final Object obj = info.targetView.getTag();
- if (obj instanceof ViewHolder) {
- showEditDialog((ViewHolder)obj);
- } else {
- QcomLog.w(TAG, "wrong context item info " + info);
- }
- return true;
- default:
- return super.onContextItemSelected(item);
+ case MENU_DELETE_ONE:
+ mBookmark.delete(info.id);
+ return true;
+ case MENU_EDIT:
+ final Object obj = info.targetView.getTag();
+ if (obj instanceof ViewHolder) {
+ showEditDialog((ViewHolder) obj);
+ } else {
+ Log.w(TAG, "wrong context item info " + info);
+ }
+ return true;
+ default:
+ return super.onContextItemSelected(item);
}
}
-
+
private void showEditDialog(final ViewHolder holder) {
if (LOG) {
- QcomLog.v(TAG, "showEditDialog(" + holder + ")");
+ Log.v(TAG, "showEditDialog(" + holder + ")");
}
if (holder == null) {
return;
}
final LayoutInflater inflater = LayoutInflater.from(this);
final View v = inflater.inflate(R.layout.bookmark_edit_dialog, null);
- final EditText titleView = (EditText)v.findViewById(R.id.title);
- final EditText dataView = (EditText)v.findViewById(R.id.data);
+ final EditText titleView = (EditText) v.findViewById(R.id.title);
+ final EditText dataView = (EditText) v.findViewById(R.id.data);
titleView.setText(holder.mTitle);
dataView.setText(holder.mData);
-
+
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.edit);
builder.setView(v);
@@ -231,7 +233,7 @@ public class BookmarkActivity extends Activity implements OnItemClickListener {
mBookmark.update(holder.mId, titleView.getText().toString(),
dataView.getText().toString(), 0);
}
-
+
});
builder.setNegativeButton(android.R.string.cancel, null);
final AlertDialog dialog = builder.create();
diff --git a/src/com/qcom/gallery3d/video/BookmarkEnhance.java b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
index 033b055b5..fc3ed9b0f 100755..100644
--- a/src/com/qcom/gallery3d/video/BookmarkEnhance.java
+++ b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
@@ -1,4 +1,4 @@
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -6,16 +6,16 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.util.Log;
import com.android.gallery3d.R;
-import com.qcom.gallery3d.ext.QcomLog;
public class BookmarkEnhance {
private static final String TAG = "BookmarkEnhance";
private static final boolean LOG = true;
-
+
private static final Uri BOOKMARK_URI = Uri.parse("content://media/internal/bookmark");
-
+
public static final String COLUMN_ID = "_id";
public static final String COLUMN_DATA = "_data";
public static final String COLUMN_TITLE = "_display_name";
@@ -23,11 +23,11 @@ public class BookmarkEnhance {
public static final String COLUMN_MEDIA_TYPE = "mime_type";
private static final String COLUMN_POSITION = "position";
private static final String COLUMN_MIME_TYPE = "media_type";
-
+
private static final String NULL_HOCK = COLUMN_POSITION;
public static final String ORDER_COLUMN = COLUMN_ADD_DATE + " ASC ";
private static final String VIDEO_STREAMING_MEDIA_TYPE = "streaming";
-
+
public static final int INDEX_ID = 0;
public static final int INDEX_DATA = 1;
public static final int INDEX_TITLE = 2;
@@ -35,24 +35,25 @@ public class BookmarkEnhance {
public static final int INDEX_MIME_TYPE = 4;
private static final int INDEX_POSITION = 5;
private static final int INDEX_MEDIA_TYPE = 6;
-
- public static final String[] PROJECTION = new String[]{
- COLUMN_ID,
- COLUMN_DATA,
- COLUMN_TITLE,
- COLUMN_ADD_DATE,
- COLUMN_MIME_TYPE,
+
+ public static final String[] PROJECTION = new String[] {
+ COLUMN_ID,
+ COLUMN_DATA,
+ COLUMN_TITLE,
+ COLUMN_ADD_DATE,
+ COLUMN_MIME_TYPE,
};
-
+
private final Context mContext;
private final ContentResolver mCr;
-
+
public BookmarkEnhance(final Context context) {
mContext = context;
mCr = context.getContentResolver();
}
-
- public Uri insert(final String title, final String uri, final String mimeType,final long position) {
+
+ public Uri insert(final String title, final String uri, final String mimeType,
+ final long position) {
final ContentValues values = new ContentValues();
final String mytitle = (title == null ? mContext.getString(R.string.default_title) : title);
values.put(COLUMN_TITLE, mytitle);
@@ -63,33 +64,38 @@ public class BookmarkEnhance {
values.put(COLUMN_MIME_TYPE, mimeType);
final Uri insertUri = mCr.insert(BOOKMARK_URI, values);
if (LOG) {
- QcomLog.v(TAG, "insert(" + title + "," + uri + ", " + position + ") return " + insertUri);
+ Log.v(TAG, "insert(" + title + "," + uri + ", " + position + ") return "
+ + insertUri);
}
return insertUri;
}
-
+
public int delete(final long id) {
final Uri uri = ContentUris.withAppendedId(BOOKMARK_URI, id);
final int count = mCr.delete(uri, null, null);
if (LOG) {
- QcomLog.v(TAG, "delete(" + id + ") return " + count);
+ Log.v(TAG, "delete(" + id + ") return " + count);
}
return count;
}
-
+
public int deleteAll() {
- final int count = mCr.delete(BOOKMARK_URI, COLUMN_MEDIA_TYPE + "=? ", new String[]{VIDEO_STREAMING_MEDIA_TYPE});
+ final int count = mCr.delete(BOOKMARK_URI, COLUMN_MEDIA_TYPE + "=? ", new String[] {
+ VIDEO_STREAMING_MEDIA_TYPE
+ });
if (LOG) {
- QcomLog.v(TAG, "deleteAll() return " + count);
+ Log.v(TAG, "deleteAll() return " + count);
}
return count;
}
-
+
public boolean exists(final String uri) {
final Cursor cursor = mCr.query(BOOKMARK_URI,
PROJECTION,
COLUMN_DATA + "=? and " + COLUMN_MEDIA_TYPE + "=? ",
- new String[]{uri, VIDEO_STREAMING_MEDIA_TYPE},
+ new String[] {
+ uri, VIDEO_STREAMING_MEDIA_TYPE
+ },
null
);
boolean exist = false;
@@ -98,11 +104,11 @@ public class BookmarkEnhance {
cursor.close();
}
if (LOG) {
- QcomLog.v(TAG, "exists(" + uri + ") return " + exist);
+ Log.v(TAG, "exists(" + uri + ") return " + exist);
}
return exist;
}
-
+
public Cursor query() {
final Cursor cursor = mCr.query(BOOKMARK_URI,
PROJECTION,
@@ -111,11 +117,11 @@ public class BookmarkEnhance {
ORDER_COLUMN
);
if (LOG) {
- QcomLog.v(TAG, "query() return cursor=" + (cursor == null ? -1 : cursor.getCount()));
+ Log.v(TAG, "query() return cursor=" + (cursor == null ? -1 : cursor.getCount()));
}
return cursor;
}
-
+
public int update(final long id, final String title, final String uri, final int position) {
final ContentValues values = new ContentValues();
values.put(COLUMN_TITLE, title);
@@ -124,7 +130,7 @@ public class BookmarkEnhance {
final Uri updateUri = ContentUris.withAppendedId(BOOKMARK_URI, id);
final int count = mCr.update(updateUri, values, null, null);
if (LOG) {
- QcomLog.v(TAG, "update(" + id + ", " + title + ", " + uri + ", " + position + ")" +
+ Log.v(TAG, "update(" + id + ", " + title + ", " + uri + ", " + position + ")" +
" return " + count);
}
return count;
diff --git a/src/com/qcom/gallery3d/video/BookmarkHooker.java b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
index fc8bcd885..9d7697d7a 100755..100644
--- a/src/com/qcom/gallery3d/video/BookmarkHooker.java
+++ b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
@@ -1,31 +1,34 @@
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import com.android.gallery3d.R;
-import com.qcom.gallery3d.ext.MovieUtils;
+import org.codeaurora.gallery3d.ext.MovieUtils;
public class BookmarkHooker extends MovieHooker {
private static final String TAG = "BookmarkHooker";
private static final boolean LOG = true;
-
- private static final String ACTION_BOOKMARK = "com.qcom.bookmark.VIEW";
+
+ private static final String ACTION_BOOKMARK = "org.codeaurora.bookmark.VIEW";
private static final int MENU_BOOKMARK_ADD = 1;
private static final int MENU_BOOKMARK_DISPLAY = 2;
private MenuItem mMenuBookmarks;
private MenuItem mMenuBookmarkAdd;
-
+
public static final String KEY_LOGO_BITMAP = "logo-bitmap";
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
super.onCreateOptionsMenu(menu);
- mMenuBookmarkAdd = menu.add(0, getMenuActivityId(MENU_BOOKMARK_ADD), 0, R.string.bookmark_add);
- mMenuBookmarks = menu.add(0, getMenuActivityId(MENU_BOOKMARK_DISPLAY), 0, R.string.bookmark_display);
+ mMenuBookmarkAdd = menu.add(0, getMenuActivityId(MENU_BOOKMARK_ADD), 0,
+ R.string.bookmark_add);
+ mMenuBookmarks = menu.add(0, getMenuActivityId(MENU_BOOKMARK_DISPLAY), 0,
+ R.string.bookmark_display);
return true;
}
+
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
@@ -46,27 +49,28 @@ public class BookmarkHooker extends MovieHooker {
}
return true;
}
+
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
super.onOptionsItemSelected(item);
- switch(getMenuOriginalId(item.getItemId())) {
- case MENU_BOOKMARK_ADD:
- getPlayer().addBookmark();
- return true;
- case MENU_BOOKMARK_DISPLAY:
- gotoBookmark();
- return true;
- default:
- return false;
+ switch (getMenuOriginalId(item.getItemId())) {
+ case MENU_BOOKMARK_ADD:
+ getPlayer().addBookmark();
+ return true;
+ case MENU_BOOKMARK_DISPLAY:
+ gotoBookmark();
+ return true;
+ default:
+ return false;
}
}
-
+
private void gotoBookmark() {
final Intent intent = new Intent(ACTION_BOOKMARK);
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
intent.putExtra(KEY_LOGO_BITMAP, getIntent().getParcelableExtra(KEY_LOGO_BITMAP));
getContext().startActivity(intent);
}
-} \ No newline at end of file
+}
diff --git a/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
new file mode 100755
index 000000000..39bf532e6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
@@ -0,0 +1,1032 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.Metadata;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnInfoListener;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.MediaController;
+import android.widget.MediaController.MediaPlayerControl;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * 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.
+ */
+public class CodeauroraVideoView extends SurfaceView implements MediaPlayerControl {
+ private static final boolean LOG = true;
+ private String TAG = "CodeauroraVideoView";
+ // settable by the client
+ private Uri mUri;
+ private Map<String, String> mHeaders;
+
+ // 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;
+ private static final int STATE_SUSPENDED = 6;
+ private static final int MSG_LAYOUT_READY = 1;
+
+ // 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 mAudioSession;
+ private int mVideoWidth;
+ private int mVideoHeight;
+ private int mSurfaceWidth;
+ private int mSurfaceHeight;
+ private int mDuration;
+ private MediaController mMediaController;
+ private OnCompletionListener mOnCompletionListener;
+ private MediaPlayer.OnPreparedListener mOnPreparedListener;
+ private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener;
+ private MediaPlayer.OnVideoSizeChangedListener mVideoSizeListener;
+ private MediaPlayer.OnPreparedListener mPreparedListener;
+ private int mCurrentBufferPercentage;
+ private OnErrorListener mOnErrorListener;
+ private OnInfoListener mOnInfoListener;
+ private int mSeekWhenPrepared; // recording the seek position while preparing
+ private boolean mCanPause;
+ private boolean mCanSeekBack;
+ private boolean mCanSeekForward;
+ private boolean mHasGotPreparedCallBack = false;
+ private boolean mNeedWaitLayout = false;
+ private boolean mHasGotMetaData = false;
+ private boolean mOnResumed;
+
+ private final Handler mHandler = new Handler() {
+ public void handleMessage(final Message msg) {
+ if (LOG) {
+ Log.v(TAG, "handleMessage() to do prepare. msg=" + msg);
+ }
+ switch (msg.what) {
+ case MSG_LAYOUT_READY:
+ if (mMediaPlayer == null || mUri == null) {
+ Log.w(TAG, "Cannot prepare play! mMediaPlayer=" + mMediaPlayer
+ + ", mUri=" + mUri);
+ } else {
+ doPreparedIfReady(mMediaPlayer);
+ }
+ break;
+ default:
+ Log.w(TAG, "Unhandled message " + msg);
+ break;
+ }
+ }
+ };
+
+ public CodeauroraVideoView(Context context) {
+ super(context);
+ initVideoView();
+ initialize();
+ }
+
+ public CodeauroraVideoView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ initVideoView();
+ initialize();
+ }
+
+ public CodeauroraVideoView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initVideoView();
+ initialize();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
+ int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
+ if (mVideoWidth > 0 && mVideoHeight > 0) {
+
+ int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+ int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+ int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+ int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+
+ if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
+ // the size is fixed
+ width = widthSpecSize;
+ height = heightSpecSize;
+
+ // for compatibility, we adjust size based on aspect ratio
+ if ( mVideoWidth * height < width * mVideoHeight ) {
+ width = height * mVideoWidth / mVideoHeight;
+ } else if ( mVideoWidth * height > width * mVideoHeight ) {
+ height = width * mVideoHeight / mVideoWidth;
+ }
+ } else if (widthSpecMode == MeasureSpec.EXACTLY) {
+ // only the width is fixed, adjust the height to match aspect ratio if possible
+ width = widthSpecSize;
+ height = width * mVideoHeight / mVideoWidth;
+ if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+ // couldn't match aspect ratio within the constraints
+ height = heightSpecSize;
+ }
+ } else if (heightSpecMode == MeasureSpec.EXACTLY) {
+ // only the height is fixed, adjust the width to match aspect ratio if possible
+ height = heightSpecSize;
+ width = height * mVideoWidth / mVideoHeight;
+ if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+ // couldn't match aspect ratio within the constraints
+ width = widthSpecSize;
+ }
+ } else {
+ // neither the width nor the height are fixed, try to use actual video size
+ width = mVideoWidth;
+ height = mVideoHeight;
+ if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+ height = heightSpecSize;
+ width = height * mVideoWidth / mVideoHeight;
+ }
+ if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+ width = widthSpecSize;
+ height = width * mVideoHeight / mVideoWidth;
+ }
+ }
+ } else {
+ // no size yet, just adopt the given spec sizes
+ }
+ setMeasuredDimension(width, height);
+ if (mNeedWaitLayout) { // when OnMeasure ok, start video.
+ mNeedWaitLayout = false;
+ mHandler.sendEmptyMessage(MSG_LAYOUT_READY);
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setClassName(CodeauroraVideoView.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setClassName(CodeauroraVideoView.class.getName());
+ }
+
+ public int resolveAdjustedSize(int desiredSize, int measureSpec) {
+ return getDefaultSize(desiredSize, measureSpec);
+ }
+
+ private void initVideoView() {
+ mVideoWidth = 0;
+ mVideoHeight = 0;
+ getHolder().addCallback(mSHCallback);
+ getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ mCurrentState = STATE_IDLE;
+ mTargetState = STATE_IDLE;
+ }
+
+ private void initialize() {
+ mPreparedListener = new MediaPlayer.OnPreparedListener() {
+ public void onPrepared(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "mPreparedListener.onPrepared(" + mp + ")");
+ }
+ //Here we can get meta data from mediaplayer.
+ // Get the capabilities of the player for this stream
+ final Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
+ MediaPlayer.BYPASS_METADATA_FILTER);
+ if (data != null) {
+ mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
+ || data.getBoolean(Metadata.PAUSE_AVAILABLE);
+ mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
+ mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
+ } else {
+ mCanPause = true;
+ mCanSeekBack = true;
+ mCanSeekForward = true;
+ Log.w(TAG, "Metadata is null!");
+ }
+ if (LOG) {
+ Log.v(TAG, "mPreparedListener.onPrepared() mCanPause=" + mCanPause);
+ }
+ mHasGotPreparedCallBack = true;
+ doPreparedIfReady(mMediaPlayer);
+ }
+ };
+
+ mErrorListener = new MediaPlayer.OnErrorListener() {
+ public boolean onError(final MediaPlayer mp, final int frameworkErr, final int implErr) {
+ Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
+ if (mCurrentState == STATE_ERROR) {
+ Log.w(TAG, "Duplicate error message. error message has been sent! " +
+ "error=(" + frameworkErr + "," + implErr + ")");
+ return true;
+ }
+ //record error position and duration
+ //here disturb the original logic
+ mSeekWhenPrepared = getCurrentPosition();
+ if (LOG) {
+ Log.v(TAG, "onError() mSeekWhenPrepared=" + mSeekWhenPrepared + ", mDuration=" + mDuration);
+ }
+ //for old version Streaming server, getduration is not valid.
+ mDuration = Math.abs(mDuration);
+ mCurrentState = STATE_ERROR;
+ mTargetState = STATE_ERROR;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+
+ /* If an error handler has been supplied, use it and finish. */
+ if (mOnErrorListener != null) {
+ if (mOnErrorListener.onError(mMediaPlayer, frameworkErr, implErr)) {
+ 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) {
+ final Resources r = mContext.getResources();
+ int messageId;
+
+ if (frameworkErr == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+ messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback;
+ } else {
+ messageId = com.android.internal.R.string.VideoView_error_text_unknown;
+ }
+ new AlertDialog.Builder(mContext)
+ .setMessage(messageId)
+ .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
+ 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 (mOnCompletionListener != null) {
+ mOnCompletionListener.onCompletion(mMediaPlayer);
+ }
+ }
+ })
+ .setCancelable(false)
+ .show();
+ }
+ return true;
+ }
+ };
+
+ mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
+ public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
+ mCurrentBufferPercentage = percent;
+ if (mOnBufferingUpdateListener != null) {
+ mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
+ }
+ if (LOG) {
+ Log.v(TAG, "onBufferingUpdate() Buffering percent: " + percent);
+ Log.v(TAG, "onBufferingUpdate() mTargetState=" + mTargetState);
+ Log.v(TAG, "onBufferingUpdate() mCurrentState=" + mCurrentState);
+ }
+ }
+ };
+
+ mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
+ public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
+ mVideoWidth = mp.getVideoWidth();
+ mVideoHeight = mp.getVideoHeight();
+ if (LOG) {
+ Log.v(TAG, "OnVideoSizeChagned(" + width + "," + height + ")");
+ Log.v(TAG, "OnVideoSizeChagned(" + mVideoWidth + "," + mVideoHeight + ")");
+ Log.v(TAG, "OnVideoSizeChagned() mCurrentState=" + mCurrentState);
+ }
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+ if (mCurrentState == STATE_PREPARING) {
+ mNeedWaitLayout = true;
+ }
+ }
+ if (mVideoSizeListener != null) {
+ mVideoSizeListener.onVideoSizeChanged(mp, width, height);
+ }
+ CodeauroraVideoView.this.requestLayout();
+ }
+ };
+
+ getHolder().removeCallback(mSHCallback);
+ mSHCallback = new SurfaceHolder.Callback() {
+ public void surfaceChanged(final SurfaceHolder holder, final int format, final int w, final int h) {
+ if (LOG) {
+ Log.v(TAG, "surfaceChanged(" + holder + ", " + format + ", " + w + ", " + h + ")");
+ Log.v(TAG, "surfaceChanged() mMediaPlayer=" + mMediaPlayer + ", mTargetState=" + mTargetState
+ + ", mVideoWidth=" + mVideoWidth + ", mVideoHeight=" + mVideoHeight);
+ }
+ mSurfaceWidth = w;
+ mSurfaceHeight = h;
+ final boolean isValidState = (mTargetState == STATE_PLAYING);
+ final boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
+ if (mMediaPlayer != null && isValidState && hasValidSize) {
+ if (mSeekWhenPrepared != 0) {
+ seekTo(mSeekWhenPrepared);
+ }
+ Log.v(TAG, "surfaceChanged() start()");
+ start();
+ }
+ }
+
+ public void surfaceCreated(final SurfaceHolder holder) {
+ if (LOG) {
+ Log.v(TAG, "surfaceCreated(" + holder + ")");
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ }
+
+ public void surfaceDestroyed(final SurfaceHolder holder) {
+ // after we return from this we can't use the surface any more
+ if (LOG) {
+ Log.v(TAG, "surfaceDestroyed(" + holder + ")");
+ }
+ mSurfaceHolder = null;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+ release(true);
+ }
+ };
+ getHolder().addCallback(mSHCallback);
+ }
+
+ public void setVideoPath(String path) {
+ setVideoURI(Uri.parse(path));
+ }
+
+ public void setVideoURI(Uri uri) {
+ setVideoURI(uri, null);
+ }
+
+ /**
+ * @hide
+ */
+ public void setVideoURI(Uri uri, Map<String, String> headers) {
+ Log.d(TAG,"setVideoURI uri = " + uri);
+ mDuration = -1;
+ setResumed(true);
+ mUri = uri;
+ mHeaders = headers;
+ 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() {
+ clearVideoInfo();
+ if (mUri == null || mSurfaceHolder == null) {
+ // not ready for playback just yet, will try again later
+ 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);
+ if ("".equalsIgnoreCase(String.valueOf(mUri))) {
+ Log.w(TAG, "Unable to open content: " + mUri);
+ mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ return;
+ }
+ try {
+ mMediaPlayer = new MediaPlayer();
+ if (mAudioSession != 0) {
+ mMediaPlayer.setAudioSessionId(mAudioSession);
+ } else {
+ mAudioSession = mMediaPlayer.getAudioSessionId();
+ }
+ mMediaPlayer.setOnPreparedListener(mPreparedListener);
+ mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
+ mMediaPlayer.setOnCompletionListener(mCompletionListener);
+ mMediaPlayer.setOnErrorListener(mErrorListener);
+ mMediaPlayer.setOnInfoListener(mOnInfoListener);
+ mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
+ mCurrentBufferPercentage = 0;
+ mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mMediaPlayer.setScreenOnWhilePlaying(true);
+ mMediaPlayer.prepareAsync();
+ // we don't set the target state here either, but preserve the
+ // target state that was there before.
+ mCurrentState = STATE_PREPARING;
+ attachMediaController();
+ } 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;
+ }
+ }
+
+ 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());
+ }
+ }
+
+ private boolean isHTTPStreaming(Uri mUri) {
+ if (mUri != null){
+ String scheme = mUri.toString();
+ if (scheme.startsWith("http://") || scheme.startsWith("https://")) {
+ if (scheme.endsWith(".m3u8") || scheme.endsWith(".m3u")
+ || scheme.contains("m3u8") || scheme.endsWith(".mpd")) {
+ // HLS or DASH streaming source
+ return false;
+ }
+ // HTTP streaming
+ return true;
+ }
+ }
+ return false;
+ }
+
+ 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);
+ requestLayout();
+ }
+ }
+ };
+
+ private MediaPlayer.OnCompletionListener mCompletionListener =
+ new MediaPlayer.OnCompletionListener() {
+ public void onCompletion(MediaPlayer mp) {
+ mCurrentState = STATE_PLAYBACK_COMPLETED;
+ mTargetState = STATE_PLAYBACK_COMPLETED;
+ if (mMediaController != null) {
+ mMediaController.hide();
+ }
+ if (mOnCompletionListener != null) {
+ mOnCompletionListener.onCompletion(mMediaPlayer);
+ }
+ }
+ };
+
+ 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 (mMediaController != null) {
+ mMediaController.hide();
+ }
+
+ /* 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;
+ } else {
+ messageId = com.android.internal.R.string.VideoView_error_text_unknown;
+ }
+
+ new AlertDialog.Builder(mContext)
+ .setMessage(messageId)
+ .setPositiveButton(com.android.internal.R.string.VideoView_error_button,
+ 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 (mOnCompletionListener != null) {
+ mOnCompletionListener.onCompletion(mMediaPlayer);
+ }
+ }
+ })
+ .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(OnCompletionListener l) {
+ mOnCompletionListener = 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;
+ }
+
+ /**
+ * Register a callback to be invoked when an informational event
+ * occurs during playback or setup.
+ *
+ * @param l The callback that will be run
+ */
+ 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();
+ }
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ /*
+ if (mCurrentState == STATE_SUSPENDED) {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ if (mMediaPlayer.resume()) {
+ mCurrentState = STATE_PREPARED;
+ if (mSeekWhenPrepared != 0) {
+ seekTo(mSeekWhenPrepared);
+ }
+ if (mTargetState == STATE_PLAYING) {
+ start();
+ }
+ return;
+ } else {
+ release(false);
+ }
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ */
+
+ if (LOG) {
+ Log.v(TAG, "surfaceCreated(" + holder + ")");
+ }
+ if (mCurrentState == STATE_SUSPENDED) {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder);
+ release(false);
+ }
+ mSurfaceHolder = holder;
+ openVideo();
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // after we return from this we can't use the surface any more
+ mSurfaceHolder = null;
+ if (mMediaController != null) mMediaController.hide();
+ if (isHTTPStreaming(mUri) && mCurrentState == STATE_SUSPENDED) {
+ // Don't call release() while run suspend operation
+ return;
+ }
+ 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;
+ }
+ }
+ }
+
+ @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) {
+ final boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
+ keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
+ keyCode != KeyEvent.KEYCODE_MENU &&
+ keyCode != KeyEvent.KEYCODE_CALL &&
+ keyCode != KeyEvent.KEYCODE_ENDCALL &&
+ keyCode != KeyEvent.KEYCODE_CAMERA;
+ if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
+ if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)) {
+ if (mMediaPlayer.isPlaying()) {
+ pause();
+ mMediaController.show();
+ } else {
+ start();
+ mMediaController.hide();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+ if (!mMediaPlayer.isPlaying()) {
+ start();
+ mMediaController.hide();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+ || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+ if (mMediaPlayer.isPlaying()) {
+ pause();
+ mMediaController.show();
+ }
+ return true;
+ } else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_NEXT ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_REWIND ||
+ keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
+ keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
+ // consume media action, so if video view if front,
+ // other media player will not play any sounds.
+ return true;
+ } else {
+ toggleMediaControlsVisiblity();
+ }
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void toggleMediaControlsVisiblity() {
+ if (mMediaController.isShowing()) {
+ mMediaController.hide();
+ } else {
+ mMediaController.show();
+ }
+ }
+
+ @Override
+ public void start() {
+ if (isInPlaybackState()) {
+ mMediaPlayer.start();
+ mCurrentState = STATE_PLAYING;
+ }
+ mTargetState = STATE_PLAYING;
+ }
+
+ @Override
+ public void pause() {
+ if (isInPlaybackState()) {
+ if (mMediaPlayer.isPlaying()) {
+ mMediaPlayer.pause();
+ mCurrentState = STATE_PAUSED;
+ }
+ }
+ mTargetState = STATE_PAUSED;
+ }
+
+ public void suspend() {
+ // HTTP streaming will call mMediaPlayer->suspend(), others will call release()
+ /*
+ if (isHTTPStreaming(mUri) && mCurrentState != STATE_PREPARING) {
+ if (mMediaPlayer.suspend()) {
+ mTargetState = mCurrentState;
+ mCurrentState = STATE_SUSPENDED;
+ return;
+ }
+ }*/
+ release(false);
+ }
+
+ public void resume() {
+ setResumed(true);
+ openVideo();
+ }
+
+ @Override
+ public int getDuration() {
+ final boolean inPlaybackState = isInPlaybackState();
+ if (LOG) {
+ Log.v(TAG, "getDuration() mDuration=" + mDuration + ", inPlaybackState="
+ + inPlaybackState);
+ }
+ if (inPlaybackState) {
+ if (mDuration > 0) {
+ return mDuration;
+ }
+ // in case the duration is zero or smaller than zero for streaming
+ // video
+ int tempDuration = mMediaPlayer.getDuration();
+ if (tempDuration <= 0) {
+ return mDuration;
+ } else {
+ mDuration = tempDuration;
+ }
+
+ return mDuration;
+ }
+ return mDuration;
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ int position = 0;
+ if (mSeekWhenPrepared > 0) {
+ // if connecting error before seek,
+ // we should remember this position for retry
+ position = mSeekWhenPrepared;
+ // /M: if player not started, getCurrentPosition() will lead to NE.
+ } else if (isInPlaybackState()) {
+ position = mMediaPlayer.getCurrentPosition();
+ }
+ if (LOG) {
+ Log.v(TAG, "getCurrentPosition() return " + position
+ + ", mSeekWhenPrepared=" + mSeekWhenPrepared);
+ }
+ return position;
+ }
+
+ @Override
+ public void seekTo(int msec) {
+ if (isInPlaybackState()) {
+ mMediaPlayer.seekTo(msec);
+ mSeekWhenPrepared = 0;
+ } else {
+ mSeekWhenPrepared = msec;
+ }
+ }
+
+ @Override
+ public boolean isPlaying() {
+ return isInPlaybackState() && mMediaPlayer.isPlaying();
+ }
+
+ @Override
+ public int getBufferPercentage() {
+ if (mMediaPlayer != null) {
+ return mCurrentBufferPercentage;
+ }
+ return 0;
+ }
+
+ private boolean isInPlaybackState() {
+ return (mMediaPlayer != null &&
+ mCurrentState != STATE_ERROR &&
+ mCurrentState != STATE_IDLE &&
+ mCurrentState != STATE_PREPARING &&
+ mCurrentState != STATE_SUSPENDED);
+ }
+
+ @Override
+ public boolean canPause() {
+ return mCanPause;
+ }
+
+ @Override
+ public boolean canSeekBackward() {
+ return mCanSeekBack;
+ }
+
+ @Override
+ public boolean canSeekForward() {
+ return mCanSeekForward;
+ }
+
+ @Override
+ public int getAudioSessionId() {
+ if (mAudioSession == 0) {
+ MediaPlayer foo = new MediaPlayer();
+ mAudioSession = foo.getAudioSessionId();
+ foo.release();
+ }
+ return mAudioSession;
+ }
+
+ // for duration displayed
+ public void setDuration(final int duration) {
+ if (LOG) {
+ Log.v(TAG, "setDuration(" + duration + ")");
+ }
+ mDuration = (duration > 0 ? -duration : duration);
+ }
+
+ public void setVideoURI(final Uri uri, final Map<String, String> headers,
+ final boolean hasGotMetaData) {
+ if (LOG) {
+ Log.v(TAG, "setVideoURI(" + uri + ", " + headers + ")");
+ }
+ // clear the flags
+ mHasGotMetaData = hasGotMetaData;
+ setVideoURI(uri, headers);
+ }
+
+ private void doPreparedIfReady(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "doPreparedIfReady() mHasGotPreparedCallBack=" + mHasGotPreparedCallBack
+ + ", mHasGotMetaData=" + mHasGotMetaData + ", mNeedWaitLayout="
+ + mNeedWaitLayout
+ + ", mCurrentState=" + mCurrentState);
+ }
+ if (mHasGotPreparedCallBack && mHasGotMetaData && !mNeedWaitLayout) {
+ doPrepared(mp);
+ }
+ }
+
+ private void doPrepared(final MediaPlayer mp) {
+ if (LOG) {
+ Log.v(TAG, "doPrepared(" + mp + ") start");
+ }
+ mCurrentState = STATE_PREPARED;
+ if (mOnPreparedListener != null) {
+ mOnPreparedListener.onPrepared(mMediaPlayer);
+ }
+ mVideoWidth = mp.getVideoWidth();
+ mVideoHeight = mp.getVideoHeight();
+
+ // mSeekWhenPrepared may be changed after seekTo()
+ final int seekToPosition = mSeekWhenPrepared;
+ if (seekToPosition != 0) {
+ seekTo(seekToPosition);
+ }
+ if (mVideoWidth != 0 && mVideoHeight != 0) {
+ getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+ }
+
+ if (mTargetState == STATE_PLAYING) {
+ start();
+ }
+ if (LOG) {
+ Log.v(TAG, "doPrepared() end video size: " + mVideoWidth + "," + mVideoHeight
+ + ", mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
+ }
+ }
+
+ /**
+ * surfaceCreate will invoke openVideo after the activity stoped. Here set
+ * this flag to avoid openVideo after the activity stoped.
+ *
+ * @param resume
+ */
+ public void setResumed(final boolean resume) {
+ if (LOG) {
+ Log.v(TAG, "setResumed(" + resume + ") mUri=" + mUri + ", mOnResumed=" + mOnResumed);
+ }
+ mOnResumed = resume;
+ }
+
+ private void clearVideoInfo() {
+ if (LOG) {
+ Log.v(TAG, "clearVideoInfo()");
+ }
+ mHasGotPreparedCallBack = false;
+ mNeedWaitLayout = false;
+ }
+
+ public void clearSeek() {
+ if (LOG) {
+ Log.v(TAG, "clearSeek() mSeekWhenPrepared=" + mSeekWhenPrepared);
+ }
+ mSeekWhenPrepared = 0;
+ }
+
+ public void clearDuration() {
+ if (LOG) {
+ Log.v(TAG, "clearDuration() mDuration=" + mDuration);
+ }
+ mDuration = -1;
+ }
+
+ public boolean isTargetPlaying() {
+ if (LOG) {
+ Log.v(TAG, "isTargetPlaying() mTargetState=" + mTargetState);
+ }
+ return mTargetState == STATE_PLAYING;
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/DmReceiver.java b/src/org/codeaurora/gallery3d/video/DmReceiver.java
new file mode 100644
index 000000000..616ce33d6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/DmReceiver.java
@@ -0,0 +1,65 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.preference.PreferenceManager;
+import android.provider.Settings.System;
+import android.util.Log;
+
+public class DmReceiver extends BroadcastReceiver {
+ private static final String TAG = "DmReceiver";
+ public static final String WRITE_SETTING_ACTION = "streaming.action.WRITE_SETTINGS";
+ public static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+
+ private SharedPreferences mPref;
+ static final int STREAMING_CONNPROFILE_IO_HANDLER_TYPE = 1;
+ static final int STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE = 3;
+ static final int STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE = 4;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mPref == null) {
+ mPref = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+ if (BOOT_COMPLETED.equals(intent.getAction())) {
+ String rtpMaxport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MAXPORT, "65535");
+ String rtpMinport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MINPORT, "8192");
+ String apn = mPref.getString(SettingsActivity.PREFERENCE_APN, "CMWAP");
+ System.putString(context.getContentResolver(),
+ "streaming_max_udp_port", rtpMaxport);
+ System.putString(context.getContentResolver(),
+ "streaming_min_udp_port", rtpMinport);
+ System.putString(context.getContentResolver(), "apn", apn);
+ } else if (WRITE_SETTING_ACTION.equals(intent.getAction())) {
+ int valueType = intent.getIntExtra("type", 0);
+ String value = intent.getStringExtra("value");
+ if (valueType == STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MAXPORT,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "streaming_max_udp_port", value);
+ } else if (valueType == STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MINPORT,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "streaming_min_udp_port", value);
+ } else if (valueType == STREAMING_CONNPROFILE_IO_HANDLER_TYPE) {
+ mPref.edit().putString(SettingsActivity.PREFERENCE_APN,
+ value).commit();
+ System.putString(context.getContentResolver(),
+ "apn", value);
+ }
+ }
+ }
+}
diff --git a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
index 7694cbfff..f95e9c09f 100755
--- a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
+++ b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
@@ -18,6 +18,7 @@ public class ExtensionHelper {
final ActivityHookerGroup group = new ActivityHookerGroup();
boolean loop = context.getResources().getBoolean(R.bool.loop);
boolean stereo = context.getResources().getBoolean(R.bool.stereo);
+ boolean streaming = context.getResources().getBoolean(R.bool.streaming);
if (loop == true) {
group.addHooker(new LoopVideoHooker()); // add it for common feature.
@@ -25,7 +26,10 @@ public class ExtensionHelper {
if (stereo == true) {
group.addHooker(new StereoAudioHooker()); // add it for common feature.
}
-
+ if (streaming == true) {
+ group.addHooker(new StreamingHooker());
+ group.addHooker(new BookmarkHooker());
+ }
return group;
}
}
diff --git a/src/com/qcom/gallery3d/video/MovieTitleHelper.java b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
index 42ba3ec90..5f2229d5e 100755..100644
--- a/src/com/qcom/gallery3d/video/MovieTitleHelper.java
+++ b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
@@ -1,4 +1,4 @@
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.content.Context;
import android.database.Cursor;
@@ -6,15 +6,15 @@ import android.database.sqlite.SQLiteException;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
+import android.util.Log;
-import com.qcom.gallery3d.ext.QcomLog;
import java.io.File;
public class MovieTitleHelper {
private static final String TAG = "MovieTitleHelper";
private static final boolean LOG = true;
-
+
public static String getTitleFromMediaData(final Context context, final Uri uri) {
String title = null;
Cursor cursor = null;
@@ -22,14 +22,20 @@ public class MovieTitleHelper {
String data = Uri.decode(uri.toString());
data = data.replaceAll("'", "''");
final String where = "_data LIKE '%" + data.replaceFirst("file:///", "") + "'";
- cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
- new String[]{OpenableColumns.DISPLAY_NAME}, where, null, null);
- if (LOG) {
- QcomLog.v(TAG, "setInfoFromMediaData() cursor=" + (cursor == null ? "null" : cursor.getCount()));
+ cursor = context.getContentResolver().query(
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+ new String[] {
+ OpenableColumns.DISPLAY_NAME
+ }, where, null, null);
+ if (LOG) {
+ Log.v(
+ TAG,
+ "setInfoFromMediaData() cursor="
+ + (cursor == null ? "null" : cursor.getCount()));
}
if (cursor != null && cursor.moveToFirst()) {
title = cursor.getString(0);
- }
+ }
} catch (final SQLiteException ex) {
ex.printStackTrace();
} finally {
@@ -38,20 +44,22 @@ public class MovieTitleHelper {
}
}
if (LOG) {
- QcomLog.v(TAG, "setInfoFromMediaData() return " + title);
+ Log.v(TAG, "setInfoFromMediaData() return " + title);
}
return title;
}
-
+
public static String getTitleFromDisplayName(final Context context, final Uri uri) {
String title = null;
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri,
- new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
+ new String[] {
+ OpenableColumns.DISPLAY_NAME
+ }, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
title = cursor.getString(0);
- }
+ }
} catch (final SQLiteException ex) {
ex.printStackTrace();
} finally {
@@ -60,29 +68,31 @@ public class MovieTitleHelper {
}
}
if (LOG) {
- QcomLog.v(TAG, "getTitleFromDisplayName() return " + title);
+ Log.v(TAG, "getTitleFromDisplayName() return " + title);
}
return title;
}
-
+
public static String getTitleFromUri(final Uri uri) {
final String title = Uri.decode(uri.getLastPathSegment());
if (LOG) {
- QcomLog.v(TAG, "getTitleFromUri() return " + title);
+ Log.v(TAG, "getTitleFromUri() return " + title);
}
return title;
}
-
+
public static String getTitleFromData(final Context context, final Uri uri) {
String title = null;
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri,
- new String[]{"_data"}, null, null, null);
+ new String[] {
+ "_data"
+ }, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final File file = new File(cursor.getString(0));
title = file.getName();
- }
+ }
} catch (final SQLiteException ex) {
ex.printStackTrace();
} finally {
@@ -91,7 +101,7 @@ public class MovieTitleHelper {
}
}
if (LOG) {
- QcomLog.v(TAG, "getTitleFromData() return " + title);
+ Log.v(TAG, "getTitleFromData() return " + title);
}
return title;
}
diff --git a/src/com/qcom/gallery3d/video/SettingsActivity.java b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
index b3324e9f2..450f10d7c 100755
--- a/src/com/qcom/gallery3d/video/SettingsActivity.java
+++ b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
@@ -1,5 +1,4 @@
-
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.app.ActionBar;
import android.app.Activity;
@@ -7,7 +6,9 @@ import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
@@ -16,68 +17,38 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.RingtonePreference;
import android.preference.PreferenceScreen;
-import android.provider.Telephony;
-import android.telephony.MSimTelephonyManager;
-import java.util.ArrayList;
-import android.os.SystemProperties;
-
-
-
-
-
-/* wangyong 2012.2.9 begin*/
-//import android.provider.Calendar;
-/* wangyong 2012.2.9 end*/
import android.provider.ContactsContract;
+import android.provider.Telephony;
+import android.telephony.TelephonyManager;
+import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
-import android.text.method.DigitsKeyListener;
-import android.net.Uri;
-
-import android.telephony.TelephonyManager;
import com.android.gallery3d.R;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
+import java.util.ArrayList;
public class SettingsActivity extends PreferenceActivity {
- public static final String PREFERENCE_RTP_MINPORT = "rtp_min_port";
+ public static final String PREFERENCE_RTP_MINPORT = "rtp_min_port";
public static final String PREFERENCE_RTP_MAXPORT = "rtp_max_port";
-
public static final String PREFERENCE_RTCP_MINPORT = "rtcp_min_port";
-
public static final String PREFERENCE_RTCP_MAXPORT = "rtcp_max_port";
-
public static final String PREFERENCE_BUFFER_SIZE = "buffer_size";
-
public static final String PREFERENCE_APN = "apn";
-
private EditTextPreference mRtpMinPort;
-
private EditTextPreference mRtpMaxPort;
-
private EditTextPreference mRtcpMinPort;
-
private EditTextPreference mRtcpMaxPort;
-
private EditTextPreference mBufferSize;
-
private PreferenceScreen mApn;
-
private CheckBoxPreference mRepeat;
private static final int SELECT_APN = 1;
-
public static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
-
private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
-
private static final int ID_INDEX = 0;
-
private static final int NAME_INDEX = 1;
private boolean mUseNvOperatorForEhrpd = SystemProperties.getBoolean(
@@ -86,11 +57,8 @@ public class SettingsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Log.v("settingActivty", "onCreate");
addPreferencesFromResource(R.xml.rtsp_settings_preferences);
- // SharedPreferences mPref =
- // PreferenceManager.getDefaultSharedPreferences(ComposeMessageActivity.this);
SharedPreferences mPref;
mPref = getPreferenceScreen().getSharedPreferences();
String rtpMinport = mPref.getString(PREFERENCE_RTP_MINPORT, "8192");
@@ -98,8 +66,7 @@ public class SettingsActivity extends PreferenceActivity {
String rtcpMinport = mPref.getString(PREFERENCE_RTCP_MAXPORT, null);
String rtcpMaxport = mPref.getString(PREFERENCE_RTCP_MAXPORT, null);
String bufferSize = mPref.getString(PREFERENCE_BUFFER_SIZE, null);
- // String apn = getSelectedApnKey();//mPref.getString(PREFERENCE_APN,
- // "CMWAP");
+
mRtpMinPort = (EditTextPreference) findPreference(PREFERENCE_RTP_MINPORT);
mRtpMinPort.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
mRtpMinPort.setSummary(rtpMinport);
@@ -108,11 +75,9 @@ public class SettingsActivity extends PreferenceActivity {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
mRtpMinPort.setSummary(summary);
- /* Start of zhuzhongwei 2011.2.14 */
- Log.w("rtsp", "z66 summary = " + summary);
+ Log.d("rtsp", "z66 summary = " + summary);
android.provider.Settings.System.putString(getContentResolver(),
"streaming_min_udp_port", summary);
- /* End of zhuzhongwei 2011.2.14 */
return true;
}
});
@@ -125,11 +90,9 @@ public class SettingsActivity extends PreferenceActivity {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String summary = newValue.toString();
mRtpMaxPort.setSummary(summary);
- /* Start of zhuzhongwei 2011.2.14 */
Log.w("rtsp", "z82 summary = " + summary);
android.provider.Settings.System.putString(getContentResolver(),
"streaming_max_udp_port", summary);
- /* End of zhuzhongwei 2011.2.14 */
return true;
}
});
@@ -153,7 +116,7 @@ public class SettingsActivity extends PreferenceActivity {
return true;
}
});
-
+
mBufferSize = (EditTextPreference) findPreference(PREFERENCE_BUFFER_SIZE);
mBufferSize.getEditText().setKeyListener(DigitsKeyListener.getInstance("0123456789"));
mBufferSize.setSummary(bufferSize);
@@ -165,80 +128,21 @@ public class SettingsActivity extends PreferenceActivity {
}
});
- /*
- * mBufferSize= (EditTextPreference)
- * findPreference(PREFERENCE_BUFFER_SIZE);
- * mBufferSize.getEditText().setKeyListener
- * (DigitsKeyListener.getInstance("0123456789"));
- * mBufferSize.setSummary(bufferSize);
- * mBufferSize.setOnPreferenceChangeListener(new
- * Preference.OnPreferenceChangeListener() { public boolean
- * onPreferenceChange(Preference preference, Object newValue) { final
- * String summary = newValue.toString();
- * mBufferSize.setSummary(summary); return true; } }); <!----
- * <PreferenceCategory android:title="@string/buffer_size">
- * <EditTextPreference android:order="5" android:key="buffer_size"
- * android:title="@string/buffer_size" android:summary=""
- * android:inputType="number"
- * android:dialogTitle="@string/set_buffer_size" />
- * </PreferenceCategory> ---->
- */
- /*
- * mApn = (ListPreference) findPreference(PREFERENCE_APN);
- * mApn.setValue(apn); mApn.setSummary(mApn.getEntry());
- * mApn.setOnPreferenceChangeListener(new
- * Preference.OnPreferenceChangeListener() { public boolean
- * onPreferenceChange(Preference preference, Object newValue) { final
- * String summary = newValue.toString(); int index =
- * mApn.findIndexOfValue(summary);
- * mApn.setSummary(mApn.getEntries()[index]); mApn.setValue(summary);
- * android.provider.Settings.System.putString(getContentResolver(),
- * "apn", summary); return true; } });
- */
- /*
- * mApn = (ListPreference) findPreference(PREFERENCE_APN);
- * mApn.setValue(getSelectedApnKey()); mApn.setSummary(mApn.getEntry());
- * mApn.setOnPreferenceChangeListener(new
- * Preference.OnPreferenceChangeListener() { public boolean
- * onPreferenceChange(Preference preference, Object newValue) { //final
- * String summary = newValue.toString(); //int index =
- * mApn.findIndexOfValue(summary);
- * ////mApn.setSummary(mApn.getEntries()[index]);
- * //mApn.setValue(summary);
- * //android.provider.Settings.System.putString(getContentResolver(),
- * "apn", summary); Intent intent = new Intent();
- * intent.setClassName("com.android.settings"
- * ,"com.android.settings.ApnSettings"); //startActivity(intent);
- * startActivityForResult(intent, SELECT_APN); return true; } });
- */
-
mApn = (PreferenceScreen) findPreference(PREFERENCE_APN);
- // mApn.setValue(getSelectedApnKey());
mApn.setSummary(getDefaultApnName());
mApn.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
- // final String summary = newValue.toString();
- // int index = mApn.findIndexOfValue(summary);
- // //mApn.setSummary(mApn.getEntries()[index]);
- // mApn.setValue(summary);
- // android.provider.Settings.System.putString(getContentResolver(),
- // "apn", summary);
-
Intent intent = new Intent();
intent.setClassName("com.android.settings", "com.android.settings.ApnSettings");
- // startActivity(intent);
startActivityForResult(intent, SELECT_APN);
return true;
}
});
-
- // lizhongchao add for 4.0 UI START
ActionBar ab = getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setTitle(R.string.setting);
- // lizhongchao add for 4.0 UI END
}
private String getDefaultApnName() {
@@ -247,23 +151,17 @@ public class SettingsActivity extends PreferenceActivity {
String key = null;
String name = null;
Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {
- "_id"
+ "_id"
}, null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
key = cursor.getString(ID_INDEX);
- Log.v("settingActivty", "default apn key = " + key);
+ Log.v("settingActivty", "default apn key = " + key);
}
cursor.close();
// to find default proxy
- /**
- String where = "numeric=\""
- + android.os.SystemProperties.get(
- TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "") + "\"";
- */
-
- String where = getOperatorNumericSelection();
+ String where = getOperatorNumericSelection();
cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
"_id", "name", "apn", "type"
@@ -272,19 +170,6 @@ public class SettingsActivity extends PreferenceActivity {
while (cursor != null && cursor.moveToNext()) {
String curKey = cursor.getString(cursor.getColumnIndex("_id"));
String curName = cursor.getString(cursor.getColumnIndex("name"));
- Log.v("settingActivty", "default apn curkey = " + curKey);
- Log.v("settingActivty", "default apn curName = " + curName);
- // String user = cursor.getString(cursor.getColumnIndex("user"));
- // String password =
- // cursor.getString(cursor.getColumnIndex("password"));
- // a.proxy = cursor.getString(cursor.getColumnIndex("proxy"));
- // a.type = cursor.getString(cursor.getColumnIndex("type"));
-
- // logv( "getDefaultApn, a.key=" + a.key + ",a.apn=" + a.apn +
- // ",a.user=" + a.user + ",a.password=" + a.password + ", a.proxy="
- // + a.proxy);
- // Log.d("rtsp","getDefaultApnName, cur, key=" + curKey +
- // ",curName=" + curName);
if (curKey.equals(key)) {
Log.d("rtsp", "getDefaultApnName, find, key=" + curKey + ",curName=" + curName);
name = curName;
@@ -292,10 +177,9 @@ public class SettingsActivity extends PreferenceActivity {
}
}
- if (cursor != null)
+ if (cursor != null) {
cursor.close();
- Log.v("settingActivty", "default apn name = " + name);
-
+ }
return name;
}
@@ -322,26 +206,22 @@ public class SettingsActivity extends PreferenceActivity {
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case SELECT_APN:
- // if (resultCode == RESULT_CANCELED) {
setResult(resultCode);
finish();
Log.w("rtsp", "onActivityResult requestCode = " + requestCode);
- // mApn.setSummary(getDefaultApnName());
- // }
break;
}
}
-
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
- if(item.getItemId() == android.R.id.home){
+ if (item.getItemId() == android.R.id.home) {
finish();
}
return true;
}
-
private String getOperatorNumericSelection() {
String[] mccmncs = getOperatorNumeric();
String where;
@@ -362,7 +242,7 @@ public class SettingsActivity extends PreferenceActivity {
}
mccMncFromSim = TelephonyManager.getDefault().getSimOperator();
-
+
if (mccMncFromSim != null && mccMncFromSim.length() > 0) {
result.add(mccMncFromSim);
}
diff --git a/src/com/qcom/gallery3d/video/StreamingHooker.java b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
index 84152fc9d..d4fa43fc5 100755..100644
--- a/src/com/qcom/gallery3d/video/StreamingHooker.java
+++ b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
@@ -1,68 +1,56 @@
-package com.qcom.gallery3d.video;
+package org.codeaurora.gallery3d.video;
import android.content.Intent;
import android.net.Uri;
import android.provider.Browser;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import com.android.gallery3d.R;
-import com.qcom.gallery3d.ext.MovieUtils;
-import com.qcom.gallery3d.ext.QcomLog;
+import org.codeaurora.gallery3d.ext.MovieUtils;
public class StreamingHooker extends MovieHooker {
private static final String TAG = "StreamingHooker";
private static final boolean LOG = true;
-
- private static final String ACTION_STREAMING = "com.qcom.settings.streaming";
+
+ private static final String ACTION_STREAMING = "org.codeaurora.settings.streaming";
private static final int MENU_INPUT_URL = 1;
private static final int MENU_SETTINGS = 2;
private static final int MENU_DETAIL = 3;
- private MenuItem mMenuDetail;
-
+
public static final String KEY_LOGO_BITMAP = "logo-bitmap";
-
+
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
super.onCreateOptionsMenu(menu);
- //when in rtsp streaming type, generally it only has one uri.
- mMenuDetail = menu.add(0, getMenuActivityId(MENU_DETAIL), 0, R.string.media_detail);
+ // when in rtsp streaming type, generally it only has one uri.
menu.add(0, getMenuActivityId(MENU_INPUT_URL), 0, R.string.input_url);
menu.add(0, getMenuActivityId(MENU_SETTINGS), 0, R.string.streaming_settings);
return true;
}
+
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
- if (MovieUtils.isLocalFile(getMovieItem().getUri(), getMovieItem().getMimeType())) {
- if (mMenuDetail != null) {
- mMenuDetail.setVisible(false);
- }
- } else {
- if (mMenuDetail != null) {
- mMenuDetail.setVisible(false);
- }
- }
return true;
}
+
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
super.onOptionsItemSelected(item);
- switch(getMenuOriginalId(item.getItemId())) {
- case MENU_INPUT_URL:
- gotoInputUrl();
- return true;
- case MENU_SETTINGS:
- gotoSettings();
- return true;
- case MENU_DETAIL:
- getPlayer().showDetail();
- return true;
- default:
- return false;
+ switch (getMenuOriginalId(item.getItemId())) {
+ case MENU_INPUT_URL:
+ gotoInputUrl();
+ return true;
+ case MENU_SETTINGS:
+ gotoSettings();
+ return true;
+ default:
+ return false;
}
}
-
+
private void gotoInputUrl() {
final String appName = getClass().getName();
final Intent intent = new Intent();
@@ -72,18 +60,19 @@ public class StreamingHooker extends MovieHooker {
intent.putExtra(Browser.EXTRA_APPLICATION_ID, appName);
getContext().startActivity(intent);
if (LOG) {
- QcomLog.v(TAG, "gotoInputUrl() appName=" + appName);
+ Log.v(TAG, "gotoInputUrl() appName=" + appName);
}
}
-
+
private void gotoSettings() {
final Intent intent = new Intent(ACTION_STREAMING);
-// intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
-// | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
-// intent.putExtra(KEY_LOGO_BITMAP, getIntent().getParcelableExtra(KEY_LOGO_BITMAP));
+ // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ // | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
+ // intent.putExtra(KEY_LOGO_BITMAP,
+ // getIntent().getParcelableExtra(KEY_LOGO_BITMAP));
getContext().startActivity(intent);
if (LOG) {
- QcomLog.v(TAG, "gotoInputUrl()");
+ Log.v(TAG, "gotoInputUrl()");
}
}
-} \ No newline at end of file
+}