[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