[Android] [PATCH 12/12] Merge tv with gradle integration
Geoffrey Métais
geoffrey.metais at gmail.com
Mon Nov 17 17:06:50 CET 2014
---
vlc-android/AndroidManifest.xml | 39 +-
vlc-android/build.gradle | 55 ++-
vlc-android/project.properties | 2 +-
vlc-android/res/layout/tv_audio_player.xml | 102 -----
vlc-android/res/layout/tv_details.xml | 6 -
vlc-android/res/layout/tv_main.xml | 7 -
vlc-android/res/layout/tv_main_fragment.xml | 7 -
vlc-android/res/layout/tv_search | 8 -
vlc-android/res/layout/tv_vertical_grid | 6 -
vlc-android/res/values/dimens.xml | 2 -
vlc-android/res/values/strings.xml | 3 -
.../src/org/videolan/vlc/gui/tv/CardPresenter.java | 106 ------
.../org/videolan/vlc/gui/tv/DetailsActivity.java | 14 -
.../vlc/gui/tv/DetailsDescriptionPresenter.java | 24 --
.../src/org/videolan/vlc/gui/tv/GridFragment.java | 319 ----------------
.../org/videolan/vlc/gui/tv/MainTvActivity.java | 268 -------------
.../org/videolan/vlc/gui/tv/MediaItemDetails.java | 64 ----
.../vlc/gui/tv/MediaItemDetailsFragment.java | 121 ------
.../org/videolan/vlc/gui/tv/SearchActivity.java | 15 -
.../org/videolan/vlc/gui/tv/SearchFragment.java | 114 ------
.../org/videolan/vlc/gui/tv/StringPresenter.java | 29 --
.../src/org/videolan/vlc/gui/tv/TvMedia.java | 136 -------
.../src/org/videolan/vlc/gui/tv/TvUtil.java | 29 --
.../videolan/vlc/gui/tv/VerticalGridActivity.java | 17 -
.../gui/tv/audioplayer/AudioPlayerActivity.java | 278 --------------
.../gui/tv/audioplayer/DividerItemDecoration.java | 105 ------
.../vlc/gui/tv/audioplayer/PlaylistAdapter.java | 55 ---
vlc-android/tv/AndroidManifest.xml | 419 +++++++++++++++++++++
vlc-android/tv/res/layout/tv_audio_player.xml | 102 +++++
vlc-android/tv/res/layout/tv_details.xml | 6 +
vlc-android/tv/res/layout/tv_main.xml | 7 +
vlc-android/tv/res/layout/tv_main_fragment.xml | 7 +
vlc-android/tv/res/layout/tv_search | 8 +
vlc-android/tv/res/layout/tv_vertical_grid | 6 +
vlc-android/tv/res/values/dimens.xml | 4 +
vlc-android/tv/res/values/strings.xml | 5 +
.../src/org/videolan/vlc/gui/tv/CardPresenter.java | 106 ++++++
.../org/videolan/vlc/gui/tv/DetailsActivity.java | 14 +
.../vlc/gui/tv/DetailsDescriptionPresenter.java | 24 ++
.../src/org/videolan/vlc/gui/tv/GridFragment.java | 319 ++++++++++++++++
.../org/videolan/vlc/gui/tv/MainTvActivity.java | 268 +++++++++++++
.../org/videolan/vlc/gui/tv/MediaItemDetails.java | 64 ++++
.../vlc/gui/tv/MediaItemDetailsFragment.java | 121 ++++++
.../org/videolan/vlc/gui/tv/SearchActivity.java | 15 +
.../org/videolan/vlc/gui/tv/SearchFragment.java | 114 ++++++
.../org/videolan/vlc/gui/tv/StringPresenter.java | 29 ++
.../tv/src/org/videolan/vlc/gui/tv/TvMedia.java | 136 +++++++
.../tv/src/org/videolan/vlc/gui/tv/TvUtil.java | 29 ++
.../videolan/vlc/gui/tv/VerticalGridActivity.java | 17 +
.../gui/tv/audioplayer/AudioPlayerActivity.java | 278 ++++++++++++++
.../gui/tv/audioplayer/DividerItemDecoration.java | 105 ++++++
.../vlc/gui/tv/audioplayer/PlaylistAdapter.java | 55 +++
52 files changed, 2307 insertions(+), 1882 deletions(-)
delete mode 100644 vlc-android/res/layout/tv_audio_player.xml
delete mode 100644 vlc-android/res/layout/tv_details.xml
delete mode 100644 vlc-android/res/layout/tv_main.xml
delete mode 100644 vlc-android/res/layout/tv_main_fragment.xml
delete mode 100644 vlc-android/res/layout/tv_search
delete mode 100644 vlc-android/res/layout/tv_vertical_grid
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/DetailsActivity.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/SearchActivity.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/SearchFragment.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/StringPresenter.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/TvMedia.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
delete mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
create mode 100644 vlc-android/tv/AndroidManifest.xml
create mode 100644 vlc-android/tv/res/layout/tv_audio_player.xml
create mode 100644 vlc-android/tv/res/layout/tv_details.xml
create mode 100644 vlc-android/tv/res/layout/tv_main.xml
create mode 100644 vlc-android/tv/res/layout/tv_main_fragment.xml
create mode 100644 vlc-android/tv/res/layout/tv_search
create mode 100644 vlc-android/tv/res/layout/tv_vertical_grid
create mode 100644 vlc-android/tv/res/values/dimens.xml
create mode 100644 vlc-android/tv/res/values/strings.xml
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/CardPresenter.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsActivity.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchActivity.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/StringPresenter.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/TvMedia.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/TvUtil.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
create mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
diff --git a/vlc-android/AndroidManifest.xml b/vlc-android/AndroidManifest.xml
index 7456de7..276988d 100644
--- a/vlc-android/AndroidManifest.xml
+++ b/vlc-android/AndroidManifest.xml
@@ -6,8 +6,8 @@
android:versionName="1.0.0-git" >
<uses-sdk
- android:minSdkVersion="L"
- android:targetSdkVersion="L" />
+ android:minSdkVersion="7"
+ android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
@@ -17,8 +17,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
- <!-- Needed for audio search on TV -->
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:name="org.videolan.vlc.VLCApplication"
@@ -29,18 +27,6 @@
android:logo="@drawable/ic_logo_w"
android:theme="@style/Theme.VLC.NoTitleBar" >
<activity
- android:name="org.videolan.vlc.gui.tv.MainTvActivity"
- android:label="@string/app_name"
- android:theme="@style/Theme.Leanback">
-
- <intent-filter
- android:priority="5">
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
- </intent-filter>
- </activity>
- <activity
android:name=".gui.MainActivity"
android:configChanges="orientation|screenSize"
android:icon="@drawable/icon"
@@ -54,23 +40,6 @@
</intent-filter>
</activity>
- <activity android:name="org.videolan.vlc.gui.tv.DetailsActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.VerticalGridActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.SearchActivity"
- android:exported="true"
- android:theme="@style/Theme.Leanback"/>
-
- <activity android:name="org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity"
- android:exported="true"
- android:launchMode="singleInstance"
- android:theme="@style/Theme.Leanback"/>
-
<activity android:name=".gui.CompatErrorActivity" />
<activity android:name=".gui.PreferencesActivity" />
<activity
@@ -420,12 +389,12 @@
android:name="android.appwidget.provider"
android:resource="@xml/vlcwidget" />
</receiver>
- <!--receiver android:name=".RemoteControlClientReceiver" >
+ <receiver android:name=".RemoteControlClientReceiver" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="org.videolan.vlc.remote.PlayPause" />
</intent-filter>
- </receiver-->
+ </receiver>
</application>
</manifest>
diff --git a/vlc-android/build.gradle b/vlc-android/build.gradle
index 4628e27..b3d1210 100644
--- a/vlc-android/build.gradle
+++ b/vlc-android/build.gradle
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
+
task buildDebug(type:Exec) {
/*
Properties set for Android Studio own shell.
@@ -39,16 +40,6 @@ android {
compileSdkVersion 21
buildToolsVersion "21.0.2"
- sourceSets.main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = ['src']
- resources.srcDirs = ['src']
- aidl.srcDirs = ['src']
- renderscript.srcDirs = ['src']
- res.srcDirs = ['res']
- assets.srcDirs = ['assets']
- }
-
lintOptions {
abortOnError false
}
@@ -78,13 +69,54 @@ android {
buildTypes {
release {
- tasks.assembleRelease.dependsOn buildRelease
signingConfig signingConfigs.release
+ tasks.assembleRelease.dependsOn buildRelease
}
debug {
tasks.assembleDebug.dependsOn buildDebug
}
}
+ productFlavors {
+ vanilla {
+ tasks.whenTaskAdded { task ->
+ if (task.name == 'assembleVanillaDebug') {
+ task.dependsOn buildDebug
+ } else if (task.name == 'assembleVanillaRelease') {
+ task.dependsOn buildRelease
+ }
+ }
+ applicationId "org.videolan.vlc"
+ }
+ tv {
+ tasks.whenTaskAdded { task ->
+ if (task.name == 'assembleTvDebug') {
+ task.dependsOn buildDebug
+ } else if (task.name == 'assembleTvRelease') {
+ task.dependsOn buildRelease
+ }
+ }
+ minSdkVersion 17
+ }
+ }
+
+ sourceSets.main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+ sourceSets.tv {
+ manifest.srcFile 'tv/AndroidManifest.xml'
+ java.srcDirs = ['tv/src']
+ resources.srcDirs = ['tv/src']
+ aidl.srcDirs = ['tv/src']
+ renderscript.srcDirs = ['tv/src']
+ res.srcDirs = ['tv/res']
+ assets.srcDirs = ['tv/assets']
+ }
}
dependencies {
@@ -92,4 +124,5 @@ dependencies {
compile project(':libvlc')
compile 'com.android.support:appcompat-v7:21.0.0'
compile 'com.android.support:cardview-v7:21.0.0'
+ tvCompile 'com.android.support:leanback-v17:21.0.0'
}
\ No newline at end of file
diff --git a/vlc-android/project.properties b/vlc-android/project.properties
index 880b0ad..4ac9888 100644
--- a/vlc-android/project.properties
+++ b/vlc-android/project.properties
@@ -10,7 +10,7 @@
#split.density=true
# Project target.
-target=android-L
+target=android-21
android.library.reference.1=../java-libs/appcompat
android.library.reference.2=../java-libs/WheelView
android.library.reference.3=../java-libs/cardview
diff --git a/vlc-android/res/layout/tv_audio_player.xml b/vlc-android/res/layout/tv_audio_player.xml
deleted file mode 100644
index 1ec9e5e..0000000
--- a/vlc-android/res/layout/tv_audio_player.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:weightSum="3" >
-
- <!-- Cover -->
- <ImageView
- android:id="@+id/album_cover"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="2"
- android:padding="10dp"
- android:src="@drawable/background_cone"
- android:scaleType="fitXY" >
- </ImageView>
-
- <!-- Playlist -->
- <android.support.v7.widget.RecyclerView
- android:id="@+id/playlist"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:scrollbars="vertical" />
- </LinearLayout>
-
- <!-- Media HUD -->
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_alignParentBottom="true"
- android:paddingRight="30dip"
- android:paddingLeft="30dip"
- android:paddingTop="10dip"
- android:paddingBottom="5dip"
- android:alpha="0.8"
- android:background="@android:color/black">
- <TextView
- android:id="@+id/media_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_alignParentTop="true"
- android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Title"/>
- <TextView
- android:id="@+id/media_artist"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/media_title"
- android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Subtitle"/>
- <ProgressBar
- android:id="@+id/media_progress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/media_artist"
- android:layout_alignStart="@+id/media_controls"
- android:layout_alignEnd="@+id/media_controls"
- android:indeterminate="false"/>
- <!-- Media control buttons -->
- <LinearLayout
- android:id="@+id/media_controls"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/media_progress">
- <ImageView
- android:id="@+id/button_previous"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous"
- android:clickable="true"
- android:onClick="onClick"/>
- <ImageView
- android:id="@+id/button_play"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:src="@drawable/ic_play"
- android:clickable="true"
- android:onClick="onClick"/>
- <ImageView
- android:id="@+id/button_next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next"
- android:clickable="true"
- android:onClick="onClick"/>
- </LinearLayout>
- </RelativeLayout>
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/vlc-android/res/layout/tv_details.xml b/vlc-android/res/layout/tv_details.xml
deleted file mode 100644
index f000fbe..0000000
--- a/vlc-android/res/layout/tv_details.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="org.videolan.vlc.gui.tv.MediaItemDetailsFragment"
- android:id="@+id/details_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-/>
\ No newline at end of file
diff --git a/vlc-android/res/layout/tv_main.xml b/vlc-android/res/layout/tv_main.xml
deleted file mode 100644
index 4568719..0000000
--- a/vlc-android/res/layout/tv_main.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="org.videolan.vlc.gui.tv.MainFragment"
- android:id="@+id/main_browse_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-/>
diff --git a/vlc-android/res/layout/tv_main_fragment.xml b/vlc-android/res/layout/tv_main_fragment.xml
deleted file mode 100644
index c220b43..0000000
--- a/vlc-android/res/layout/tv_main_fragment.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="android.support.v17.leanback.app.BrowseFragment"
- android:id="@+id/browse_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
\ No newline at end of file
diff --git a/vlc-android/res/layout/tv_search b/vlc-android/res/layout/tv_search
deleted file mode 100644
index c324a89..0000000
--- a/vlc-android/res/layout/tv_search
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="org.videolan.vlc.gui.tv.SearchFragment"
- android:id="@+id/search_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
\ No newline at end of file
diff --git a/vlc-android/res/layout/tv_vertical_grid b/vlc-android/res/layout/tv_vertical_grid
deleted file mode 100644
index 7d58289..0000000
--- a/vlc-android/res/layout/tv_vertical_grid
+++ /dev/null
@@ -1,6 +0,0 @@
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="org.videolan.vlc.gui.tv.GridFragment"
- android:id="@+id/vertical_grid_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
-/>
\ No newline at end of file
diff --git a/vlc-android/res/values/dimens.xml b/vlc-android/res/values/dimens.xml
index fdbd4a8..1400716 100644
--- a/vlc-android/res/values/dimens.xml
+++ b/vlc-android/res/values/dimens.xml
@@ -10,6 +10,4 @@
<dimen name="grid_card_title_text_size">12sp</dimen>
<dimen name="grid_card_subtitle_text_size">10sp</dimen>
<dimen name="grid_card_vertical_spacing">0dp</dimen>
- <dimen name="tv_card_width">192dp</dimen>
- <dimen name="tv_card_height">108dp</dimen>
</resources>
\ No newline at end of file
diff --git a/vlc-android/res/values/strings.xml b/vlc-android/res/values/strings.xml
index 52ddf05..bf6e2d4 100644
--- a/vlc-android/res/values/strings.xml
+++ b/vlc-android/res/values/strings.xml
@@ -303,9 +303,6 @@
<string name="drawer_open">Open navigation drawer</string>
<string name="drawer_close">Close navigation drawer</string>
- <!-- Android TV -->
- <string name="search_results">Search results</string>
-
<string-array name="hardware_acceleration_list">
<item>@string/automatic</item>
<item>@string/hardware_acceleration_disabled</item>
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java b/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
deleted file mode 100644
index a070433..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/CardPresenter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaDatabase;
-import org.videolan.vlc.R;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.support.v17.leanback.widget.ImageCardView;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.View;
-import android.view.ViewGroup;
-
-public class CardPresenter extends Presenter {
-
- private static final String TAG = "CardPresenter";
-
- private static Context sContext;
- private static int CARD_WIDTH = 0;
- private static int CARD_HEIGHT = 0;
- private static Resources sResources;
- private static MediaDatabase sMediaDatabase = MediaDatabase.getInstance();
- private static Drawable sDefaultCardImage;
-
- static class ViewHolder extends Presenter.ViewHolder {
- private ImageCardView mCardView;
-
- public ViewHolder(View view) {
- super(view);
- mCardView = (ImageCardView) view;
- }
-
- public ImageCardView getCardView() {
- return mCardView;
- }
-
- protected void updateCardViewImage(String mediaLocation) {
- Bitmap picture = sMediaDatabase.getPicture(sContext, mediaLocation);
- if (picture.getByteCount() > 4)
- mCardView.setMainImage(new BitmapDrawable(sResources, picture));
- else
- updateCardViewImage(sDefaultCardImage);
- }
-
- protected void updateCardViewImage(Drawable image) {
- mCardView.setMainImage(image);
- }
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent) {
- sContext = parent.getContext();
- sResources = sContext.getResources();
- sDefaultCardImage = sContext.getResources().getDrawable(R.drawable.cone);
- if (CARD_WIDTH == 0) {
- CARD_WIDTH = sResources.getDimensionPixelSize(
- R.dimen.tv_card_width);
- CARD_HEIGHT = sResources.getDimensionPixelSize(
- R.dimen.tv_card_height);
- }
-
- ImageCardView cardView = new ImageCardView(sContext);
- cardView.setFocusable(true);
- cardView.setFocusableInTouchMode(true);
- cardView.setBackgroundColor(sContext.getResources().getColor(R.color.lb_details_overview_bg_color));
- return new ViewHolder(cardView);
- }
-
- @Override
- public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
- ((ViewHolder) viewHolder).mCardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
- if (item instanceof Media) {
- Media media = (Media) item;
- ((ViewHolder) viewHolder).mCardView.setTitleText(media.getTitle());
- ((ViewHolder) viewHolder).mCardView.setContentText(media.getDescription());
- if (media.isPictureParsed())
- ((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
- else
- ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
- } else if (item instanceof GridFragment.ListItem) {
- GridFragment.ListItem listItem = (GridFragment.ListItem) item;
- Media media = listItem.mMediaList.get(0);
- ((ViewHolder) viewHolder).mCardView.setTitleText(listItem.mTitle);
- ((ViewHolder) viewHolder).mCardView.setContentText(listItem.mSubTitle);
- if (media.isPictureParsed())
- ((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
- else
- ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
- } else if (item instanceof String){
- ((ViewHolder) viewHolder).mCardView.setTitleText((String) item);
- ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
- }
- }
-
- @Override
- public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
- }
-
- @Override
- public void onViewAttachedToWindow(Presenter.ViewHolder viewHolder) {
- // TODO?
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/DetailsActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/DetailsActivity.java
deleted file mode 100644
index 9b4bc1d..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/DetailsActivity.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.vlc.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class DetailsActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tv_details);
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java b/vlc-android/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
deleted file mode 100644
index 79292ab..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
-import android.util.Log;
-
-public class DetailsDescriptionPresenter extends
- AbstractDetailsDescriptionPresenter {
- public static final String TAG ="DetailsDescriptionPresenter";
-
- protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
- Log.d(TAG, "itemData "+itemData);
- MediaItemDetails details = (MediaItemDetails) itemData;
- // In a production app, the itemData object contains the information
- // needed to display details for the media item:
- // viewHolder.getTitle().setText(details.getShortTitle());
-
- // Here we provide static data for testing purposes:
- viewHolder.getTitle().setText(details.getTitle());
- viewHolder.getSubtitle().setText(details.getSubTitle());
- viewHolder.getBody().setText(details.getBody());
- }
-
-
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
deleted file mode 100644
index de120d8..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaDatabase;
-import org.videolan.vlc.MediaLibrary;
-import org.videolan.vlc.R;
-import org.videolan.vlc.Thumbnailer;
-import org.videolan.vlc.gui.audio.AudioUtil;
-import org.videolan.vlc.gui.audio.MediaComparators;
-import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
-import org.videolan.vlc.gui.video.VideoBrowserInterface;
-import org.videolan.vlc.gui.video.VideoListHandler;
-import org.videolan.vlc.util.Util;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.os.Handler;
-import android.support.v17.leanback.app.VerticalGridFragment;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.OnItemClickedListener;
-import android.support.v17.leanback.widget.Row;
-import android.support.v17.leanback.widget.VerticalGridPresenter;
-
-public class GridFragment extends VerticalGridFragment implements VideoBrowserInterface {
- private static final String TAG = "VLC/GridFragment";
-
- private static final int NUM_COLUMNS = 5;
-
- protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
- protected Media mItemToUpdate;
- private Map<String, ListItem> mMediaItemMap;
- private ArrayList<ListItem> mMediaItemList;
- private ArrayObjectAdapter mAdapter;
- private MediaLibrary mMediaLibrary;
- private Thumbnailer mThumbnailer;
- HashMap<String, Integer> mMediaIndex;
- Context mContext;
- String mCategory, mFilter;
- long mType = -1;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mContext = getActivity();
- if (savedInstanceState != null){
- mType = savedInstanceState.getLong(MEDIA_SECTION);
- mCategory = savedInstanceState.getString(AUDIO_CATEGORY);
- mFilter = savedInstanceState.getString(AUDIO_FILTER);
- } else {
- mType = getActivity().getIntent().getLongExtra(MEDIA_SECTION, -1);
- mCategory = getActivity().getIntent().getStringExtra(AUDIO_CATEGORY);
- mFilter = getActivity().getIntent().getStringExtra(AUDIO_FILTER);
- }
-
-
- mMediaLibrary = MediaLibrary.getInstance();
-
- if (mType == HEADER_VIDEO) {
- mThumbnailer = new Thumbnailer(mContext, getActivity().getWindowManager().getDefaultDisplay());
- setupFragment();
- } else if (mType == HEADER_MUSIC) {
- setupFragment();
- } else {
- setupFragmentForAudio();
- }
- }
-
- public void onResume() {
- super.onResume();
- if (mMediaLibrary.isWorking()) {
- Util.actionScanStart();
- }
-
- /* Start the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.start(this);
- }
-
- public void onPause() {
- super.onPause();
- mMediaLibrary.removeUpdateHandler(mHandler);
-
- /* Stop the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.stop();
- }
-
- public void onSaveInstanceState(Bundle outState){
- super.onSaveInstanceState(outState);
- outState.putLong(MEDIA_SECTION, mType);
- outState.putString(AUDIO_CATEGORY, mCategory);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mThumbnailer != null)
- mThumbnailer.clearJobs();
- mBarrier.reset();
- }
-
- private void setupFragmentForAudio() {
- Bitmap picture;
- String title;
- mMediaItemMap = new HashMap<String, ListItem>();
- mMediaItemList = new ArrayList<GridFragment.ListItem>();
- VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
- mAdapter = new ArrayObjectAdapter(new CardPresenter());
- gridPresenter.setNumberOfColumns(NUM_COLUMNS);
- setGridPresenter(gridPresenter);
-
- List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
- if (getString(R.string.artists).equals(mCategory)){
- Collections.sort(audioList, MediaComparators.byArtist);
- title = getString(R.string.artists);
- for (Media media : audioList){
- add(media.getArtist(), null, media);
- }
- } else if (getString(R.string.albums).equals(mCategory)){
- title = getString(R.string.albums);
- Collections.sort(audioList, MediaComparators.byAlbum);
- for (Media media : audioList){
- if (mFilter == null
- || (mType == FILTER_ARTIST && mFilter.equals(media.getArtist().trim()))
- || (mType == FILTER_GENRE && mFilter.equals(media.getGenre().trim()))) {
- add(media.getAlbum(), media.getArtist(), media);
- }
- }
- //Customize title for artist/genre browsing
- if (mType == FILTER_ARTIST){
- title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getArtist();
- } else if (mType == FILTER_GENRE){
- title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getGenre();
- }
- } else if (getString(R.string.genres).equals(mCategory)){
- title = getString(R.string.genres);
- Collections.sort(audioList, MediaComparators.byGenre);
- for (Media media : audioList){
- add(media.getGenre(), null, media);
- }
- } else if (getString(R.string.songs).equals(mCategory)){
- title = getString(R.string.songs);
- Collections.sort(audioList, MediaComparators.byName);
- for (Media media : audioList){
- add(media.getTitle(), media.getArtist(), media);
- }
- } else {
- title = getString(R.string.app_name_full);
- }
- setTitle(title);
- //check for pictures
- for (Media media : audioList){
- picture = AudioUtil.getCover(mContext, media, 320);
- if (picture != null){
- MediaDatabase.setPicture(media, picture);
- picture = null;
- }
- }
- mAdapter.addAll(0, mMediaItemList);
- setAdapter(mAdapter);
-
- setOnItemClickedListener(new OnItemClickedListener() {
- @Override
- public void onItemClicked(Object item, Row row) {
- ListItem listItem = (ListItem) item;
- Intent intent;
- if (getString(R.string.artists).equals(mCategory)){
- intent = new Intent(mContext, VerticalGridActivity.class);
- intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
- intent.putExtra(MEDIA_SECTION, FILTER_ARTIST);
- intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getArtist().trim());
- } else if (getString(R.string.genres).equals(mCategory)){
- intent = new Intent(mContext, VerticalGridActivity.class);
- intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
- intent.putExtra(MEDIA_SECTION, FILTER_GENRE);
- intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getGenre().trim());
- } else {
- ArrayList<String> locations = new ArrayList<String>();
- for (Media media : listItem.mMediaList){
- locations.add(media.getLocation());
- }
- intent = new Intent(mContext, AudioPlayerActivity.class);
- intent.putExtra("locations", locations);
- }
- startActivity(intent);
- }
- });
- }
-
- //TODO shrink audio part, I keep it for now just in case...
- private void setupFragment() {
- setTitle(getString(R.string.app_name_full));
- int size;
- Media media;
- Bitmap picture;
-
- MediaDatabase mediaDatabase = MediaDatabase.getInstance();
- VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
- mAdapter = new ArrayObjectAdapter(new CardPresenter());
-
- gridPresenter.setNumberOfColumns(NUM_COLUMNS);
- setGridPresenter(gridPresenter);
-
-
- ArrayList<Media> mediaList = null;
- if (mType == HEADER_VIDEO)
- mediaList = mMediaLibrary.getVideoItems();
- else if (mType == HEADER_MUSIC)
- mediaList = mMediaLibrary.getAudioItems();
- size = mediaList == null ? 0 : mediaList.size();
- mMediaIndex = new HashMap<String, Integer>(size);
-
- for (int i = 0 ; i < size ; ++i){
- media = mediaList.get(i);
- mAdapter.add(media);
- mMediaIndex.put(media.getLocation(), i);
- if (mThumbnailer != null){
- picture = mediaDatabase.getPicture(mContext, media.getLocation());
- if (picture== null) {
- mThumbnailer.addJob(media);
- } else {
- MediaDatabase.setPicture(media, picture);
- picture = null;
- }
- } else {
- picture = AudioUtil.getCover(mContext, media, 320);
- if (picture != null){
- MediaDatabase.setPicture(media, picture);
- picture = null;
- }
- }
- }
-
- setAdapter(mAdapter);
-
- /*setOnItemSelectedListener(new OnItemSelectedListener() {
- @Override
- public void onItemSelected(Object item, Row row) {
- setTitle(((Media )item).getTitle());
- }
- });*/
-
- setOnItemClickedListener(new OnItemClickedListener() {
- @Override
- public void onItemClicked(Object item, Row row) {
- Media media = (Media) item;
- TvUtil.openMedia(getActivity(), media, null);
- }
- });
- }
-
- public void await() throws InterruptedException, BrokenBarrierException {
- mBarrier.await();
- }
-
- public void resetBarrier() {
- mBarrier.reset();
- }
- @Override
- public void setItemToUpdate(Media item) {
- mItemToUpdate = item;
- mHandler.sendEmptyMessage(VideoListHandler.UPDATE_ITEM);
- }
-
- public void updateItem() {
- mAdapter.notifyArrayItemRangeChanged(mMediaIndex.get(mItemToUpdate.getLocation()), 1);
- try {
- mBarrier.await();
- } catch (InterruptedException e) {
- } catch (BrokenBarrierException e) {}
- }
-
- @Override
- public void updateList() {
- // TODO Auto-generated method stub
- };
-
- private Handler mHandler = new VideoListHandler(this);
-
- // An item of the list: a media or a separator.
- public class ListItem {
- public String mTitle;
- public String mSubTitle;
- public ArrayList<Media> mMediaList;
- public boolean mIsSeparator;
-
- public ListItem(String title, String subTitle, Media media, boolean isSeparator) {
- mMediaList = new ArrayList<Media>();
- if (media != null)
- mMediaList.add(media);
- mTitle = title;
- mSubTitle = subTitle;
- mIsSeparator = isSeparator;
- }
- }
-
- public void add(String title, String subTitle, Media media) {
- if(title == null) return;
- title = title.trim();
- if(subTitle != null) subTitle = subTitle.trim();
- if (mMediaItemMap.containsKey(title))
- mMediaItemMap.get(title).mMediaList.add(media);
- else {
- ListItem item = new ListItem(title, subTitle, media, false);
- mMediaItemMap.put(title, item);
- mMediaItemList.add(item);
- }
- }
-}
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
deleted file mode 100644
index ee6f685..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
+++ /dev/null
@@ -1,268 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
-
-import org.videolan.libvlc.LibVLC;
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaDatabase;
-import org.videolan.vlc.MediaLibrary;
-import org.videolan.vlc.R;
-import org.videolan.vlc.Thumbnailer;
-import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
-import org.videolan.vlc.gui.video.VideoBrowserInterface;
-import org.videolan.vlc.gui.video.VideoListHandler;
-import org.videolan.vlc.util.Util;
-
-import android.app.Activity;
-import android.app.FragmentManager;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.support.v17.leanback.app.BackgroundManager;
-import android.support.v17.leanback.app.BrowseFragment;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemClickedListener;
-import android.support.v17.leanback.widget.Row;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-public class MainTvActivity extends Activity implements VideoBrowserInterface {
-
- private static final int NUM_ITEMS_PREVIEW = 5;
-
- public static final String TAG = "VLC/MainTvActivity";
-
- protected BrowseFragment mBrowseFragment;
- protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
- private MediaLibrary mMediaLibrary;
- private Thumbnailer mThumbnailer;
- private Media mItemToUpdate;
- ArrayObjectAdapter mRowsAdapter;
- ArrayObjectAdapter mVideoAdapter;
- ArrayObjectAdapter mAudioAdapter;
- ArrayObjectAdapter mCategoriesAdapter;
- HashMap<String, Integer> mVideoIndex;
- Drawable mDefaultBackground;
- Activity mContext;
-
- OnItemClickedListener mItemClickListener = new OnItemClickedListener() {
- @Override
- public void onItemClicked(Object item, Row row) {
- if (row.getId() == HEADER_CATEGORIES){
- String category = (String)item;
- Intent intent = new Intent(mContext, VerticalGridActivity.class);
- intent.putExtra(AUDIO_CATEGORY, category);
- startActivity(intent);
- } else
- TvUtil.openMedia(mContext, (Media)item, row);
- }
- };
-
- OnClickListener mSearchClickedListenernew = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(mContext, SearchActivity.class);
- startActivity(intent);
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- /*
- * skip browser and show directly Audio Player if a song is playing
- */
- if (LibVLC.getExistingInstance() != null){
- if (LibVLC.getExistingInstance().isPlaying()){
- startActivity(new Intent(this, AudioPlayerActivity.class));
- finish();
- return;
- }
- }
- mContext = this;
- setContentView(R.layout.tv_main_fragment);
-
- mMediaLibrary = MediaLibrary.getInstance();
- mDefaultBackground = getResources().getDrawable(R.drawable.background);
- final FragmentManager fragmentManager = getFragmentManager();
- mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById(
- R.id.browse_fragment);
-
- // Set display parameters for the BrowseFragment
- mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
- mBrowseFragment.setTitle(getString(R.string.app_name));
- mBrowseFragment.setBadgeDrawable(getResources().getDrawable(R.drawable.cone));
- // set search icon color
- mBrowseFragment.setSearchAffordanceColor(getResources().getColor(R.color.darkorange));
-
- // add a listener for selected items
- mBrowseFragment.setOnItemClickedListener(mItemClickListener);
-
- mBrowseFragment.setOnSearchClickedListener(mSearchClickedListenernew);
- mMediaLibrary.loadMediaItems(this, true);
- mThumbnailer = new Thumbnailer(this, getWindowManager().getDefaultDisplay());
- BackgroundManager.getInstance(this).attach(getWindow());
- }
-
- public void onResume() {
- super.onResume();
- mMediaLibrary.addUpdateHandler(mHandler);
- if (mMediaLibrary.isWorking()) {
- Util.actionScanStart();
- }
-
- /* Start the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.start(this);
- }
-
- public void onPause() {
- super.onPause();
- mMediaLibrary.removeUpdateHandler(mHandler);
-
- /* Stop the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.stop();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mThumbnailer != null)
- mThumbnailer.clearJobs();
- mBarrier.reset();
- }
-
- protected void updateBackground(Drawable drawable) {
- BackgroundManager.getInstance(this).setDrawable(drawable);
- }
-
- protected void clearBackground() {
- BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
- }
-
- public void await() throws InterruptedException, BrokenBarrierException {
- mBarrier.await();
- }
-
- public void resetBarrier() {
- mBarrier.reset();
- }
-
- public void updateList() {
- new AsyncUpdate().execute();
- }
-
- @Override
- public void setItemToUpdate(Media item) {
- mItemToUpdate = item;
- mHandler.sendEmptyMessage(VideoListHandler.UPDATE_ITEM);
- }
-
- public void updateItem() {
- mVideoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
- try {
- mBarrier.await();
- } catch (InterruptedException e) {
- } catch (BrokenBarrierException e) {}
- }
-
- private Handler mHandler = new VideoListHandler(this);
-
- public class AsyncUpdate extends AsyncTask<Void, Void, Void> {
-
- public AsyncUpdate() { }
-
- @Override
- protected void onPreExecute(){
- mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
- }
- @Override
- protected Void doInBackground(Void... params) {
- MediaDatabase mediaDatabase = MediaDatabase.getInstance();
- ArrayList<Media> videoList = mMediaLibrary.getVideoItems();
-// ArrayList<Media> audioList = mMediaLibrary.getAudioItems();
- int size;
- Media item;
- Bitmap picture;
-
- // Update video section
- if (!videoList.isEmpty()) {
- size = videoList.size();
- mVideoIndex = new HashMap<String, Integer>(size);
- mVideoAdapter = new ArrayObjectAdapter(
- new CardPresenter());
- if (NUM_ITEMS_PREVIEW < size)
- size = NUM_ITEMS_PREVIEW;
- for (int i = 0 ; i < size ; ++i) {
- item = videoList.get(i);
- picture = mediaDatabase.getPicture(mContext, item.getLocation());
-
- mVideoAdapter.add(item);
- mVideoIndex.put(item.getLocation(), i);
- if (mThumbnailer != null){
- if (picture== null) {
- mThumbnailer.addJob(item);
- } else {
- MediaDatabase.setPicture(item, picture);
- picture = null;
- }
- }
- }
- // Empty item to launch grid activity
- mVideoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
-
- HeaderItem header = new HeaderItem(HEADER_VIDEO, getString(R.string.video), null);
- mRowsAdapter.add(new ListRow(header, mVideoAdapter));
- }
-
- /*// update audio section
- if (!audioList.isEmpty()) {
- size = audioList.size();
- if (NUM_ITEMS_PREVIEW < size)
- size = NUM_ITEMS_PREVIEW;
- mAudioAdapter = new ArrayObjectAdapter(new CardPresenter());
- for (int i = 0 ; i < size ; ++i) {
- item = audioList.get(i);
- picture = AudioUtil.getCover(mContext, item, 320);
- if (picture != null){
- MediaDatabase.setPicture(item, picture);
- picture = null;
- }
- mAudioAdapter.add(item);
-
- }
- // Empty item to launch grid activity
- mAudioAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
-
- HeaderItem header = new HeaderItem(HEADER_MUSIC, getString(R.string.audio), null);
- mRowsAdapter.add(new ListRow(header, mAudioAdapter));
- }*/
-
- mCategoriesAdapter = new ArrayObjectAdapter(new CardPresenter());
- mCategoriesAdapter.add(getString(R.string.artists));
- mCategoriesAdapter.add(getString(R.string.albums));
- mCategoriesAdapter.add(getString(R.string.genres));
- mCategoriesAdapter.add(getString(R.string.songs));
- HeaderItem header = new HeaderItem(HEADER_CATEGORIES, getString(R.string.audio), null);
- mRowsAdapter.add(new ListRow(header, mCategoriesAdapter));
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- mBrowseFragment.setAdapter(mRowsAdapter);
- }
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetails.java b/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
deleted file mode 100644
index b3b0601..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class MediaItemDetails implements Parcelable {
-
- private String title, subTitle, body, location;
-
- public MediaItemDetails(String title, String subTitle, String body, String location) {
- this.title = title;
- this.subTitle = subTitle;
- this.body = body;
- this.location = location;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getSubTitle() {
- return subTitle;
- }
-
- public String getBody() {
- return body;
- }
-
- public String getLocation(){
- return location;
- }
-
- @Override
- public int describeContents() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(title);
- dest.writeString(subTitle);
- dest.writeString(body);
- dest.writeString(location);
- }
-
- public static final Parcelable.Creator<MediaItemDetails> CREATOR
- = new Parcelable.Creator<MediaItemDetails>() {
- public MediaItemDetails createFromParcel(Parcel in) {
- return new MediaItemDetails(in);
- }
-
- public MediaItemDetails[] newArray(int size) {
- return new MediaItemDetails[size];
- }
- };
-
- private MediaItemDetails(Parcel in) {
- title = in.readString();
- subTitle = in.readString();
- body = in.readString();
- location = in.readString();
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
deleted file mode 100644
index bcf087b..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import java.util.ArrayList;
-
-import org.videolan.libvlc.LibVLC;
-import org.videolan.libvlc.LibVlcException;
-import org.videolan.vlc.MediaLibrary;
-import org.videolan.vlc.R;
-import org.videolan.vlc.audio.AudioServiceController;
-import org.videolan.vlc.gui.audio.AudioPlayer;
-import org.videolan.vlc.gui.audio.AudioUtil;
-import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
-
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.support.v17.leanback.app.DetailsFragment;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.ClassPresenterSelector;
-import android.support.v17.leanback.widget.DetailsOverviewRow;
-import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnActionClickedListener;
-import android.util.Log;
-
-public class MediaItemDetailsFragment extends DetailsFragment implements AudioServiceController.AudioServiceConnectionListener {
- private static final String TAG = "MediaItemDetailsFragment";
- private static final int ID_PLAY = 1;
- private static final int ID_LISTEN = 2;
- private ArrayObjectAdapter mRowsAdapter;
- private AudioServiceController mAudioController;
- private AudioPlayer mAudioPlayer;
- private MediaItemDetails mMedia;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mAudioController = AudioServiceController.getInstance();
- buildDetails();
- }
-
- public void onResume(){
- super.onResume();
- }
-
- public void onPause(){
- super.onPause();
- if (mAudioController.isPlaying()){
- mAudioController.stop();
- mAudioController.unbindAudioService(getActivity());
- }
- }
-
- private void buildDetails() {
- Bundle extras = getActivity().getIntent().getExtras();
- mMedia = extras.getParcelable("item");
- ClassPresenterSelector selector = new ClassPresenterSelector();
- // Attach your media item details presenter to the row presenter:
- DetailsOverviewRowPresenter rowPresenter =
- new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
-
- rowPresenter.setBackgroundColor(getResources().getColor(R.color.darkorange));
- rowPresenter.setOnActionClickedListener(new OnActionClickedListener() {
-
- @Override
- public void onActionClicked(Action action) {
- if (action.getId() == ID_LISTEN){
- mAudioController.bindAudioService(getActivity(), MediaItemDetailsFragment.this);
- } else if (action.getId() == ID_PLAY){
- ArrayList<String> locations = new ArrayList<String>();
- locations.add(mMedia.getLocation());
- Intent intent = new Intent(getActivity(), AudioPlayerActivity.class);
- intent.putExtra("locations", locations);
- startActivity(intent);
- }
- }
- });
- selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
- selector.addClassPresenter(ListRow.class,
- new ListRowPresenter());
- mRowsAdapter = new ArrayObjectAdapter(selector);
-
- Resources res = getActivity().getResources();
- DetailsOverviewRow detailsOverview = new DetailsOverviewRow(mMedia);
-
- // Add images and action buttons to the details view
- Bitmap cover = AudioUtil.getCover(getActivity(), MediaLibrary.getInstance().getMediaItem(mMedia.getLocation()), 480);
- if (cover == null)
- detailsOverview.setImageDrawable(res.getDrawable(R.drawable.cone));
- else
- detailsOverview.setImageBitmap(getActivity(), cover);
- detailsOverview.addAction(new Action(ID_PLAY, "Play"));
- detailsOverview.addAction(new Action(ID_LISTEN, "Listen"));
- mRowsAdapter.add(detailsOverview);
-
- // Add a Related items row
- ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
- new StringPresenter());
- listRowAdapter.add("Media Item 1");
- listRowAdapter.add("Media Item 2");
- listRowAdapter.add("Media Item 3");
- HeaderItem header = new HeaderItem(0, "Related Items", null);
- mRowsAdapter.add(new ListRow(header, listRowAdapter));
-
- setAdapter(mRowsAdapter);
- }
-
- @Override
- public void onConnectionSuccess() {
- mAudioController.load(mMedia.getLocation(), true);
- }
-
- @Override
- public void onConnectionFailed() {}
-
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/SearchActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/SearchActivity.java
deleted file mode 100644
index be02217..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/SearchActivity.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.vlc.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class SearchActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tv_search);
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/SearchFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/SearchFragment.java
deleted file mode 100644
index e55dd64..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/SearchFragment.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaLibrary;
-import org.videolan.vlc.R;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcelable;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.ObjectAdapter;
-import android.support.v17.leanback.widget.OnItemClickedListener;
-import android.support.v17.leanback.widget.Row;
-import android.text.TextUtils;
-
-public class SearchFragment extends android.support.v17.leanback.app.SearchFragment
-implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider {
-
- private static final String TAG = "SearchFragment";
- private static final int SEARCH_DELAY_MS = 300;
-
- private ArrayObjectAdapter mRowsAdapter;
- private Handler mHandler = new Handler();
- private SearchRunnable mDelayedLoad;
- protected Activity mActivity;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
- setSearchResultProvider(this);
- setOnItemClickedListener(getDefaultItemClickedListener());
- mDelayedLoad = new SearchRunnable();
- mActivity = getActivity();
- }
-
- @Override
- public ObjectAdapter getResultsAdapter() {
- return mRowsAdapter;
- }
-
- private void queryByWords(String words) {
- mRowsAdapter.clear();
- if (!TextUtils.isEmpty(words)) {
- mDelayedLoad.setSearchQuery(words);
- mHandler.removeCallbacks(mDelayedLoad);
- mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
- }
- }
-
- @Override
- public boolean onQueryTextChange(String newQuery) {
- queryByWords(newQuery);
- return true;
- }
-
- @Override
- public boolean onQueryTextSubmit(String query) {
- queryByWords(query);
- return true;
- }
-
- private void loadRows(String query) {
- ArrayList<Media> mediaList = MediaLibrary.getInstance().getMediaItems();
- ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
- for (Media media : mediaList) {
- if (media.getTitle().toLowerCase().indexOf(query.toLowerCase()) >= 0
- || media.getLocation().toLowerCase().indexOf(query.toLowerCase()) >= 0) {
- listRowAdapter.add(media);
- }
- }
- HeaderItem header = new HeaderItem(0, getResources().getString(R.string.search_results),
- null);
- mRowsAdapter.add(new ListRow(header, listRowAdapter));
- }
-
- protected OnItemClickedListener getDefaultItemClickedListener() {
- return new OnItemClickedListener() {
- @Override
- public void onItemClicked(Object item, Row row) {
- if (item instanceof Media) {
- TvUtil.openMedia(mActivity, (Media) item, row);
- }
- }
- };
- }
-
- private class SearchRunnable implements Runnable {
-
- private volatile String searchQuery;
-
- public SearchRunnable() {}
-
- public void run() {
- loadRows(searchQuery);
- }
-
- public void setSearchQuery(String value) {
- this.searchQuery = value;
- }
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/StringPresenter.java b/vlc-android/src/org/videolan/vlc/gui/tv/StringPresenter.java
deleted file mode 100644
index 4eff8bc..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/StringPresenter.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.vlc.R;
-
-import android.support.v17.leanback.widget.Presenter;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class StringPresenter extends Presenter {
- private static final String TAG = "StringPresenter";
-
- public ViewHolder onCreateViewHolder(ViewGroup parent) {
- TextView textView = new TextView(parent.getContext());
- textView.setFocusable(true);
- textView.setFocusableInTouchMode(true);
- textView.setBackground(
- parent.getContext().getResources().getDrawable(R.drawable.background_cone));
- return new ViewHolder(textView);
- }
-
- public void onBindViewHolder(ViewHolder viewHolder, Object item) {
- ((TextView) viewHolder.view).setText(item.toString());
- }
-
- public void onUnbindViewHolder(ViewHolder viewHolder) {
- // no op
- }
-
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/TvMedia.java b/vlc-android/src/org/videolan/vlc/gui/tv/TvMedia.java
deleted file mode 100644
index cc7381b..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/TvMedia.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class TvMedia implements Parcelable {
- private long id;
- private String mediaUrl;
- private String title;
- private String description;
- private int bgImageId;
- private int cardImageId;
- private String bgImageUrl;
- private String cardImageUrl;
-
- public TvMedia(long id, String title, String description, String bgImageUrl, String cardImageUrl, String mediaUrl) {
- this.id = id;
- this.title = title;
- this.description = description;
- this.bgImageUrl = bgImageUrl;
- this.cardImageUrl = cardImageUrl;
- this.mediaUrl = mediaUrl;
- }
-
- public TvMedia(long id, String title, String description, int bgImageId, int cardImageId, String mediaUrl) {
- this.id = id;
- this.title = title;
- this.description = description;
- this.bgImageId = bgImageId;
- this.cardImageId = cardImageId;
- this.mediaUrl = mediaUrl;
- }
-
- public long getId(){
- return id;
- }
-
- public String getDescription(){
- return description;
- }
-
- public String getBgImageUrl(){
- return bgImageUrl;
- }
-
- public String getCardImageUrl(){
- return cardImageUrl;
- }
-
- public String getVideoUrl(){
- return mediaUrl;
- }
-
- public String getTitle(){
- return title;
- }
-
- public int getBackgroundImageId() {
- return bgImageId;
- }
-
-// public URI getBackgroundImageURI() {
-// try {
-// Log.d("BACK MEDIA: ", bgImageUrl);
-// return new URI(getBgImageUrl());
-// } catch (URISyntaxException e) {
-// Log.d("URI exception: ", bgImageUrl);
-// return null;
-// }
-// }
-
- public int getCardImageId() {
- return cardImageId;
- }
-
-// public URI getCardImageURI() {
-// try {
-// return new URI(getCardImageUrl());
-// } catch (URISyntaxException e) {
-// return null;
-// }
-// }
-
- @Override
- public String toString() {
- return "Movie{" +
- "id=" + id +
- ", title='" + title + '\'' +
- ", mediaUrl='" + mediaUrl + '\'' +
- ", backgroundImageId='" + bgImageId + '\'' +
-// ", backgroundImageURI='" + getBackgroundImageURI().toString() + '\'' +
- ", cardImageUrl='" + cardImageUrl + '\'' +
- '}';
- }
-
- @Override
- public int describeContents() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeString(mediaUrl);
- dest.writeString(title);
- dest.writeString(description);
- dest.writeInt(bgImageId);
- dest.writeInt(cardImageId);
- dest.writeString(bgImageUrl);
- dest.writeString(cardImageUrl);
- }
-
- public static final Parcelable.Creator<TvMedia> CREATOR
- = new Parcelable.Creator<TvMedia>() {
- public TvMedia createFromParcel(Parcel in) {
- return new TvMedia(in);
- }
-
- public TvMedia[] newArray(int size) {
- return new TvMedia[size];
- }
- };
-
- private TvMedia(Parcel in) {
- id = in.readLong();
- mediaUrl = in.readString();
- title = in.readString();
- description = in.readString();
- bgImageId = in.readInt();
- cardImageId = in.readInt();
- bgImageUrl = in.readString();
- cardImageUrl = in.readString();
- }
-
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.java b/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.java
deleted file mode 100644
index b75268c..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.gui.video.VideoPlayerActivity;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Parcelable;
-import android.support.v17.leanback.widget.Row;
-
-public class TvUtil {
-
-
- public static void openMedia(Activity activity, Media media, Row row){
- if (media.getType() == Media.TYPE_VIDEO){
- VideoPlayerActivity.start(activity, media.getLocation(), false);
- } else if (media.getType() == Media.TYPE_AUDIO){
- Intent intent = new Intent(activity,
- DetailsActivity.class);
- // pass the item information
- intent.putExtra("item", (Parcelable)new MediaItemDetails(media.getTitle(), media.getArtist(), media.getAlbum(), media.getLocation()));
- activity.startActivity(intent);
- } else if (media.getType() == Media.TYPE_GROUP){
- Intent intent = new Intent(activity, VerticalGridActivity.class);
- intent.putExtra("id", row.getId());
- activity.startActivity(intent);
- }
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
deleted file mode 100644
index 64e96f1..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.videolan.vlc.gui.tv;
-
-import org.videolan.vlc.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class VerticalGridActivity extends Activity {
-
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tv_vertical_grid);
- getWindow().setBackgroundDrawableResource(R.drawable.background);
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
deleted file mode 100644
index cd8924b..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package org.videolan.vlc.gui.tv.audioplayer;
-
-import java.util.ArrayList;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaLibrary;
-import org.videolan.vlc.R;
-import org.videolan.vlc.audio.AudioServiceController;
-import org.videolan.vlc.gui.audio.AudioUtil;
-import org.videolan.vlc.gui.tv.audioplayer.PlaylistAdapter.ViewHolder;
-import org.videolan.vlc.interfaces.IAudioPlayer;
-import org.videolan.vlc.util.AndroidDevices;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.os.Bundle;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.Adapter;
-import android.view.InputDevice;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-public class AudioPlayerActivity extends Activity implements AudioServiceController.AudioServiceConnectionListener, IAudioPlayer{
- public static final String TAG = "AudioPlayerActivity";
-
- private AudioServiceController mAudioController;
- private RecyclerView mRecyclerView;
- private Adapter<ViewHolder> mAdapter;
- private LinearLayoutManager mLayoutManager;
- private ArrayList<String> mLocations;
-
- //PAD navigation
- private static final int JOYSTICK_INPUT_DELAY = 300;
- private long mLastMove;
- private int mSelectedItem = 0;
- private int mCurrentlyPlaying;
-
- private TextView mTitleTv, mArtistTv;
- private ImageView mPlayPauseButton, mCover;
- private ProgressBar mProgressBar;
-
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.tv_audio_player);
-
- mLocations = getIntent().getStringArrayListExtra("locations");
- mRecyclerView = (RecyclerView) findViewById(R.id.playlist);
- mLayoutManager = new LinearLayoutManager(this);
- mRecyclerView.setLayoutManager(mLayoutManager);
- mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
- if (mLocations == null)
- mLocations = new ArrayList<String>();
- else {
- mAdapter = new PlaylistAdapter(mLocations);
- mRecyclerView.setAdapter(mAdapter);
- }
-
- mAudioController = AudioServiceController.getInstance();
-
- mTitleTv = (TextView)findViewById(R.id.media_title);
- mArtistTv = (TextView)findViewById(R.id.media_artist);
- mPlayPauseButton = (ImageView)findViewById(R.id.button_play);
- mProgressBar = (ProgressBar)findViewById(R.id.media_progress);
- mCover = (ImageView)findViewById(R.id.album_cover);
-
- }
-
- public void onStart(){
- super.onStart();
- mAudioController.bindAudioService(this, this);
- mAudioController.addAudioPlayer(this);
- }
-
- public void onStop(){
- super.onStop();
- mAudioController.removeAudioPlayer(this);
- mAudioController.unbindAudioService(this);
- mLocations.clear();
- }
-
- protected void onResume() {
- super.onResume();
- mRecyclerView.post(new Runnable() {
- @Override
- public void run() {
- mLayoutManager.getChildAt(mSelectedItem).setSelected(true);
- }
- });
- };
-
- @Override
- public void onConnectionSuccess() {
- ArrayList<String> medialocations = (ArrayList<String>) mAudioController.getMediaLocations();
- if (!mLocations.isEmpty() && !mLocations.equals(medialocations))
- mAudioController.load(mLocations, 0, true);
- else {
- mLocations = medialocations;
- update();
- mAdapter = new PlaylistAdapter(mLocations);
- mRecyclerView.setAdapter(mAdapter);
- }
- }
-
- @Override
- public void onConnectionFailed() {}
-
- @Override
- public void update() {
- mPlayPauseButton.setImageResource(mAudioController.isPlaying() ? R.drawable.ic_pause : R.drawable.ic_play);
- if (mAudioController.hasMedia()) {
- mTitleTv.setText(mAudioController.getTitle());
- mArtistTv.setText(mAudioController.getArtist());
- mProgressBar.setMax(mAudioController.getLength());
- Media media = MediaLibrary.getInstance().getMediaItem(mAudioController.getCurrentMediaLocation());
- Bitmap cover = AudioUtil.getCover(this, media, mCover.getWidth());
- if (cover == null)
- cover = mAudioController.getCover();
- if (cover == null)
- mCover.setImageResource(R.drawable.background_cone);
- else
- mCover.setImageBitmap(cover);
- }
- }
-
- @Override
- public void updateProgress() {
- mProgressBar.setProgress(mAudioController.getTime());
- }
-
- public boolean onKeyDown(int keyCode, KeyEvent event){
- switch (keyCode){
- /*
- * Playback control
- */
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_PLAY:
- case KeyEvent.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_SPACE:
- case KeyEvent.KEYCODE_BUTTON_A:
- togglePlayPause();
- return true;
- case KeyEvent.KEYCODE_F:
- case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
- case KeyEvent.KEYCODE_BUTTON_R1:
- goNext();
- return true;
- case KeyEvent.KEYCODE_R:
- case KeyEvent.KEYCODE_MEDIA_REWIND:
- case KeyEvent.KEYCODE_BUTTON_L1:
- goPrevious();
- return true;
- /*
- * Playlist navigation
- */
- case KeyEvent.KEYCODE_DPAD_UP:
- selectPrevious();
- return true;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- selectNext();
- return true;
- case KeyEvent.KEYCODE_BUTTON_X:
- mAudioController.playIndex(mSelectedItem);
- mCurrentlyPlaying = mSelectedItem;
- return true;
- default:
- return super.onKeyDown(keyCode, event);
- }
- }
-
- @TargetApi(12) //only active for Android 3.1+
- public boolean dispatchGenericMotionEvent(MotionEvent event){
-
- InputDevice mInputDevice = event.getDevice();
-
- float x = AndroidDevices.getCenteredAxis(event, mInputDevice,
- MotionEvent.AXIS_X);
-// float y = AndroidDevices.getCenteredAxis(event, mInputDevice,
-// MotionEvent.AXIS_Y);
-// float z = AndroidDevices.getCenteredAxis(event, mInputDevice,
-// MotionEvent.AXIS_Z);
-// float rz = AndroidDevices.getCenteredAxis(event, mInputDevice,
-// MotionEvent.AXIS_RZ);
-
- if (System.currentTimeMillis() - mLastMove > JOYSTICK_INPUT_DELAY){
- if (Math.abs(x) > 0.3){
- seek(x > 0.0f ? 10000 : -10000);
- mLastMove = System.currentTimeMillis();
- return true;
- }
- //TODO Will we change volume in app on TV ?
- /*else if (Math.abs(rz) > 0.3){
- mVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
- int delta = -(int) ((rz / 7) * mAudioMax);
- int vol = (int) Math.min(Math.max(mVol + delta, 0), mAudioMax);
- setAudioVolume(vol);
- mLastMove = System.currentTimeMillis();
- }*/
- }
- return false;
- }
-
- private void seek(int delta) {
- int time = mAudioController.getTime()+delta;
- if (time < 0 || time > mAudioController.getLength())
- return;
- mAudioController.setTime(time);
- }
-
- public void onClick(View v){
- switch (v.getId()){
- case R.id.button_play:
- togglePlayPause();
- break;
- case R.id.button_next:
- goNext();
- break;
- case R.id.button_previous:
- goPrevious();
- break;
- }
- }
-
- private void goPrevious() {
- if (mAudioController.hasPrevious()) {
- mAudioController.previous();
- selectItem(--mCurrentlyPlaying);
- }
- }
-
- private void goNext() {
- if (mAudioController.hasNext()){
- mAudioController.next();
- selectItem(++mCurrentlyPlaying);
- }
- }
-
- private void togglePlayPause() {
- if (mAudioController.isPlaying())
- mAudioController.pause();
- else if (mAudioController.hasMedia())
- mAudioController.play();
- }
-
- private void selectNext() {
- if (mSelectedItem >= mAdapter.getItemCount()-1)
- return;
- selectItem(++mSelectedItem);
- }
-
- private void selectPrevious() {
- if (mSelectedItem < 1)
- return;
- selectItem(--mSelectedItem);
- }
-
- private void selectItem(int position){
- mSelectedItem = position;
- mRecyclerView.stopScroll();
- mLayoutManager.scrollToPosition(position);
- mRecyclerView.post(new Runnable() {
- @Override
- public void run() {
- View v;
- for (int i = 0 ; i< mAdapter.getItemCount() ; ++i){
- v = mLayoutManager.findViewByPosition(i);
- if (v != null)
- v.setSelected( i == mSelectedItem);
- }
- }
- });
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java b/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
deleted file mode 100644
index a9c9520..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.videolan.vlc.gui.tv.audioplayer;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-public class DividerItemDecoration extends RecyclerView.ItemDecoration {
-
- private static final int[] ATTRS = new int[]{
- android.R.attr.listDivider
- };
-
- public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
-
- public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
-
- private Drawable mDivider;
-
- private int mOrientation;
-
- public DividerItemDecoration(Context context, int orientation) {
- final TypedArray a = context.obtainStyledAttributes(ATTRS);
- mDivider = a.getDrawable(0);
- a.recycle();
- setOrientation(orientation);
- }
-
- public void setOrientation(int orientation) {
- if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
- throw new IllegalArgumentException("invalid orientation");
- }
- mOrientation = orientation;
- }
-
- @Override
- public void onDraw(Canvas c, RecyclerView parent) {
- if (mOrientation == VERTICAL_LIST) {
- drawVertical(c, parent);
- } else {
- drawHorizontal(c, parent);
- }
- }
-
- public void drawVertical(Canvas c, RecyclerView parent) {
- final int left = parent.getPaddingLeft();
- final int right = parent.getWidth() - parent.getPaddingRight();
-
- final int childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- final View child = parent.getChildAt(i);
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
- .getLayoutParams();
- final int top = child.getBottom() + params.bottomMargin;
- final int bottom = top + mDivider.getIntrinsicHeight();
- mDivider.setBounds(left, top, right, bottom);
- mDivider.draw(c);
- }
- }
-
- public void drawHorizontal(Canvas c, RecyclerView parent) {
- final int top = parent.getPaddingTop();
- final int bottom = parent.getHeight() - parent.getPaddingBottom();
-
- final int childCount = parent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- final View child = parent.getChildAt(i);
- final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
- .getLayoutParams();
- final int left = child.getRight() + params.rightMargin;
- final int right = left + mDivider.getIntrinsicHeight();
- mDivider.setBounds(left, top, right, bottom);
- mDivider.draw(c);
- }
- }
-
- @Override
- public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
- if (mOrientation == VERTICAL_LIST) {
- outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
- } else {
- outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
- }
- }
-}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java b/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
deleted file mode 100644
index 917d4cd..0000000
--- a/vlc-android/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.videolan.vlc.gui.tv.audioplayer;
-
-import java.util.ArrayList;
-
-import org.videolan.libvlc.Media;
-import org.videolan.vlc.MediaLibrary;
-
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
- private ArrayList<String> mDataset;
- private static MediaLibrary sMediaLibrary = MediaLibrary.getInstance();
-
- public static class ViewHolder extends RecyclerView.ViewHolder {
- public TextView mTitleTv;
- public TextView mArtistTv;
- public ViewHolder(View v) {
- super(v);
- mTitleTv = (TextView) v.findViewById(android.R.id.text1);
- mTitleTv.setTextAppearance(v.getContext(), android.R.style.TextAppearance_DeviceDefault_Small);
- mArtistTv = (TextView) v.findViewById(android.R.id.text2);
- mArtistTv.setTextAppearance(v.getContext(), android.R.style.TextAppearance_DeviceDefault_Small_Inverse);
- }
- }
-
- public PlaylistAdapter(ArrayList<String> myDataset) {
- mDataset = myDataset;
- }
-
- @Override
- public PlaylistAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
- int viewType) {
- View v = LayoutInflater.from(parent.getContext())
- .inflate(android.R.layout.simple_list_item_2, parent, false);
-
- ViewHolder vh = new ViewHolder(v);
- return vh;
- }
-
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- Media media = sMediaLibrary.getMediaItem(mDataset.get(position));
- holder.mTitleTv.setText(media.getTitle());
- holder.mArtistTv.setText(media.getArtist());
- }
-
- @Override
- public int getItemCount() {
- return mDataset.size();
- }
-}
\ No newline at end of file
diff --git a/vlc-android/tv/AndroidManifest.xml b/vlc-android/tv/AndroidManifest.xml
new file mode 100644
index 0000000..8360431
--- /dev/null
+++ b/vlc-android/tv/AndroidManifest.xml
@@ -0,0 +1,419 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.videolan.vlc"
+ android:installLocation="auto"
+ android:versionCode="9999"
+ android:versionName="1.0.0-git" >
+
+ <uses-sdk
+ android:minSdkVersion="17"
+ android:targetSdkVersion="21" />
+
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_LOGS" />
+ <uses-permission android:name="android.permission.VIBRATE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <!-- Needed for audio search on TV -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <uses-feature
+ android:name="android.hardware.touchscreen"
+ android:required="false" />
+ <uses-feature
+ android:name="android.hardware.gamepad"
+ android:required="false" />
+
+ <application
+ android:name="org.videolan.vlc.VLCApplication"
+ android:debuggable="true"
+ android:hardwareAccelerated="true"
+ android:icon="@drawable/icon"
+ android:label="@string/app_name"
+ android:logo="@drawable/ic_logo_w"
+ android:theme="@style/Theme.VLC.NoTitleBar" >
+ <activity
+ android:name="org.videolan.vlc.gui.tv.MainTvActivity"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.Leanback">
+
+ <intent-filter
+ android:priority="5">
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="org.videolan.vlc.gui.tv.DetailsActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback"/>
+
+ <activity android:name="org.videolan.vlc.gui.tv.VerticalGridActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback"/>
+
+ <activity android:name="org.videolan.vlc.gui.tv.SearchActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback"/>
+
+ <activity android:name="org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity"
+ android:exported="true"
+ android:launchMode="singleInstance"
+ android:theme="@style/Theme.Leanback"/>
+
+ <activity android:name=".gui.CompatErrorActivity" />
+ <activity android:name=".gui.PreferencesActivity" />
+ <activity
+ android:name=".gui.BrowserActivity"
+ android:label="@string/mediafiles"
+ android:theme="@style/Theme.VLC.NoTitleBar" />
+ <activity android:name=".gui.DebugLogActivity" />
+ <activity
+ android:name=".gui.NativeCrashActivity"
+ android:process=":NativeCrashActivity"
+ android:stateNotNeeded="true"
+ android:theme="@style/Theme.VLC" />
+ <activity
+ android:name=".gui.video.VideoPlayerActivity"
+ android:configChanges="orientation|screenSize"
+ android:theme="@style/Theme.VLC.Player" >
+
+ <!-- This filter captures protocols without type info -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="rtmp" />
+ <data android:scheme="rtmpe" />
+ <data android:scheme="rtmps" />
+ <data android:scheme="rtp" />
+ <data android:scheme="rtsp" />
+ <data android:scheme="mms" />
+ <data android:scheme="mmsh" />
+ <data android:scheme="icyx" />
+ <data android:scheme="httplive" />
+ <data android:scheme="udp" />
+ <data android:scheme="vlc" />
+ </intent-filter>
+ <!-- This filter captures protocols with type info -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:mimeType="video/*" />
+ <data android:mimeType="audio/*" />
+ <data android:scheme="rtmp" />
+ <data android:scheme="rtmpe" />
+ <data android:scheme="rtmps" />
+ <data android:scheme="rtp" />
+ <data android:scheme="rtsp" />
+ <data android:scheme="mms" />
+ <data android:scheme="mmsh" />
+ <data android:scheme="icyx" />
+ <data android:scheme="httplive" />
+ <data android:scheme="udp" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="" />
+ <data android:scheme="file" />
+ <data android:scheme="ftp" />
+ <data android:scheme="content" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:mimeType="video/*" />
+ <data android:mimeType="audio/*" />
+ <data android:mimeType="*/rmvb" />
+ <data android:mimeType="*/avi" />
+ <data android:mimeType="*/mkv" />
+ <data android:mimeType="application/3gpp*" />
+ <data android:mimeType="application/mp4" />
+ <data android:mimeType="application/mpeg*" />
+ <data android:mimeType="application/ogg" />
+ <data android:mimeType="application/sdp" />
+ <data android:mimeType="application/vnd.3gp*" />
+ <data android:mimeType="application/vnd.apple.mpegurl" />
+ <data android:mimeType="application/vnd.dvd*" />
+ <data android:mimeType="application/vnd.dolby*" />
+ <data android:mimeType="application/vnd.rn-realmedia*" />
+ <data android:mimeType="application/x-iso9660-image" />
+ <data android:mimeType="application/x-extension-mp4" />
+ <data android:mimeType="application/x-flac" />
+ <data android:mimeType="application/x-matroska" />
+ <data android:mimeType="application/x-mpegURL" />
+ <data android:mimeType="application/x-ogg" />
+ <data android:mimeType="application/x-quicktimeplayer" />
+ <data android:mimeType="application/x-shockwave-flash" />
+ <data android:mimeType="application/xspf+xml" />
+ <data android:mimeType="misc/ultravox" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+
+ <data android:scheme="" />
+ <data android:scheme="file" />
+ <data android:scheme="ftp" />
+ <data android:scheme="content" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="*" />
+
+ <!-- video -->
+
+ <data android:pathPattern=".*\\.3g2" />
+ <data android:pathPattern=".*\\.3gp" />
+ <data android:pathPattern=".*\\.3gp2" />
+ <data android:pathPattern=".*\\.3gpp" />
+ <data android:pathPattern=".*\\.amv" />
+ <data android:pathPattern=".*\\.asf" />
+ <data android:pathPattern=".*\\.avi" />
+ <data android:pathPattern=".*\\.divx" />
+ <data android:pathPattern=".*\\.drc" />
+ <data android:pathPattern=".*\\.dv" />
+ <data android:pathPattern=".*\\.f4v" />
+ <data android:pathPattern=".*\\.flv" />
+ <data android:pathPattern=".*\\.gvi" />
+ <data android:pathPattern=".*\\.gxf" />
+ <data android:pathPattern=".*\\.ismv" />
+ <data android:pathPattern=".*\\.iso" />
+ <data android:pathPattern=".*\\.m1v" />
+ <data android:pathPattern=".*\\.m2v" />
+ <data android:pathPattern=".*\\.m2t" />
+ <data android:pathPattern=".*\\.m2ts" />
+ <!-- <data android:pathPattern=".*\\.m3u" /> -->
+ <data android:pathPattern=".*\\.m3u8" />
+ <data android:pathPattern=".*\\.mkv" />
+ <data android:pathPattern=".*\\.mov" />
+ <data android:pathPattern=".*\\.mp2" />
+ <data android:pathPattern=".*\\.mp2v" />
+ <data android:pathPattern=".*\\.mp4" />
+ <data android:pathPattern=".*\\.mp4v" />
+ <data android:pathPattern=".*\\.mpe" />
+ <data android:pathPattern=".*\\.mpeg" />
+ <data android:pathPattern=".*\\.mpeg1" />
+ <data android:pathPattern=".*\\.mpeg2" />
+ <data android:pathPattern=".*\\.mpeg4" />
+ <data android:pathPattern=".*\\.mpg" />
+ <data android:pathPattern=".*\\.mpv2" />
+ <data android:pathPattern=".*\\.mts" />
+ <data android:pathPattern=".*\\.mtv" />
+ <data android:pathPattern=".*\\.mxf" />
+ <data android:pathPattern=".*\\.mxg" />
+ <data android:pathPattern=".*\\.nsv" />
+ <data android:pathPattern=".*\\.nut" />
+ <data android:pathPattern=".*\\.nuv" />
+ <data android:pathPattern=".*\\.ogm" />
+ <data android:pathPattern=".*\\.ogv" />
+ <data android:pathPattern=".*\\.ogx" />
+ <data android:pathPattern=".*\\.ps" />
+ <data android:pathPattern=".*\\.rec" />
+ <data android:pathPattern=".*\\.rm" />
+ <data android:pathPattern=".*\\.rmvb" />
+ <data android:pathPattern=".*\\.tod" />
+ <data android:pathPattern=".*\\.ts" />
+ <data android:pathPattern=".*\\.tts" />
+ <data android:pathPattern=".*\\.vob" />
+ <data android:pathPattern=".*\\.vro" />
+ <data android:pathPattern=".*\\.webm" />
+ <data android:pathPattern=".*\\.wm" />
+ <data android:pathPattern=".*\\.wmv" />
+ <data android:pathPattern=".*\\.wtv" />
+ <data android:pathPattern=".*\\.xesc" />
+ <data android:pathPattern=".*\\.3G2" />
+ <data android:pathPattern=".*\\.3GP" />
+ <data android:pathPattern=".*\\.3GP2" />
+ <data android:pathPattern=".*\\.3GPP" />
+ <data android:pathPattern=".*\\.AMV" />
+ <data android:pathPattern=".*\\.ASF" />
+ <data android:pathPattern=".*\\.AVI" />
+ <data android:pathPattern=".*\\.DIVX" />
+ <data android:pathPattern=".*\\.DRC" />
+ <data android:pathPattern=".*\\.DV" />
+ <data android:pathPattern=".*\\.F4V" />
+ <data android:pathPattern=".*\\.FLV" />
+ <data android:pathPattern=".*\\.GVI" />
+ <data android:pathPattern=".*\\.GXF" />
+ <data android:pathPattern=".*\\.ISMV" />
+ <data android:pathPattern=".*\\.ISO" />
+ <data android:pathPattern=".*\\.M1V" />
+ <data android:pathPattern=".*\\.M2V" />
+ <data android:pathPattern=".*\\.M2T" />
+ <data android:pathPattern=".*\\.M2TS" />
+ <!-- <data android:pathPattern=".*\\.M3U" /> -->
+ <data android:pathPattern=".*\\.M3U8" />
+ <data android:pathPattern=".*\\.MKV" />
+ <data android:pathPattern=".*\\.MOV" />
+ <data android:pathPattern=".*\\.MP2" />
+ <data android:pathPattern=".*\\.MP2V" />
+ <data android:pathPattern=".*\\.MP4" />
+ <data android:pathPattern=".*\\.MP4V" />
+ <data android:pathPattern=".*\\.MPE" />
+ <data android:pathPattern=".*\\.MPEG" />
+ <data android:pathPattern=".*\\.MPEG1" />
+ <data android:pathPattern=".*\\.MPEG2" />
+ <data android:pathPattern=".*\\.MPEG4" />
+ <data android:pathPattern=".*\\.MPG" />
+ <data android:pathPattern=".*\\.MPV2" />
+ <data android:pathPattern=".*\\.MTS" />
+ <data android:pathPattern=".*\\.MTV" />
+ <data android:pathPattern=".*\\.MXF" />
+ <data android:pathPattern=".*\\.MXG" />
+ <data android:pathPattern=".*\\.NSV" />
+ <data android:pathPattern=".*\\.NUT" />
+ <data android:pathPattern=".*\\.NUV" />
+ <data android:pathPattern=".*\\.OGM" />
+ <data android:pathPattern=".*\\.OGV" />
+ <data android:pathPattern=".*\\.OGX" />
+ <data android:pathPattern=".*\\.PS" />
+ <data android:pathPattern=".*\\.REC" />
+ <data android:pathPattern=".*\\.RM" />
+ <data android:pathPattern=".*\\.RMVB" />
+ <data android:pathPattern=".*\\.TOD" />
+ <data android:pathPattern=".*\\.TS" />
+ <data android:pathPattern=".*\\.TTS" />
+ <data android:pathPattern=".*\\.VOB" />
+ <data android:pathPattern=".*\\.VRO" />
+ <data android:pathPattern=".*\\.WEBM" />
+ <data android:pathPattern=".*\\.WM" />
+ <data android:pathPattern=".*\\.WMV" />
+ <data android:pathPattern=".*\\.WTV" />
+ <data android:pathPattern=".*\\.XESC" />
+
+ <!-- audio -->
+
+ <data android:pathPattern=".*\\.3ga" />
+ <data android:pathPattern=".*\\.a52" />
+ <data android:pathPattern=".*\\.aac" />
+ <data android:pathPattern=".*\\.ac3" />
+ <data android:pathPattern=".*\\.adt" />
+ <data android:pathPattern=".*\\.adts" />
+ <data android:pathPattern=".*\\.aif" />
+ <data android:pathPattern=".*\\.aifc" />
+ <data android:pathPattern=".*\\.aiff" />
+ <data android:pathPattern=".*\\.amr" />
+ <data android:pathPattern=".*\\.aob" />
+ <data android:pathPattern=".*\\.ape" />
+ <data android:pathPattern=".*\\.awb" />
+ <data android:pathPattern=".*\\.caf" />
+ <data android:pathPattern=".*\\.dts" />
+ <data android:pathPattern=".*\\.flac" />
+ <data android:pathPattern=".*\\.it" />
+ <data android:pathPattern=".*\\.m4a" />
+ <data android:pathPattern=".*\\.m4b" />
+ <data android:pathPattern=".*\\.m4p" />
+ <data android:pathPattern=".*\\.mid" />
+ <data android:pathPattern=".*\\.mka" />
+ <data android:pathPattern=".*\\.mlp" />
+ <data android:pathPattern=".*\\.mod" />
+ <data android:pathPattern=".*\\.mpa" />
+ <data android:pathPattern=".*\\.mp1" />
+ <data android:pathPattern=".*\\.mp2" />
+ <data android:pathPattern=".*\\.mp3" />
+ <data android:pathPattern=".*\\.mpc" />
+ <data android:pathPattern=".*\\.mpga" />
+ <data android:pathPattern=".*\\.oga" />
+ <data android:pathPattern=".*\\.ogg" />
+ <data android:pathPattern=".*\\.oma" />
+ <data android:pathPattern=".*\\.opus" />
+ <data android:pathPattern=".*\\.ra" />
+ <data android:pathPattern=".*\\.ram" />
+ <data android:pathPattern=".*\\.rmi" />
+ <data android:pathPattern=".*\\.s3m" />
+ <data android:pathPattern=".*\\.spx" />
+ <data android:pathPattern=".*\\.tta" />
+ <data android:pathPattern=".*\\.voc" />
+ <data android:pathPattern=".*\\.vqf" />
+ <data android:pathPattern=".*\\.w64" />
+ <data android:pathPattern=".*\\.wav" />
+ <data android:pathPattern=".*\\.wma" />
+ <data android:pathPattern=".*\\.wv" />
+ <data android:pathPattern=".*\\.xa" />
+ <data android:pathPattern=".*\\.xm" />
+ <data android:pathPattern=".*\\.3GA" />
+ <data android:pathPattern=".*\\.A52" />
+ <data android:pathPattern=".*\\.AAC" />
+ <data android:pathPattern=".*\\.AC3" />
+ <data android:pathPattern=".*\\.ADT" />
+ <data android:pathPattern=".*\\.ADTS" />
+ <data android:pathPattern=".*\\.AIF" />
+ <data android:pathPattern=".*\\.AIFC" />
+ <data android:pathPattern=".*\\.AIFF" />
+ <data android:pathPattern=".*\\.AMR" />
+ <data android:pathPattern=".*\\.AOB" />
+ <data android:pathPattern=".*\\.APE" />
+ <data android:pathPattern=".*\\.AWB" />
+ <data android:pathPattern=".*\\.CAF" />
+ <data android:pathPattern=".*\\.DTS" />
+ <data android:pathPattern=".*\\.FLAC" />
+ <data android:pathPattern=".*\\.IT" />
+ <data android:pathPattern=".*\\.M4A" />
+ <data android:pathPattern=".*\\.M4B" />
+ <data android:pathPattern=".*\\.M4P" />
+ <data android:pathPattern=".*\\.MID" />
+ <data android:pathPattern=".*\\.MKA" />
+ <data android:pathPattern=".*\\.MLP" />
+ <data android:pathPattern=".*\\.MOD" />
+ <data android:pathPattern=".*\\.MPA" />
+ <data android:pathPattern=".*\\.MP1" />
+ <data android:pathPattern=".*\\.MP2" />
+ <data android:pathPattern=".*\\.MP3" />
+ <data android:pathPattern=".*\\.MPC" />
+ <data android:pathPattern=".*\\.MPGA" />
+ <data android:pathPattern=".*\\.OGA" />
+ <data android:pathPattern=".*\\.OGG" />
+ <data android:pathPattern=".*\\.OMA" />
+ <data android:pathPattern=".*\\.OPUS" />
+ <data android:pathPattern=".*\\.RA" />
+ <data android:pathPattern=".*\\.RAM" />
+ <data android:pathPattern=".*\\.RMI" />
+ <data android:pathPattern=".*\\.S3M" />
+ <data android:pathPattern=".*\\.SPX" />
+ <data android:pathPattern=".*\\.TTA" />
+ <data android:pathPattern=".*\\.VOC" />
+ <data android:pathPattern=".*\\.VQF" />
+ <data android:pathPattern=".*\\.W64" />
+ <data android:pathPattern=".*\\.WAV" />
+ <data android:pathPattern=".*\\.WMA" />
+ <data android:pathPattern=".*\\.WV" />
+ <data android:pathPattern=".*\\.XA" />
+ <data android:pathPattern=".*\\.XM" />
+ </intent-filter>
+ </activity>
+
+ <service android:name="org.videolan.vlc.audio.AudioService" />
+
+ <receiver android:name=".PhoneStateReceiver" >
+ <intent-filter>
+ <action android:name="android.intent.action.PHONE_STATE" />
+ </intent-filter>
+ </receiver>
+ <receiver
+ android:name=".widget.VLCAppWidgetProvider"
+ android:exported="false"
+ android:label="VLC mini player" >
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.appwidget.provider"
+ android:resource="@xml/vlcwidget" />
+ </receiver>
+ </application>
+
+</manifest>
diff --git a/vlc-android/tv/res/layout/tv_audio_player.xml b/vlc-android/tv/res/layout/tv_audio_player.xml
new file mode 100644
index 0000000..1ec9e5e
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_audio_player.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:weightSum="3" >
+
+ <!-- Cover -->
+ <ImageView
+ android:id="@+id/album_cover"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="2"
+ android:padding="10dp"
+ android:src="@drawable/background_cone"
+ android:scaleType="fitXY" >
+ </ImageView>
+
+ <!-- Playlist -->
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/playlist"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:scrollbars="vertical" />
+ </LinearLayout>
+
+ <!-- Media HUD -->
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentBottom="true"
+ android:paddingRight="30dip"
+ android:paddingLeft="30dip"
+ android:paddingTop="10dip"
+ android:paddingBottom="5dip"
+ android:alpha="0.8"
+ android:background="@android:color/black">
+ <TextView
+ android:id="@+id/media_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Title"/>
+ <TextView
+ android:id="@+id/media_artist"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/media_title"
+ android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Subtitle"/>
+ <ProgressBar
+ android:id="@+id/media_progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/media_artist"
+ android:layout_alignStart="@+id/media_controls"
+ android:layout_alignEnd="@+id/media_controls"
+ android:indeterminate="false"/>
+ <!-- Media control buttons -->
+ <LinearLayout
+ android:id="@+id/media_controls"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/media_progress">
+ <ImageView
+ android:id="@+id/button_previous"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_previous"
+ android:clickable="true"
+ android:onClick="onClick"/>
+ <ImageView
+ android:id="@+id/button_play"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="10dp"
+ android:layout_marginRight="10dp"
+ android:src="@drawable/ic_play"
+ android:clickable="true"
+ android:onClick="onClick"/>
+ <ImageView
+ android:id="@+id/button_next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_next"
+ android:clickable="true"
+ android:onClick="onClick"/>
+ </LinearLayout>
+ </RelativeLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/vlc-android/tv/res/layout/tv_details.xml b/vlc-android/tv/res/layout/tv_details.xml
new file mode 100644
index 0000000..f000fbe
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_details.xml
@@ -0,0 +1,6 @@
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="org.videolan.vlc.gui.tv.MediaItemDetailsFragment"
+ android:id="@+id/details_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
\ No newline at end of file
diff --git a/vlc-android/tv/res/layout/tv_main.xml b/vlc-android/tv/res/layout/tv_main.xml
new file mode 100644
index 0000000..4568719
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_main.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="org.videolan.vlc.gui.tv.MainFragment"
+ android:id="@+id/main_browse_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
diff --git a/vlc-android/tv/res/layout/tv_main_fragment.xml b/vlc-android/tv/res/layout/tv_main_fragment.xml
new file mode 100644
index 0000000..c220b43
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_main_fragment.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="android.support.v17.leanback.app.BrowseFragment"
+ android:id="@+id/browse_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
\ No newline at end of file
diff --git a/vlc-android/tv/res/layout/tv_search b/vlc-android/tv/res/layout/tv_search
new file mode 100644
index 0000000..c324a89
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_search
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="org.videolan.vlc.gui.tv.SearchFragment"
+ android:id="@+id/search_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
\ No newline at end of file
diff --git a/vlc-android/tv/res/layout/tv_vertical_grid b/vlc-android/tv/res/layout/tv_vertical_grid
new file mode 100644
index 0000000..7d58289
--- /dev/null
+++ b/vlc-android/tv/res/layout/tv_vertical_grid
@@ -0,0 +1,6 @@
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="org.videolan.vlc.gui.tv.GridFragment"
+ android:id="@+id/vertical_grid_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
\ No newline at end of file
diff --git a/vlc-android/tv/res/values/dimens.xml b/vlc-android/tv/res/values/dimens.xml
new file mode 100644
index 0000000..5c07160
--- /dev/null
+++ b/vlc-android/tv/res/values/dimens.xml
@@ -0,0 +1,4 @@
+<resources>
+ <dimen name="tv_card_width">192dp</dimen>
+ <dimen name="tv_card_height">108dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/vlc-android/tv/res/values/strings.xml b/vlc-android/tv/res/values/strings.xml
new file mode 100644
index 0000000..ea277b6
--- /dev/null
+++ b/vlc-android/tv/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+ <string name="search_results">Search results</string>
+</resources>
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/CardPresenter.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/CardPresenter.java
new file mode 100644
index 0000000..a070433
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/CardPresenter.java
@@ -0,0 +1,106 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.v17.leanback.widget.ImageCardView;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CardPresenter extends Presenter {
+
+ private static final String TAG = "CardPresenter";
+
+ private static Context sContext;
+ private static int CARD_WIDTH = 0;
+ private static int CARD_HEIGHT = 0;
+ private static Resources sResources;
+ private static MediaDatabase sMediaDatabase = MediaDatabase.getInstance();
+ private static Drawable sDefaultCardImage;
+
+ static class ViewHolder extends Presenter.ViewHolder {
+ private ImageCardView mCardView;
+
+ public ViewHolder(View view) {
+ super(view);
+ mCardView = (ImageCardView) view;
+ }
+
+ public ImageCardView getCardView() {
+ return mCardView;
+ }
+
+ protected void updateCardViewImage(String mediaLocation) {
+ Bitmap picture = sMediaDatabase.getPicture(sContext, mediaLocation);
+ if (picture.getByteCount() > 4)
+ mCardView.setMainImage(new BitmapDrawable(sResources, picture));
+ else
+ updateCardViewImage(sDefaultCardImage);
+ }
+
+ protected void updateCardViewImage(Drawable image) {
+ mCardView.setMainImage(image);
+ }
+ }
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ sContext = parent.getContext();
+ sResources = sContext.getResources();
+ sDefaultCardImage = sContext.getResources().getDrawable(R.drawable.cone);
+ if (CARD_WIDTH == 0) {
+ CARD_WIDTH = sResources.getDimensionPixelSize(
+ R.dimen.tv_card_width);
+ CARD_HEIGHT = sResources.getDimensionPixelSize(
+ R.dimen.tv_card_height);
+ }
+
+ ImageCardView cardView = new ImageCardView(sContext);
+ cardView.setFocusable(true);
+ cardView.setFocusableInTouchMode(true);
+ cardView.setBackgroundColor(sContext.getResources().getColor(R.color.lb_details_overview_bg_color));
+ return new ViewHolder(cardView);
+ }
+
+ @Override
+ public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
+ ((ViewHolder) viewHolder).mCardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
+ if (item instanceof Media) {
+ Media media = (Media) item;
+ ((ViewHolder) viewHolder).mCardView.setTitleText(media.getTitle());
+ ((ViewHolder) viewHolder).mCardView.setContentText(media.getDescription());
+ if (media.isPictureParsed())
+ ((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
+ else
+ ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+ } else if (item instanceof GridFragment.ListItem) {
+ GridFragment.ListItem listItem = (GridFragment.ListItem) item;
+ Media media = listItem.mMediaList.get(0);
+ ((ViewHolder) viewHolder).mCardView.setTitleText(listItem.mTitle);
+ ((ViewHolder) viewHolder).mCardView.setContentText(listItem.mSubTitle);
+ if (media.isPictureParsed())
+ ((ViewHolder) viewHolder).updateCardViewImage(media.getLocation());
+ else
+ ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+ } else if (item instanceof String){
+ ((ViewHolder) viewHolder).mCardView.setTitleText((String) item);
+ ((ViewHolder) viewHolder).updateCardViewImage(sDefaultCardImage);
+ }
+ }
+
+ @Override
+ public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
+ }
+
+ @Override
+ public void onViewAttachedToWindow(Presenter.ViewHolder viewHolder) {
+ // TODO?
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsActivity.java
new file mode 100644
index 0000000..9b4bc1d
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsActivity.java
@@ -0,0 +1,14 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.vlc.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class DetailsActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_details);
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
new file mode 100644
index 0000000..79292ab
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/DetailsDescriptionPresenter.java
@@ -0,0 +1,24 @@
+package org.videolan.vlc.gui.tv;
+
+import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
+import android.util.Log;
+
+public class DetailsDescriptionPresenter extends
+ AbstractDetailsDescriptionPresenter {
+ public static final String TAG ="DetailsDescriptionPresenter";
+
+ protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
+ Log.d(TAG, "itemData "+itemData);
+ MediaItemDetails details = (MediaItemDetails) itemData;
+ // In a production app, the itemData object contains the information
+ // needed to display details for the media item:
+ // viewHolder.getTitle().setText(details.getShortTitle());
+
+ // Here we provide static data for testing purposes:
+ viewHolder.getTitle().setText(details.getTitle());
+ viewHolder.getSubtitle().setText(details.getSubTitle());
+ viewHolder.getBody().setText(details.getBody());
+ }
+
+
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
new file mode 100644
index 0000000..de120d8
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
@@ -0,0 +1,319 @@
+package org.videolan.vlc.gui.tv;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.Thumbnailer;
+import org.videolan.vlc.gui.audio.AudioUtil;
+import org.videolan.vlc.gui.audio.MediaComparators;
+import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
+import org.videolan.vlc.gui.video.VideoBrowserInterface;
+import org.videolan.vlc.gui.video.VideoListHandler;
+import org.videolan.vlc.util.Util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v17.leanback.app.VerticalGridFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.VerticalGridPresenter;
+
+public class GridFragment extends VerticalGridFragment implements VideoBrowserInterface {
+ private static final String TAG = "VLC/GridFragment";
+
+ private static final int NUM_COLUMNS = 5;
+
+ protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
+ protected Media mItemToUpdate;
+ private Map<String, ListItem> mMediaItemMap;
+ private ArrayList<ListItem> mMediaItemList;
+ private ArrayObjectAdapter mAdapter;
+ private MediaLibrary mMediaLibrary;
+ private Thumbnailer mThumbnailer;
+ HashMap<String, Integer> mMediaIndex;
+ Context mContext;
+ String mCategory, mFilter;
+ long mType = -1;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = getActivity();
+ if (savedInstanceState != null){
+ mType = savedInstanceState.getLong(MEDIA_SECTION);
+ mCategory = savedInstanceState.getString(AUDIO_CATEGORY);
+ mFilter = savedInstanceState.getString(AUDIO_FILTER);
+ } else {
+ mType = getActivity().getIntent().getLongExtra(MEDIA_SECTION, -1);
+ mCategory = getActivity().getIntent().getStringExtra(AUDIO_CATEGORY);
+ mFilter = getActivity().getIntent().getStringExtra(AUDIO_FILTER);
+ }
+
+
+ mMediaLibrary = MediaLibrary.getInstance();
+
+ if (mType == HEADER_VIDEO) {
+ mThumbnailer = new Thumbnailer(mContext, getActivity().getWindowManager().getDefaultDisplay());
+ setupFragment();
+ } else if (mType == HEADER_MUSIC) {
+ setupFragment();
+ } else {
+ setupFragmentForAudio();
+ }
+ }
+
+ public void onResume() {
+ super.onResume();
+ if (mMediaLibrary.isWorking()) {
+ Util.actionScanStart();
+ }
+
+ /* Start the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.start(this);
+ }
+
+ public void onPause() {
+ super.onPause();
+ mMediaLibrary.removeUpdateHandler(mHandler);
+
+ /* Stop the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.stop();
+ }
+
+ public void onSaveInstanceState(Bundle outState){
+ super.onSaveInstanceState(outState);
+ outState.putLong(MEDIA_SECTION, mType);
+ outState.putString(AUDIO_CATEGORY, mCategory);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mThumbnailer != null)
+ mThumbnailer.clearJobs();
+ mBarrier.reset();
+ }
+
+ private void setupFragmentForAudio() {
+ Bitmap picture;
+ String title;
+ mMediaItemMap = new HashMap<String, ListItem>();
+ mMediaItemList = new ArrayList<GridFragment.ListItem>();
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+ mAdapter = new ArrayObjectAdapter(new CardPresenter());
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+
+ List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
+ if (getString(R.string.artists).equals(mCategory)){
+ Collections.sort(audioList, MediaComparators.byArtist);
+ title = getString(R.string.artists);
+ for (Media media : audioList){
+ add(media.getArtist(), null, media);
+ }
+ } else if (getString(R.string.albums).equals(mCategory)){
+ title = getString(R.string.albums);
+ Collections.sort(audioList, MediaComparators.byAlbum);
+ for (Media media : audioList){
+ if (mFilter == null
+ || (mType == FILTER_ARTIST && mFilter.equals(media.getArtist().trim()))
+ || (mType == FILTER_GENRE && mFilter.equals(media.getGenre().trim()))) {
+ add(media.getAlbum(), media.getArtist(), media);
+ }
+ }
+ //Customize title for artist/genre browsing
+ if (mType == FILTER_ARTIST){
+ title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getArtist();
+ } else if (mType == FILTER_GENRE){
+ title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getGenre();
+ }
+ } else if (getString(R.string.genres).equals(mCategory)){
+ title = getString(R.string.genres);
+ Collections.sort(audioList, MediaComparators.byGenre);
+ for (Media media : audioList){
+ add(media.getGenre(), null, media);
+ }
+ } else if (getString(R.string.songs).equals(mCategory)){
+ title = getString(R.string.songs);
+ Collections.sort(audioList, MediaComparators.byName);
+ for (Media media : audioList){
+ add(media.getTitle(), media.getArtist(), media);
+ }
+ } else {
+ title = getString(R.string.app_name_full);
+ }
+ setTitle(title);
+ //check for pictures
+ for (Media media : audioList){
+ picture = AudioUtil.getCover(mContext, media, 320);
+ if (picture != null){
+ MediaDatabase.setPicture(media, picture);
+ picture = null;
+ }
+ }
+ mAdapter.addAll(0, mMediaItemList);
+ setAdapter(mAdapter);
+
+ setOnItemClickedListener(new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ ListItem listItem = (ListItem) item;
+ Intent intent;
+ if (getString(R.string.artists).equals(mCategory)){
+ intent = new Intent(mContext, VerticalGridActivity.class);
+ intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+ intent.putExtra(MEDIA_SECTION, FILTER_ARTIST);
+ intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getArtist().trim());
+ } else if (getString(R.string.genres).equals(mCategory)){
+ intent = new Intent(mContext, VerticalGridActivity.class);
+ intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+ intent.putExtra(MEDIA_SECTION, FILTER_GENRE);
+ intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getGenre().trim());
+ } else {
+ ArrayList<String> locations = new ArrayList<String>();
+ for (Media media : listItem.mMediaList){
+ locations.add(media.getLocation());
+ }
+ intent = new Intent(mContext, AudioPlayerActivity.class);
+ intent.putExtra("locations", locations);
+ }
+ startActivity(intent);
+ }
+ });
+ }
+
+ //TODO shrink audio part, I keep it for now just in case...
+ private void setupFragment() {
+ setTitle(getString(R.string.app_name_full));
+ int size;
+ Media media;
+ Bitmap picture;
+
+ MediaDatabase mediaDatabase = MediaDatabase.getInstance();
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+ mAdapter = new ArrayObjectAdapter(new CardPresenter());
+
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+
+
+ ArrayList<Media> mediaList = null;
+ if (mType == HEADER_VIDEO)
+ mediaList = mMediaLibrary.getVideoItems();
+ else if (mType == HEADER_MUSIC)
+ mediaList = mMediaLibrary.getAudioItems();
+ size = mediaList == null ? 0 : mediaList.size();
+ mMediaIndex = new HashMap<String, Integer>(size);
+
+ for (int i = 0 ; i < size ; ++i){
+ media = mediaList.get(i);
+ mAdapter.add(media);
+ mMediaIndex.put(media.getLocation(), i);
+ if (mThumbnailer != null){
+ picture = mediaDatabase.getPicture(mContext, media.getLocation());
+ if (picture== null) {
+ mThumbnailer.addJob(media);
+ } else {
+ MediaDatabase.setPicture(media, picture);
+ picture = null;
+ }
+ } else {
+ picture = AudioUtil.getCover(mContext, media, 320);
+ if (picture != null){
+ MediaDatabase.setPicture(media, picture);
+ picture = null;
+ }
+ }
+ }
+
+ setAdapter(mAdapter);
+
+ /*setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(Object item, Row row) {
+ setTitle(((Media )item).getTitle());
+ }
+ });*/
+
+ setOnItemClickedListener(new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ Media media = (Media) item;
+ TvUtil.openMedia(getActivity(), media, null);
+ }
+ });
+ }
+
+ public void await() throws InterruptedException, BrokenBarrierException {
+ mBarrier.await();
+ }
+
+ public void resetBarrier() {
+ mBarrier.reset();
+ }
+ @Override
+ public void setItemToUpdate(Media item) {
+ mItemToUpdate = item;
+ mHandler.sendEmptyMessage(VideoListHandler.UPDATE_ITEM);
+ }
+
+ public void updateItem() {
+ mAdapter.notifyArrayItemRangeChanged(mMediaIndex.get(mItemToUpdate.getLocation()), 1);
+ try {
+ mBarrier.await();
+ } catch (InterruptedException e) {
+ } catch (BrokenBarrierException e) {}
+ }
+
+ @Override
+ public void updateList() {
+ // TODO Auto-generated method stub
+ };
+
+ private Handler mHandler = new VideoListHandler(this);
+
+ // An item of the list: a media or a separator.
+ public class ListItem {
+ public String mTitle;
+ public String mSubTitle;
+ public ArrayList<Media> mMediaList;
+ public boolean mIsSeparator;
+
+ public ListItem(String title, String subTitle, Media media, boolean isSeparator) {
+ mMediaList = new ArrayList<Media>();
+ if (media != null)
+ mMediaList.add(media);
+ mTitle = title;
+ mSubTitle = subTitle;
+ mIsSeparator = isSeparator;
+ }
+ }
+
+ public void add(String title, String subTitle, Media media) {
+ if(title == null) return;
+ title = title.trim();
+ if(subTitle != null) subTitle = subTitle.trim();
+ if (mMediaItemMap.containsKey(title))
+ mMediaItemMap.get(title).mMediaList.add(media);
+ else {
+ ListItem item = new ListItem(title, subTitle, media, false);
+ mMediaItemMap.put(title, item);
+ mMediaItemList.add(item);
+ }
+ }
+}
\ No newline at end of file
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
new file mode 100644
index 0000000..ee6f685
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
@@ -0,0 +1,268 @@
+package org.videolan.vlc.gui.tv;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import org.videolan.libvlc.LibVLC;
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.Thumbnailer;
+import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
+import org.videolan.vlc.gui.video.VideoBrowserInterface;
+import org.videolan.vlc.gui.video.VideoListHandler;
+import org.videolan.vlc.util.Util;
+
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcelable;
+import android.support.v17.leanback.app.BackgroundManager;
+import android.support.v17.leanback.app.BrowseFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.Row;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+public class MainTvActivity extends Activity implements VideoBrowserInterface {
+
+ private static final int NUM_ITEMS_PREVIEW = 5;
+
+ public static final String TAG = "VLC/MainTvActivity";
+
+ protected BrowseFragment mBrowseFragment;
+ protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
+ private MediaLibrary mMediaLibrary;
+ private Thumbnailer mThumbnailer;
+ private Media mItemToUpdate;
+ ArrayObjectAdapter mRowsAdapter;
+ ArrayObjectAdapter mVideoAdapter;
+ ArrayObjectAdapter mAudioAdapter;
+ ArrayObjectAdapter mCategoriesAdapter;
+ HashMap<String, Integer> mVideoIndex;
+ Drawable mDefaultBackground;
+ Activity mContext;
+
+ OnItemClickedListener mItemClickListener = new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ if (row.getId() == HEADER_CATEGORIES){
+ String category = (String)item;
+ Intent intent = new Intent(mContext, VerticalGridActivity.class);
+ intent.putExtra(AUDIO_CATEGORY, category);
+ startActivity(intent);
+ } else
+ TvUtil.openMedia(mContext, (Media)item, row);
+ }
+ };
+
+ OnClickListener mSearchClickedListenernew = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(mContext, SearchActivity.class);
+ startActivity(intent);
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ /*
+ * skip browser and show directly Audio Player if a song is playing
+ */
+ if (LibVLC.getExistingInstance() != null){
+ if (LibVLC.getExistingInstance().isPlaying()){
+ startActivity(new Intent(this, AudioPlayerActivity.class));
+ finish();
+ return;
+ }
+ }
+ mContext = this;
+ setContentView(R.layout.tv_main_fragment);
+
+ mMediaLibrary = MediaLibrary.getInstance();
+ mDefaultBackground = getResources().getDrawable(R.drawable.background);
+ final FragmentManager fragmentManager = getFragmentManager();
+ mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById(
+ R.id.browse_fragment);
+
+ // Set display parameters for the BrowseFragment
+ mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
+ mBrowseFragment.setTitle(getString(R.string.app_name));
+ mBrowseFragment.setBadgeDrawable(getResources().getDrawable(R.drawable.cone));
+ // set search icon color
+ mBrowseFragment.setSearchAffordanceColor(getResources().getColor(R.color.darkorange));
+
+ // add a listener for selected items
+ mBrowseFragment.setOnItemClickedListener(mItemClickListener);
+
+ mBrowseFragment.setOnSearchClickedListener(mSearchClickedListenernew);
+ mMediaLibrary.loadMediaItems(this, true);
+ mThumbnailer = new Thumbnailer(this, getWindowManager().getDefaultDisplay());
+ BackgroundManager.getInstance(this).attach(getWindow());
+ }
+
+ public void onResume() {
+ super.onResume();
+ mMediaLibrary.addUpdateHandler(mHandler);
+ if (mMediaLibrary.isWorking()) {
+ Util.actionScanStart();
+ }
+
+ /* Start the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.start(this);
+ }
+
+ public void onPause() {
+ super.onPause();
+ mMediaLibrary.removeUpdateHandler(mHandler);
+
+ /* Stop the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.stop();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mThumbnailer != null)
+ mThumbnailer.clearJobs();
+ mBarrier.reset();
+ }
+
+ protected void updateBackground(Drawable drawable) {
+ BackgroundManager.getInstance(this).setDrawable(drawable);
+ }
+
+ protected void clearBackground() {
+ BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
+ }
+
+ public void await() throws InterruptedException, BrokenBarrierException {
+ mBarrier.await();
+ }
+
+ public void resetBarrier() {
+ mBarrier.reset();
+ }
+
+ public void updateList() {
+ new AsyncUpdate().execute();
+ }
+
+ @Override
+ public void setItemToUpdate(Media item) {
+ mItemToUpdate = item;
+ mHandler.sendEmptyMessage(VideoListHandler.UPDATE_ITEM);
+ }
+
+ public void updateItem() {
+ mVideoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
+ try {
+ mBarrier.await();
+ } catch (InterruptedException e) {
+ } catch (BrokenBarrierException e) {}
+ }
+
+ private Handler mHandler = new VideoListHandler(this);
+
+ public class AsyncUpdate extends AsyncTask<Void, Void, Void> {
+
+ public AsyncUpdate() { }
+
+ @Override
+ protected void onPreExecute(){
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+ }
+ @Override
+ protected Void doInBackground(Void... params) {
+ MediaDatabase mediaDatabase = MediaDatabase.getInstance();
+ ArrayList<Media> videoList = mMediaLibrary.getVideoItems();
+// ArrayList<Media> audioList = mMediaLibrary.getAudioItems();
+ int size;
+ Media item;
+ Bitmap picture;
+
+ // Update video section
+ if (!videoList.isEmpty()) {
+ size = videoList.size();
+ mVideoIndex = new HashMap<String, Integer>(size);
+ mVideoAdapter = new ArrayObjectAdapter(
+ new CardPresenter());
+ if (NUM_ITEMS_PREVIEW < size)
+ size = NUM_ITEMS_PREVIEW;
+ for (int i = 0 ; i < size ; ++i) {
+ item = videoList.get(i);
+ picture = mediaDatabase.getPicture(mContext, item.getLocation());
+
+ mVideoAdapter.add(item);
+ mVideoIndex.put(item.getLocation(), i);
+ if (mThumbnailer != null){
+ if (picture== null) {
+ mThumbnailer.addJob(item);
+ } else {
+ MediaDatabase.setPicture(item, picture);
+ picture = null;
+ }
+ }
+ }
+ // Empty item to launch grid activity
+ mVideoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
+
+ HeaderItem header = new HeaderItem(HEADER_VIDEO, getString(R.string.video), null);
+ mRowsAdapter.add(new ListRow(header, mVideoAdapter));
+ }
+
+ /*// update audio section
+ if (!audioList.isEmpty()) {
+ size = audioList.size();
+ if (NUM_ITEMS_PREVIEW < size)
+ size = NUM_ITEMS_PREVIEW;
+ mAudioAdapter = new ArrayObjectAdapter(new CardPresenter());
+ for (int i = 0 ; i < size ; ++i) {
+ item = audioList.get(i);
+ picture = AudioUtil.getCover(mContext, item, 320);
+ if (picture != null){
+ MediaDatabase.setPicture(item, picture);
+ picture = null;
+ }
+ mAudioAdapter.add(item);
+
+ }
+ // Empty item to launch grid activity
+ mAudioAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
+
+ HeaderItem header = new HeaderItem(HEADER_MUSIC, getString(R.string.audio), null);
+ mRowsAdapter.add(new ListRow(header, mAudioAdapter));
+ }*/
+
+ mCategoriesAdapter = new ArrayObjectAdapter(new CardPresenter());
+ mCategoriesAdapter.add(getString(R.string.artists));
+ mCategoriesAdapter.add(getString(R.string.albums));
+ mCategoriesAdapter.add(getString(R.string.genres));
+ mCategoriesAdapter.add(getString(R.string.songs));
+ HeaderItem header = new HeaderItem(HEADER_CATEGORIES, getString(R.string.audio), null);
+ mRowsAdapter.add(new ListRow(header, mCategoriesAdapter));
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ mBrowseFragment.setAdapter(mRowsAdapter);
+ }
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetails.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
new file mode 100644
index 0000000..b3b0601
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetails.java
@@ -0,0 +1,64 @@
+package org.videolan.vlc.gui.tv;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class MediaItemDetails implements Parcelable {
+
+ private String title, subTitle, body, location;
+
+ public MediaItemDetails(String title, String subTitle, String body, String location) {
+ this.title = title;
+ this.subTitle = subTitle;
+ this.body = body;
+ this.location = location;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getSubTitle() {
+ return subTitle;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public String getLocation(){
+ return location;
+ }
+
+ @Override
+ public int describeContents() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(title);
+ dest.writeString(subTitle);
+ dest.writeString(body);
+ dest.writeString(location);
+ }
+
+ public static final Parcelable.Creator<MediaItemDetails> CREATOR
+ = new Parcelable.Creator<MediaItemDetails>() {
+ public MediaItemDetails createFromParcel(Parcel in) {
+ return new MediaItemDetails(in);
+ }
+
+ public MediaItemDetails[] newArray(int size) {
+ return new MediaItemDetails[size];
+ }
+ };
+
+ private MediaItemDetails(Parcel in) {
+ title = in.readString();
+ subTitle = in.readString();
+ body = in.readString();
+ location = in.readString();
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
new file mode 100644
index 0000000..bcf087b
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
@@ -0,0 +1,121 @@
+package org.videolan.vlc.gui.tv;
+
+import java.util.ArrayList;
+
+import org.videolan.libvlc.LibVLC;
+import org.videolan.libvlc.LibVlcException;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.audio.AudioServiceController;
+import org.videolan.vlc.gui.audio.AudioPlayer;
+import org.videolan.vlc.gui.audio.AudioUtil;
+import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.v17.leanback.app.DetailsFragment;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.DetailsOverviewRow;
+import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.util.Log;
+
+public class MediaItemDetailsFragment extends DetailsFragment implements AudioServiceController.AudioServiceConnectionListener {
+ private static final String TAG = "MediaItemDetailsFragment";
+ private static final int ID_PLAY = 1;
+ private static final int ID_LISTEN = 2;
+ private ArrayObjectAdapter mRowsAdapter;
+ private AudioServiceController mAudioController;
+ private AudioPlayer mAudioPlayer;
+ private MediaItemDetails mMedia;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mAudioController = AudioServiceController.getInstance();
+ buildDetails();
+ }
+
+ public void onResume(){
+ super.onResume();
+ }
+
+ public void onPause(){
+ super.onPause();
+ if (mAudioController.isPlaying()){
+ mAudioController.stop();
+ mAudioController.unbindAudioService(getActivity());
+ }
+ }
+
+ private void buildDetails() {
+ Bundle extras = getActivity().getIntent().getExtras();
+ mMedia = extras.getParcelable("item");
+ ClassPresenterSelector selector = new ClassPresenterSelector();
+ // Attach your media item details presenter to the row presenter:
+ DetailsOverviewRowPresenter rowPresenter =
+ new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
+
+ rowPresenter.setBackgroundColor(getResources().getColor(R.color.darkorange));
+ rowPresenter.setOnActionClickedListener(new OnActionClickedListener() {
+
+ @Override
+ public void onActionClicked(Action action) {
+ if (action.getId() == ID_LISTEN){
+ mAudioController.bindAudioService(getActivity(), MediaItemDetailsFragment.this);
+ } else if (action.getId() == ID_PLAY){
+ ArrayList<String> locations = new ArrayList<String>();
+ locations.add(mMedia.getLocation());
+ Intent intent = new Intent(getActivity(), AudioPlayerActivity.class);
+ intent.putExtra("locations", locations);
+ startActivity(intent);
+ }
+ }
+ });
+ selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
+ selector.addClassPresenter(ListRow.class,
+ new ListRowPresenter());
+ mRowsAdapter = new ArrayObjectAdapter(selector);
+
+ Resources res = getActivity().getResources();
+ DetailsOverviewRow detailsOverview = new DetailsOverviewRow(mMedia);
+
+ // Add images and action buttons to the details view
+ Bitmap cover = AudioUtil.getCover(getActivity(), MediaLibrary.getInstance().getMediaItem(mMedia.getLocation()), 480);
+ if (cover == null)
+ detailsOverview.setImageDrawable(res.getDrawable(R.drawable.cone));
+ else
+ detailsOverview.setImageBitmap(getActivity(), cover);
+ detailsOverview.addAction(new Action(ID_PLAY, "Play"));
+ detailsOverview.addAction(new Action(ID_LISTEN, "Listen"));
+ mRowsAdapter.add(detailsOverview);
+
+ // Add a Related items row
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
+ new StringPresenter());
+ listRowAdapter.add("Media Item 1");
+ listRowAdapter.add("Media Item 2");
+ listRowAdapter.add("Media Item 3");
+ HeaderItem header = new HeaderItem(0, "Related Items", null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+
+ setAdapter(mRowsAdapter);
+ }
+
+ @Override
+ public void onConnectionSuccess() {
+ mAudioController.load(mMedia.getLocation(), true);
+ }
+
+ @Override
+ public void onConnectionFailed() {}
+
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchActivity.java
new file mode 100644
index 0000000..be02217
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchActivity.java
@@ -0,0 +1,15 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.vlc.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SearchActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_search);
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
new file mode 100644
index 0000000..e55dd64
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/SearchFragment.java
@@ -0,0 +1,114 @@
+package org.videolan.vlc.gui.tv;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcelable;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.ObjectAdapter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.Row;
+import android.text.TextUtils;
+
+public class SearchFragment extends android.support.v17.leanback.app.SearchFragment
+implements android.support.v17.leanback.app.SearchFragment.SearchResultProvider {
+
+ private static final String TAG = "SearchFragment";
+ private static final int SEARCH_DELAY_MS = 300;
+
+ private ArrayObjectAdapter mRowsAdapter;
+ private Handler mHandler = new Handler();
+ private SearchRunnable mDelayedLoad;
+ protected Activity mActivity;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+ setSearchResultProvider(this);
+ setOnItemClickedListener(getDefaultItemClickedListener());
+ mDelayedLoad = new SearchRunnable();
+ mActivity = getActivity();
+ }
+
+ @Override
+ public ObjectAdapter getResultsAdapter() {
+ return mRowsAdapter;
+ }
+
+ private void queryByWords(String words) {
+ mRowsAdapter.clear();
+ if (!TextUtils.isEmpty(words)) {
+ mDelayedLoad.setSearchQuery(words);
+ mHandler.removeCallbacks(mDelayedLoad);
+ mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+ }
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newQuery) {
+ queryByWords(newQuery);
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ queryByWords(query);
+ return true;
+ }
+
+ private void loadRows(String query) {
+ ArrayList<Media> mediaList = MediaLibrary.getInstance().getMediaItems();
+ ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(new CardPresenter());
+ for (Media media : mediaList) {
+ if (media.getTitle().toLowerCase().indexOf(query.toLowerCase()) >= 0
+ || media.getLocation().toLowerCase().indexOf(query.toLowerCase()) >= 0) {
+ listRowAdapter.add(media);
+ }
+ }
+ HeaderItem header = new HeaderItem(0, getResources().getString(R.string.search_results),
+ null);
+ mRowsAdapter.add(new ListRow(header, listRowAdapter));
+ }
+
+ protected OnItemClickedListener getDefaultItemClickedListener() {
+ return new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ if (item instanceof Media) {
+ TvUtil.openMedia(mActivity, (Media) item, row);
+ }
+ }
+ };
+ }
+
+ private class SearchRunnable implements Runnable {
+
+ private volatile String searchQuery;
+
+ public SearchRunnable() {}
+
+ public void run() {
+ loadRows(searchQuery);
+ }
+
+ public void setSearchQuery(String value) {
+ this.searchQuery = value;
+ }
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/StringPresenter.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/StringPresenter.java
new file mode 100644
index 0000000..4eff8bc
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/StringPresenter.java
@@ -0,0 +1,29 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.vlc.R;
+
+import android.support.v17.leanback.widget.Presenter;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class StringPresenter extends Presenter {
+ private static final String TAG = "StringPresenter";
+
+ public ViewHolder onCreateViewHolder(ViewGroup parent) {
+ TextView textView = new TextView(parent.getContext());
+ textView.setFocusable(true);
+ textView.setFocusableInTouchMode(true);
+ textView.setBackground(
+ parent.getContext().getResources().getDrawable(R.drawable.background_cone));
+ return new ViewHolder(textView);
+ }
+
+ public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+ ((TextView) viewHolder.view).setText(item.toString());
+ }
+
+ public void onUnbindViewHolder(ViewHolder viewHolder) {
+ // no op
+ }
+
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvMedia.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvMedia.java
new file mode 100644
index 0000000..cc7381b
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvMedia.java
@@ -0,0 +1,136 @@
+package org.videolan.vlc.gui.tv;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class TvMedia implements Parcelable {
+ private long id;
+ private String mediaUrl;
+ private String title;
+ private String description;
+ private int bgImageId;
+ private int cardImageId;
+ private String bgImageUrl;
+ private String cardImageUrl;
+
+ public TvMedia(long id, String title, String description, String bgImageUrl, String cardImageUrl, String mediaUrl) {
+ this.id = id;
+ this.title = title;
+ this.description = description;
+ this.bgImageUrl = bgImageUrl;
+ this.cardImageUrl = cardImageUrl;
+ this.mediaUrl = mediaUrl;
+ }
+
+ public TvMedia(long id, String title, String description, int bgImageId, int cardImageId, String mediaUrl) {
+ this.id = id;
+ this.title = title;
+ this.description = description;
+ this.bgImageId = bgImageId;
+ this.cardImageId = cardImageId;
+ this.mediaUrl = mediaUrl;
+ }
+
+ public long getId(){
+ return id;
+ }
+
+ public String getDescription(){
+ return description;
+ }
+
+ public String getBgImageUrl(){
+ return bgImageUrl;
+ }
+
+ public String getCardImageUrl(){
+ return cardImageUrl;
+ }
+
+ public String getVideoUrl(){
+ return mediaUrl;
+ }
+
+ public String getTitle(){
+ return title;
+ }
+
+ public int getBackgroundImageId() {
+ return bgImageId;
+ }
+
+// public URI getBackgroundImageURI() {
+// try {
+// Log.d("BACK MEDIA: ", bgImageUrl);
+// return new URI(getBgImageUrl());
+// } catch (URISyntaxException e) {
+// Log.d("URI exception: ", bgImageUrl);
+// return null;
+// }
+// }
+
+ public int getCardImageId() {
+ return cardImageId;
+ }
+
+// public URI getCardImageURI() {
+// try {
+// return new URI(getCardImageUrl());
+// } catch (URISyntaxException e) {
+// return null;
+// }
+// }
+
+ @Override
+ public String toString() {
+ return "Movie{" +
+ "id=" + id +
+ ", title='" + title + '\'' +
+ ", mediaUrl='" + mediaUrl + '\'' +
+ ", backgroundImageId='" + bgImageId + '\'' +
+// ", backgroundImageURI='" + getBackgroundImageURI().toString() + '\'' +
+ ", cardImageUrl='" + cardImageUrl + '\'' +
+ '}';
+ }
+
+ @Override
+ public int describeContents() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(id);
+ dest.writeString(mediaUrl);
+ dest.writeString(title);
+ dest.writeString(description);
+ dest.writeInt(bgImageId);
+ dest.writeInt(cardImageId);
+ dest.writeString(bgImageUrl);
+ dest.writeString(cardImageUrl);
+ }
+
+ public static final Parcelable.Creator<TvMedia> CREATOR
+ = new Parcelable.Creator<TvMedia>() {
+ public TvMedia createFromParcel(Parcel in) {
+ return new TvMedia(in);
+ }
+
+ public TvMedia[] newArray(int size) {
+ return new TvMedia[size];
+ }
+ };
+
+ private TvMedia(Parcel in) {
+ id = in.readLong();
+ mediaUrl = in.readString();
+ title = in.readString();
+ description = in.readString();
+ bgImageId = in.readInt();
+ cardImageId = in.readInt();
+ bgImageUrl = in.readString();
+ cardImageUrl = in.readString();
+ }
+
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvUtil.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvUtil.java
new file mode 100644
index 0000000..b75268c
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/TvUtil.java
@@ -0,0 +1,29 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.gui.video.VideoPlayerActivity;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Parcelable;
+import android.support.v17.leanback.widget.Row;
+
+public class TvUtil {
+
+
+ public static void openMedia(Activity activity, Media media, Row row){
+ if (media.getType() == Media.TYPE_VIDEO){
+ VideoPlayerActivity.start(activity, media.getLocation(), false);
+ } else if (media.getType() == Media.TYPE_AUDIO){
+ Intent intent = new Intent(activity,
+ DetailsActivity.class);
+ // pass the item information
+ intent.putExtra("item", (Parcelable)new MediaItemDetails(media.getTitle(), media.getArtist(), media.getAlbum(), media.getLocation()));
+ activity.startActivity(intent);
+ } else if (media.getType() == Media.TYPE_GROUP){
+ Intent intent = new Intent(activity, VerticalGridActivity.class);
+ intent.putExtra("id", row.getId());
+ activity.startActivity(intent);
+ }
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
new file mode 100644
index 0000000..64e96f1
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
@@ -0,0 +1,17 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.vlc.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class VerticalGridActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_vertical_grid);
+ getWindow().setBackgroundDrawableResource(R.drawable.background);
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
new file mode 100644
index 0000000..cd8924b
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/AudioPlayerActivity.java
@@ -0,0 +1,278 @@
+package org.videolan.vlc.gui.tv.audioplayer;
+
+import java.util.ArrayList;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.audio.AudioServiceController;
+import org.videolan.vlc.gui.audio.AudioUtil;
+import org.videolan.vlc.gui.tv.audioplayer.PlaylistAdapter.ViewHolder;
+import org.videolan.vlc.interfaces.IAudioPlayer;
+import org.videolan.vlc.util.AndroidDevices;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.Adapter;
+import android.view.InputDevice;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class AudioPlayerActivity extends Activity implements AudioServiceController.AudioServiceConnectionListener, IAudioPlayer{
+ public static final String TAG = "AudioPlayerActivity";
+
+ private AudioServiceController mAudioController;
+ private RecyclerView mRecyclerView;
+ private Adapter<ViewHolder> mAdapter;
+ private LinearLayoutManager mLayoutManager;
+ private ArrayList<String> mLocations;
+
+ //PAD navigation
+ private static final int JOYSTICK_INPUT_DELAY = 300;
+ private long mLastMove;
+ private int mSelectedItem = 0;
+ private int mCurrentlyPlaying;
+
+ private TextView mTitleTv, mArtistTv;
+ private ImageView mPlayPauseButton, mCover;
+ private ProgressBar mProgressBar;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_audio_player);
+
+ mLocations = getIntent().getStringArrayListExtra("locations");
+ mRecyclerView = (RecyclerView) findViewById(R.id.playlist);
+ mLayoutManager = new LinearLayoutManager(this);
+ mRecyclerView.setLayoutManager(mLayoutManager);
+ mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
+ if (mLocations == null)
+ mLocations = new ArrayList<String>();
+ else {
+ mAdapter = new PlaylistAdapter(mLocations);
+ mRecyclerView.setAdapter(mAdapter);
+ }
+
+ mAudioController = AudioServiceController.getInstance();
+
+ mTitleTv = (TextView)findViewById(R.id.media_title);
+ mArtistTv = (TextView)findViewById(R.id.media_artist);
+ mPlayPauseButton = (ImageView)findViewById(R.id.button_play);
+ mProgressBar = (ProgressBar)findViewById(R.id.media_progress);
+ mCover = (ImageView)findViewById(R.id.album_cover);
+
+ }
+
+ public void onStart(){
+ super.onStart();
+ mAudioController.bindAudioService(this, this);
+ mAudioController.addAudioPlayer(this);
+ }
+
+ public void onStop(){
+ super.onStop();
+ mAudioController.removeAudioPlayer(this);
+ mAudioController.unbindAudioService(this);
+ mLocations.clear();
+ }
+
+ protected void onResume() {
+ super.onResume();
+ mRecyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ mLayoutManager.getChildAt(mSelectedItem).setSelected(true);
+ }
+ });
+ };
+
+ @Override
+ public void onConnectionSuccess() {
+ ArrayList<String> medialocations = (ArrayList<String>) mAudioController.getMediaLocations();
+ if (!mLocations.isEmpty() && !mLocations.equals(medialocations))
+ mAudioController.load(mLocations, 0, true);
+ else {
+ mLocations = medialocations;
+ update();
+ mAdapter = new PlaylistAdapter(mLocations);
+ mRecyclerView.setAdapter(mAdapter);
+ }
+ }
+
+ @Override
+ public void onConnectionFailed() {}
+
+ @Override
+ public void update() {
+ mPlayPauseButton.setImageResource(mAudioController.isPlaying() ? R.drawable.ic_pause : R.drawable.ic_play);
+ if (mAudioController.hasMedia()) {
+ mTitleTv.setText(mAudioController.getTitle());
+ mArtistTv.setText(mAudioController.getArtist());
+ mProgressBar.setMax(mAudioController.getLength());
+ Media media = MediaLibrary.getInstance().getMediaItem(mAudioController.getCurrentMediaLocation());
+ Bitmap cover = AudioUtil.getCover(this, media, mCover.getWidth());
+ if (cover == null)
+ cover = mAudioController.getCover();
+ if (cover == null)
+ mCover.setImageResource(R.drawable.background_cone);
+ else
+ mCover.setImageBitmap(cover);
+ }
+ }
+
+ @Override
+ public void updateProgress() {
+ mProgressBar.setProgress(mAudioController.getTime());
+ }
+
+ public boolean onKeyDown(int keyCode, KeyEvent event){
+ switch (keyCode){
+ /*
+ * Playback control
+ */
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_PLAY:
+ case KeyEvent.KEYCODE_MEDIA_PAUSE:
+ case KeyEvent.KEYCODE_SPACE:
+ case KeyEvent.KEYCODE_BUTTON_A:
+ togglePlayPause();
+ return true;
+ case KeyEvent.KEYCODE_F:
+ case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+ case KeyEvent.KEYCODE_BUTTON_R1:
+ goNext();
+ return true;
+ case KeyEvent.KEYCODE_R:
+ case KeyEvent.KEYCODE_MEDIA_REWIND:
+ case KeyEvent.KEYCODE_BUTTON_L1:
+ goPrevious();
+ return true;
+ /*
+ * Playlist navigation
+ */
+ case KeyEvent.KEYCODE_DPAD_UP:
+ selectPrevious();
+ return true;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ selectNext();
+ return true;
+ case KeyEvent.KEYCODE_BUTTON_X:
+ mAudioController.playIndex(mSelectedItem);
+ mCurrentlyPlaying = mSelectedItem;
+ return true;
+ default:
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+
+ @TargetApi(12) //only active for Android 3.1+
+ public boolean dispatchGenericMotionEvent(MotionEvent event){
+
+ InputDevice mInputDevice = event.getDevice();
+
+ float x = AndroidDevices.getCenteredAxis(event, mInputDevice,
+ MotionEvent.AXIS_X);
+// float y = AndroidDevices.getCenteredAxis(event, mInputDevice,
+// MotionEvent.AXIS_Y);
+// float z = AndroidDevices.getCenteredAxis(event, mInputDevice,
+// MotionEvent.AXIS_Z);
+// float rz = AndroidDevices.getCenteredAxis(event, mInputDevice,
+// MotionEvent.AXIS_RZ);
+
+ if (System.currentTimeMillis() - mLastMove > JOYSTICK_INPUT_DELAY){
+ if (Math.abs(x) > 0.3){
+ seek(x > 0.0f ? 10000 : -10000);
+ mLastMove = System.currentTimeMillis();
+ return true;
+ }
+ //TODO Will we change volume in app on TV ?
+ /*else if (Math.abs(rz) > 0.3){
+ mVol = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ int delta = -(int) ((rz / 7) * mAudioMax);
+ int vol = (int) Math.min(Math.max(mVol + delta, 0), mAudioMax);
+ setAudioVolume(vol);
+ mLastMove = System.currentTimeMillis();
+ }*/
+ }
+ return false;
+ }
+
+ private void seek(int delta) {
+ int time = mAudioController.getTime()+delta;
+ if (time < 0 || time > mAudioController.getLength())
+ return;
+ mAudioController.setTime(time);
+ }
+
+ public void onClick(View v){
+ switch (v.getId()){
+ case R.id.button_play:
+ togglePlayPause();
+ break;
+ case R.id.button_next:
+ goNext();
+ break;
+ case R.id.button_previous:
+ goPrevious();
+ break;
+ }
+ }
+
+ private void goPrevious() {
+ if (mAudioController.hasPrevious()) {
+ mAudioController.previous();
+ selectItem(--mCurrentlyPlaying);
+ }
+ }
+
+ private void goNext() {
+ if (mAudioController.hasNext()){
+ mAudioController.next();
+ selectItem(++mCurrentlyPlaying);
+ }
+ }
+
+ private void togglePlayPause() {
+ if (mAudioController.isPlaying())
+ mAudioController.pause();
+ else if (mAudioController.hasMedia())
+ mAudioController.play();
+ }
+
+ private void selectNext() {
+ if (mSelectedItem >= mAdapter.getItemCount()-1)
+ return;
+ selectItem(++mSelectedItem);
+ }
+
+ private void selectPrevious() {
+ if (mSelectedItem < 1)
+ return;
+ selectItem(--mSelectedItem);
+ }
+
+ private void selectItem(int position){
+ mSelectedItem = position;
+ mRecyclerView.stopScroll();
+ mLayoutManager.scrollToPosition(position);
+ mRecyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ View v;
+ for (int i = 0 ; i< mAdapter.getItemCount() ; ++i){
+ v = mLayoutManager.findViewByPosition(i);
+ if (v != null)
+ v.setSelected( i == mSelectedItem);
+ }
+ }
+ });
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
new file mode 100644
index 0000000..a9c9520
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.videolan.vlc.gui.tv.audioplayer;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private static final int[] ATTRS = new int[]{
+ android.R.attr.listDivider
+ };
+
+ public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
+
+ public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
+
+ private Drawable mDivider;
+
+ private int mOrientation;
+
+ public DividerItemDecoration(Context context, int orientation) {
+ final TypedArray a = context.obtainStyledAttributes(ATTRS);
+ mDivider = a.getDrawable(0);
+ a.recycle();
+ setOrientation(orientation);
+ }
+
+ public void setOrientation(int orientation) {
+ if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
+ throw new IllegalArgumentException("invalid orientation");
+ }
+ mOrientation = orientation;
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent) {
+ if (mOrientation == VERTICAL_LIST) {
+ drawVertical(c, parent);
+ } else {
+ drawHorizontal(c, parent);
+ }
+ }
+
+ public void drawVertical(Canvas c, RecyclerView parent) {
+ final int left = parent.getPaddingLeft();
+ final int right = parent.getWidth() - parent.getPaddingRight();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int top = child.getBottom() + params.bottomMargin;
+ final int bottom = top + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ public void drawHorizontal(Canvas c, RecyclerView parent) {
+ final int top = parent.getPaddingTop();
+ final int bottom = parent.getHeight() - parent.getPaddingBottom();
+
+ final int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = parent.getChildAt(i);
+ final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+ .getLayoutParams();
+ final int left = child.getRight() + params.rightMargin;
+ final int right = left + mDivider.getIntrinsicHeight();
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
+ if (mOrientation == VERTICAL_LIST) {
+ outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
+ } else {
+ outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
+ }
+ }
+}
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
new file mode 100644
index 0000000..917d4cd
--- /dev/null
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/PlaylistAdapter.java
@@ -0,0 +1,55 @@
+package org.videolan.vlc.gui.tv.audioplayer;
+
+import java.util.ArrayList;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaLibrary;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class PlaylistAdapter extends RecyclerView.Adapter<PlaylistAdapter.ViewHolder> {
+ private ArrayList<String> mDataset;
+ private static MediaLibrary sMediaLibrary = MediaLibrary.getInstance();
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView mTitleTv;
+ public TextView mArtistTv;
+ public ViewHolder(View v) {
+ super(v);
+ mTitleTv = (TextView) v.findViewById(android.R.id.text1);
+ mTitleTv.setTextAppearance(v.getContext(), android.R.style.TextAppearance_DeviceDefault_Small);
+ mArtistTv = (TextView) v.findViewById(android.R.id.text2);
+ mArtistTv.setTextAppearance(v.getContext(), android.R.style.TextAppearance_DeviceDefault_Small_Inverse);
+ }
+ }
+
+ public PlaylistAdapter(ArrayList<String> myDataset) {
+ mDataset = myDataset;
+ }
+
+ @Override
+ public PlaylistAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+ int viewType) {
+ View v = LayoutInflater.from(parent.getContext())
+ .inflate(android.R.layout.simple_list_item_2, parent, false);
+
+ ViewHolder vh = new ViewHolder(v);
+ return vh;
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ Media media = sMediaLibrary.getMediaItem(mDataset.get(position));
+ holder.mTitleTv.setText(media.getTitle());
+ holder.mArtistTv.setText(media.getArtist());
+ }
+
+ @Override
+ public int getItemCount() {
+ return mDataset.size();
+ }
+}
\ No newline at end of file
--
1.9.1
More information about the Android
mailing list