diff options
author | Scott Jackson <daneren2005@gmail.com> | 2013-11-14 23:47:19 -0800 |
---|---|---|
committer | Scott Jackson <daneren2005@gmail.com> | 2013-11-14 23:47:19 -0800 |
commit | 2ad1a9ace84137b18fd6f35174920ea659dde0a3 (patch) | |
tree | 25cc337557bf119c5a82052a8312800fea6fe7be | |
parent | edaa382b8a37954fd10f47c50066ae718bd21428 (diff) | |
parent | bbf1ec51c18a5deddef714e948f3702b3d11f97c (diff) | |
download | dsub-2ad1a9ace84137b18fd6f35174920ea659dde0a3.tar.gz dsub-2ad1a9ace84137b18fd6f35174920ea659dde0a3.tar.bz2 dsub-2ad1a9ace84137b18fd6f35174920ea659dde0a3.zip |
Merge changes
451 files changed, 4357 insertions, 3092 deletions
@@ -6,3 +6,4 @@ private/* nbandroid/*
.idea
subsonic-android.iml
+releases/
\ No newline at end of file diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2e96d2ca..207c2afd 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,8 +2,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="github.daneren2005.dsub"
android:installLocation="internalOnly"
- android:versionCode="62"
- android:versionName="4.1.4">
+ android:versionCode="69"
+ android:versionName="4.2.0">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
@@ -23,7 +23,7 @@ <uses-feature android:name="android.hardware.bluetooth" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
- <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18"/>
+ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19"/>
<supports-screens android:anyDensity="true" android:xlargeScreens="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
@@ -32,36 +32,20 @@ android:icon="@drawable/launch"
android:theme="@style/Theme.DSub.Holo">
- <activity android:name="github.daneren2005.dsub.activity.MainActivity"
- android:label="DSub"
- android:configChanges="orientation|keyboardHidden"
- android:launchMode="standard">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
-
- <activity android:name="github.daneren2005.dsub.activity.SearchActivity"
- android:label="@string/search.label"
- android:configChanges="orientation|keyboardHidden"
- android:launchMode="singleTask"/>
+ <activity android:name="github.daneren2005.dsub.activity.SubsonicFragmentActivity"
+ android:configChanges="orientation|keyboardHidden"
+ android:launchMode="standard">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
- <activity android:name="github.daneren2005.dsub.activity.DownloadActivity"
+ <activity android:name="github.daneren2005.dsub.activity.DownloadActivity"
android:configChanges="keyboardHidden"
android:launchMode="singleTask"/>
<activity android:name="github.daneren2005.dsub.activity.SettingsActivity"
- android:theme="@style/Theme.DSub.Dark"
- android:configChanges="orientation|keyboardHidden"
- android:launchMode="singleTask"/>
-
- <activity android:name="github.daneren2005.dsub.activity.HelpActivity"
- android:label="@string/help.label"
- android:launchMode="singleTask"/>
-
- <activity android:name="github.daneren2005.dsub.activity.EqualizerActivity"
- android:label="@string/equalizer.label"
android:configChanges="orientation|keyboardHidden"
android:launchMode="singleTask"/>
@@ -3,26 +3,23 @@ Run these commands to grab dependent libraries: git submodule init git submodule update -Go to both ActionBarSherlock/library and DragSortListView/library and build project files with: +Go to DragSortListView/library and build project files with: android update project --path ./ +Replace the file DragSortListView/library/libs/android-support-v4.jar with the one from main projects libs/ Roadmap of major planned features in rough order that I plan to work on them in (little features get sprinkled in wherever): UI Redesign - -Fragments - -Native tabs -Tablets: side by side fragments HLS Video -Display video where album art is currently (double tap to fullscreen) -Videos can play inline with songs Background Sync -Mark playlists as 'offline', syncs changes - -Do things like star songs in offline mode that sync later + -Mark podcasts as 'offline', download new episodes only New Tabs - -Podcasts -Admin functions -Change your password -Create/delete users if admin - -Chat diff --git a/Subsonic.iml b/Subsonic.iml index d89b96cf..f7983073 100644 --- a/Subsonic.iml +++ b/Subsonic.iml @@ -11,13 +11,13 @@ <exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
</content>
+ <orderEntry type="library" name="libs1" level="project" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="libs1" level="project" />
- <orderEntry type="module" module-name="DragSortListView" />
<orderEntry type="module" module-name="appcompat" />
+ <orderEntry type="module" module-name="DragSortListView" />
</component>
</module>
diff --git a/assets/fonts/Storopia.ttf b/assets/fonts/Storopia.ttf Binary files differdeleted file mode 100644 index cbdc4c1f..00000000 --- a/assets/fonts/Storopia.ttf +++ /dev/null diff --git a/assets/html/en/index.html b/assets/html/en/index.html deleted file mode 100644 index 9ad7542c..00000000 --- a/assets/html/en/index.html +++ /dev/null @@ -1,98 +0,0 @@ -<html> -<head> - <title>DSub Help</title> - <link rel="stylesheet" href="../style.css" type="text/css"> - -</head> - -<body> - -<h3><img src="../img/subsonic.png" alt=""> Welcome to DSub!</h3> - -<p> - With <b>DSub</b> you can easily stream or download music from your home computer to your Android phone - (and do lots of other cool stuff too). -</p> - -<p> - To install the Subsonic server software on your computer, please visit <a href="http://subsonic.org">subsonic.org</a>. - It's available for Windows, Mac, Linux and Unix. -</p> - -<p> - By default, this program is configured to use the <b>Subsonic demo server</b>. Once you've set up your own - server, please go to <b>Settings</b> and change the configuration so that it connects to your own computer. -</p> - -<p> - You can use this program freely for 30 days. After that you will have to make a donation to the Subsonic project. - As a donor you get the following benefits: -</p> -<ul> - <li>Unlimited streaming and download to any number of iPhone and Android phones.</li> - <li>Video streaming.</li> - <li>A personal web address for your Subsonic server (<em>yourname</em>.subsonic.org).</li> - <li>No ads in the Subsonic web interface.</li> - <li>Free access to new premium features.</li> -</ul> - -<p> - The suggested donation amount is <b>€20</b>, but you can give any amount you like. -</p> - -<p> - Click one of the buttons to go to PayPal where you can pay by credit card or by using your PayPal account. - Once the donation is processed, you will receive a license key by email. -</p> - -<table> - <tr> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3RTGWJRNAW2PU"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">€10</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UCUUB2TYE4PGN"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">€20</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3M6TFHWEPSU44"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">€25</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5KP7LPQU77UAS"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">€30</td> - </tr> - </table> - </td> - </tr> -</table> - -<p> - For more information, please visit <a href="http://subsonic.org/">subsonic.org</a> -</p> - -</body> -</html> diff --git a/assets/html/fr/index.html b/assets/html/fr/index.html deleted file mode 100644 index 4ac8c9c3..00000000 --- a/assets/html/fr/index.html +++ /dev/null @@ -1,100 +0,0 @@ -<html> -<head> - <title>Aide de Subsonic</title> - <link rel="stylesheet" href="../style.css" type="text/css"> - -</head> - -<body> - -<h3><img src="../img/subsonic.png" alt=""> Bienvenue dans Subsonic</h3> - -<p> - Avec <b>Subsonic</b>, vous pouvez facilement écouter ou télécharger de la musique à partir de votre ordinateur personnel sur votre appareil Android - (et faire plein d'autres trucs cools aussi). -</p> - -<p> - Pour installer le serveur Subsonic sur votre ordinateur, veuillez visiter <a href="http://subsonic.org">subsonic.org</a>. - Celui-ci est disponible pour Windows, Mac, Linux et Unix. -</p> - -<p> - Par défaut, cette application est configuré pour utiliser le <b>serveur démo Subsonic</b>. - Après avoir configuré votre serveur personnel, veuillez accéder aux <b>Paramètres</b> et modifier la configuration - afin de vous connecter à votre propre ordinateur. -</p> - -<p> - Vous pouvez utiliser cette application gratuitement pendant 30 jours. - Ensuite, vous devrez effectuer un don au projet Subsonic. - En tant que donateur, vous obtiendrez les bénéfices suivants: -</p> -<ul> - <li>Écoute et téléchargement illimités vers autant de iPhones et d'appareils Android que désiré.</li> - <li>Écoute de vidéos.</li> - <li>Une adresse web personnalisée pour votre serveur Subsonic (<em>votrenom</em>.subsonic.org).</li> - <li>Aucune publicité dans l'interface web de Subsonic.</li> - <li>Accès gratuit aux nouvelles fonctionnalités avancées.</li> -</ul> - -<p> - Le montant suggéré pour le don est de <b>20€</b>, mais n'importe quel montant fera l'affaire. -</p> - -<p> - Cliquez l'un des boutons suivants pour accéder à PayPal, d'où vous pourrez payer soit par carte de crédit ou en utilisant votre compte PayPal. - Une fois le don reçu et traité, vous recevrez votre clé d'activation par courriel. -</p> - -<table> - <tr> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3RTGWJRNAW2PU"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">10€</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UCUUB2TYE4PGN"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">20€</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3M6TFHWEPSU44"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">25€</td> - </tr> - </table> - </td> - <td style="border:none;"> - <table> - <tr> - <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5KP7LPQU77UAS"><img src="../img/paypal.gif" alt=""/></a> </td> - </tr> - <tr> - <td style="text-align:center;border:none;padding:0">30€</td> - </tr> - </table> - </td> - </tr> -</table> - -<p> - Pour plus d'information, veuillez visiter <a href="http://subsonic.org/">subsonic.org</a> -</p> - -</body> -</html> diff --git a/assets/html/img/paypal.gif b/assets/html/img/paypal.gif Binary files differdeleted file mode 100644 index d017250a..00000000 --- a/assets/html/img/paypal.gif +++ /dev/null diff --git a/assets/html/img/subsonic.png b/assets/html/img/subsonic.png Binary files differdeleted file mode 100644 index 38c521c5..00000000 --- a/assets/html/img/subsonic.png +++ /dev/null diff --git a/assets/html/ru/index.html b/assets/html/ru/index.html deleted file mode 100644 index 57979152..00000000 --- a/assets/html/ru/index.html +++ /dev/null @@ -1,98 +0,0 @@ -<html>
-<head>
- <title>Помощь DSub</title>
- <link rel="stylesheet" href="../style.css" type="text/css">
-
-</head>
-
-<body>
-
-<h3><img src="../img/subsonic.png" alt=""> Добро пожаловать в DSub!</h3>
-
-<p>
- С программой <b>DSub</b> Вы можете легко включить поточное воспроизведение или скачивать музыку с Вашего домашнего компьютера на Android устройство
- (и использовать множество других полезных функции).
-</p>
-
-<p>
- Для установки серверного приложения Subsonic на Ваш компьютер, пожалуйста, посетите <a href="http://subsonic.org">subsonic.org</a>.
- Приложение доступно для Windows, Mac, а также Linux и Unix.
-</p>
-
-<p>
- По умолчанию данная программа настроена на работу с <b>демо сервером Subsonic</b>. После установки серверного
- приложения, пожалуйста, перейдите в раздел <b>Настройки</b> и измените параметры для подключения.
-</p>
-
-<p>
- Вы можете бесплатно использовать программу до 30 дней. После этого Вам необходимо сделать пожертвование проекту Subsonic.
- После этого Вы получите следующие возможности:
-</p>
-<ul>
- <li>Неограниченное поточное воспроизведение или скачивание с любого количества iPhone и Android устройств.</li>
- <li>Потоковое воспроизведение видео.</li>
- <li>Персональный адрес страницы на сервере Subsonic (<em>вашеимя</em>.subsonic.org).</li>
- <li>Отсутствие рекламы в веб-интерфейсе Subsonic.</li>
- <li>Бесплатный доступ к новым премиум-функциям.</li>
-</ul>
-
-<p>
- Рекомендуемая сумма пожертвования - <b>€20</b>, но Вы можете пожертвовать любую сумму.
-</p>
-
-<p>
- Нажмите одну из кнопок для перехода на страницу PayPal, откуда Вы сможете сделать перевод с Вашей кредитной карты или используя аккаунт PayPal.
- После отправки пожертвования Вы получите лицензионный ключ на Ваш email.
-</p>
-
-<table>
- <tr>
- <td style="border:none;">
- <table>
- <tr>
- <td style="border:none;padding:0;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3RTGWJRNAW2PU"><img src="../img/paypal.gif" alt=""/></a> </td>
- </tr>
- <tr>
- <td style="text-align:center;border:none;padding:0">€10</td>
- </tr>
- </table>
- </td>
- <td style="border:none;">
- <table>
- <tr>
- <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UCUUB2TYE4PGN"><img src="../img/paypal.gif" alt=""/></a> </td>
- </tr>
- <tr>
- <td style="text-align:center;border:none;padding:0">€20</td>
- </tr>
- </table>
- </td>
- <td style="border:none;">
- <table>
- <tr>
- <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3M6TFHWEPSU44"><img src="../img/paypal.gif" alt=""/></a> </td>
- </tr>
- <tr>
- <td style="text-align:center;border:none;padding:0">€25</td>
- </tr>
- </table>
- </td>
- <td style="border:none;">
- <table>
- <tr>
- <td style="border:none;padding:0"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5KP7LPQU77UAS"><img src="../img/paypal.gif" alt=""/></a> </td>
- </tr>
- <tr>
- <td style="text-align:center;border:none;padding:0">€30</td>
- </tr>
- </table>
- </td>
- </tr>
-</table>
-
-<p>
- За дополнительной информацией посетите <a href="http://subsonic.org/">subsonic.org</a>
-</p>
-
-</body>
-</html>
\ No newline at end of file diff --git a/assets/html/style.css b/assets/html/style.css deleted file mode 100644 index 9c1d55f2..00000000 --- a/assets/html/style.css +++ /dev/null @@ -1,11 +0,0 @@ -/* -* Taken from http://yui.yahooapis.com/2.8.0r4/build/fonts/fonts.css -*/ -body { - font: 13px / 1.231 arial, helvetica, clean, sans-serif; -} - -table { - font-size:inherit; - font:100%; -}
\ No newline at end of file diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar Binary files differindex cf12d283..9056828a 100644 --- a/libs/android-support-v4.jar +++ b/libs/android-support-v4.jar diff --git a/libs/android-support-v7-appcompat.jar b/libs/android-support-v7-appcompat.jar Binary files differindex b5f52924..fd1d984d 100644 --- a/libs/android-support-v7-appcompat.jar +++ b/libs/android-support-v7-appcompat.jar diff --git a/libs/kryo-2.21-all.jar b/libs/kryo-2.21-all.jar Binary files differnew file mode 100644 index 00000000..83f8b0f0 --- /dev/null +++ b/libs/kryo-2.21-all.jar diff --git a/project.properties b/project.properties index 558f3a9e..73506e5d 100644 --- a/project.properties +++ b/project.properties @@ -8,6 +8,6 @@ # project structure. # Project target. -target=android-18 -android.library.reference.1=DragSortListView/library -android.library.reference.2=../../../../Program Files (x86)/Android/android-sdk/extras/android/support/v7/appcompat
\ No newline at end of file +target=android-19 +android.library.reference.1=../../../../Program Files (x86)/Android/android-sdk/extras/android/support/v7/appcompat +android.library.reference.2=DragSortListView/library
\ No newline at end of file diff --git a/releases/DSub 4.0.1.apk b/releases/DSub 4.0.1.apk Binary files differdeleted file mode 100644 index 850a4bfa..00000000 --- a/releases/DSub 4.0.1.apk +++ /dev/null diff --git a/releases/DSub 4.0.2.apk b/releases/DSub 4.0.2.apk Binary files differdeleted file mode 100644 index 0c168ba8..00000000 --- a/releases/DSub 4.0.2.apk +++ /dev/null diff --git a/releases/DSub 4.0.3.apk b/releases/DSub 4.0.3.apk Binary files differdeleted file mode 100644 index a1749e3c..00000000 --- a/releases/DSub 4.0.3.apk +++ /dev/null diff --git a/releases/DSub 4.0.4.apk b/releases/DSub 4.0.4.apk Binary files differdeleted file mode 100644 index 1332af32..00000000 --- a/releases/DSub 4.0.4.apk +++ /dev/null diff --git a/releases/DSub 4.0.5.apk b/releases/DSub 4.0.5.apk Binary files differdeleted file mode 100644 index 1ece93f6..00000000 --- a/releases/DSub 4.0.5.apk +++ /dev/null diff --git a/releases/DSub 4.0.6.apk b/releases/DSub 4.0.6.apk Binary files differdeleted file mode 100644 index 278256d7..00000000 --- a/releases/DSub 4.0.6.apk +++ /dev/null diff --git a/releases/DSub 4.0.7.apk b/releases/DSub 4.0.7.apk Binary files differdeleted file mode 100644 index a97c215c..00000000 --- a/releases/DSub 4.0.7.apk +++ /dev/null diff --git a/releases/DSub 4.1.0.apk b/releases/DSub 4.1.0.apk Binary files differdeleted file mode 100644 index 1bb3fe41..00000000 --- a/releases/DSub 4.1.0.apk +++ /dev/null diff --git a/releases/DSub 4.1.1.apk b/releases/DSub 4.1.1.apk Binary files differdeleted file mode 100644 index 9d582aec..00000000 --- a/releases/DSub 4.1.1.apk +++ /dev/null diff --git a/releases/DSub 4.1.2.apk b/releases/DSub 4.1.2.apk Binary files differdeleted file mode 100644 index 0a4ee2bc..00000000 --- a/releases/DSub 4.1.2.apk +++ /dev/null diff --git a/res/drawable-hdpi-v11/notification_close.png b/res/drawable-hdpi-v11/notification_close.png Binary files differnew file mode 100644 index 00000000..254e130f --- /dev/null +++ b/res/drawable-hdpi-v11/notification_close.png diff --git a/res/drawable-hdpi-v11/notification_next.png b/res/drawable-hdpi-v11/notification_next.png Binary files differnew file mode 100644 index 00000000..59239305 --- /dev/null +++ b/res/drawable-hdpi-v11/notification_next.png diff --git a/res/drawable-hdpi-v11/notification_pause.png b/res/drawable-hdpi-v11/notification_pause.png Binary files differnew file mode 100644 index 00000000..cbd61795 --- /dev/null +++ b/res/drawable-hdpi-v11/notification_pause.png diff --git a/res/drawable-hdpi-v11/notification_play.png b/res/drawable-hdpi-v11/notification_play.png Binary files differnew file mode 100644 index 00000000..78b4d5bf --- /dev/null +++ b/res/drawable-hdpi-v11/notification_play.png diff --git a/res/drawable-hdpi-v11/notification_previous.png b/res/drawable-hdpi-v11/notification_previous.png Binary files differnew file mode 100644 index 00000000..556eaec3 --- /dev/null +++ b/res/drawable-hdpi-v11/notification_previous.png diff --git a/res/drawable-hdpi-v11/stat_notify_download.png b/res/drawable-hdpi-v11/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..48ca6924 --- /dev/null +++ b/res/drawable-hdpi-v11/stat_notify_download.png diff --git a/res/drawable-hdpi-v11/stat_notify_playing.png b/res/drawable-hdpi-v11/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..78b4d5bf --- /dev/null +++ b/res/drawable-hdpi-v11/stat_notify_playing.png diff --git a/res/drawable-hdpi/action_browse.png b/res/drawable-hdpi/action_browse.png Binary files differdeleted file mode 100644 index 54296909..00000000 --- a/res/drawable-hdpi/action_browse.png +++ /dev/null diff --git a/res/drawable-hdpi/action_compass.png b/res/drawable-hdpi/action_compass.png Binary files differdeleted file mode 100644 index 39760f89..00000000 --- a/res/drawable-hdpi/action_compass.png +++ /dev/null diff --git a/res/drawable-hdpi/action_exit.png b/res/drawable-hdpi/action_exit.png Binary files differdeleted file mode 100644 index 09e18dee..00000000 --- a/res/drawable-hdpi/action_exit.png +++ /dev/null diff --git a/res/drawable-hdpi/action_help.png b/res/drawable-hdpi/action_help.png Binary files differdeleted file mode 100644 index aaf8304c..00000000 --- a/res/drawable-hdpi/action_help.png +++ /dev/null diff --git a/res/drawable-hdpi/action_moreoverflow.png b/res/drawable-hdpi/action_moreoverflow.png Binary files differdeleted file mode 100644 index cb6ebdaf..00000000 --- a/res/drawable-hdpi/action_moreoverflow.png +++ /dev/null diff --git a/res/drawable-hdpi/action_offline.png b/res/drawable-hdpi/action_offline.png Binary files differdeleted file mode 100644 index a85f0931..00000000 --- a/res/drawable-hdpi/action_offline.png +++ /dev/null diff --git a/res/drawable-hdpi/action_play_all.png b/res/drawable-hdpi/action_play_all.png Binary files differdeleted file mode 100644 index 6ce5629a..00000000 --- a/res/drawable-hdpi/action_play_all.png +++ /dev/null diff --git a/res/drawable-hdpi/action_refresh.png b/res/drawable-hdpi/action_refresh.png Binary files differdeleted file mode 100644 index 9f30dc95..00000000 --- a/res/drawable-hdpi/action_refresh.png +++ /dev/null diff --git a/res/drawable-hdpi/action_remove_all.png b/res/drawable-hdpi/action_remove_all.png Binary files differdeleted file mode 100644 index 97b88837..00000000 --- a/res/drawable-hdpi/action_remove_all.png +++ /dev/null diff --git a/res/drawable-hdpi/action_save.png b/res/drawable-hdpi/action_save.png Binary files differdeleted file mode 100644 index 7bda97d6..00000000 --- a/res/drawable-hdpi/action_save.png +++ /dev/null diff --git a/res/drawable-hdpi/action_screen_on_off.png b/res/drawable-hdpi/action_screen_on_off.png Binary files differdeleted file mode 100644 index c7168563..00000000 --- a/res/drawable-hdpi/action_screen_on_off.png +++ /dev/null diff --git a/res/drawable-hdpi/action_search.png b/res/drawable-hdpi/action_search.png Binary files differdeleted file mode 100644 index 6bc3d426..00000000 --- a/res/drawable-hdpi/action_search.png +++ /dev/null diff --git a/res/drawable-hdpi/action_select.png b/res/drawable-hdpi/action_select.png Binary files differdeleted file mode 100644 index e9e83e3d..00000000 --- a/res/drawable-hdpi/action_select.png +++ /dev/null diff --git a/res/drawable-hdpi/action_settings.png b/res/drawable-hdpi/action_settings.png Binary files differdeleted file mode 100644 index 1ab7722b..00000000 --- a/res/drawable-hdpi/action_settings.png +++ /dev/null diff --git a/res/drawable-hdpi/action_share.png b/res/drawable-hdpi/action_share.png Binary files differdeleted file mode 100644 index 28376157..00000000 --- a/res/drawable-hdpi/action_share.png +++ /dev/null diff --git a/res/drawable-hdpi/action_shuffle.png b/res/drawable-hdpi/action_shuffle.png Binary files differdeleted file mode 100644 index 0613965c..00000000 --- a/res/drawable-hdpi/action_shuffle.png +++ /dev/null diff --git a/res/drawable-hdpi/action_toggle_list.png b/res/drawable-hdpi/action_toggle_list.png Binary files differdeleted file mode 100644 index 87f9280f..00000000 --- a/res/drawable-hdpi/action_toggle_list.png +++ /dev/null diff --git a/res/drawable-hdpi/action_toggle_list_dark.png b/res/drawable-hdpi/action_toggle_list_dark.png Binary files differnew file mode 100644 index 00000000..d0ec1a5d --- /dev/null +++ b/res/drawable-hdpi/action_toggle_list_dark.png diff --git a/res/drawable-hdpi/action_toggle_list_light.png b/res/drawable-hdpi/action_toggle_list_light.png Binary files differnew file mode 100644 index 00000000..60ec88be --- /dev/null +++ b/res/drawable-hdpi/action_toggle_list_light.png diff --git a/res/drawable-hdpi/actionbar_background.9.png b/res/drawable-hdpi/actionbar_background.9.png Binary files differdeleted file mode 100644 index 9ce38a61..00000000 --- a/res/drawable-hdpi/actionbar_background.9.png +++ /dev/null diff --git a/res/drawable-hdpi/album_art_background.png b/res/drawable-hdpi/album_art_background.png Binary files differdeleted file mode 100644 index f0757695..00000000 --- a/res/drawable-hdpi/album_art_background.png +++ /dev/null diff --git a/res/drawable-hdpi/download_cached.png b/res/drawable-hdpi/download_cached.png Binary files differnew file mode 100644 index 00000000..d935cb2c --- /dev/null +++ b/res/drawable-hdpi/download_cached.png diff --git a/res/drawable-hdpi/download_none_dark.png b/res/drawable-hdpi/download_none_dark.png Binary files differnew file mode 100644 index 00000000..a074c10d --- /dev/null +++ b/res/drawable-hdpi/download_none_dark.png diff --git a/res/drawable-hdpi/download_none_light.png b/res/drawable-hdpi/download_none_light.png Binary files differnew file mode 100644 index 00000000..21544e5f --- /dev/null +++ b/res/drawable-hdpi/download_none_light.png diff --git a/res/drawable-hdpi/download_pinned.png b/res/drawable-hdpi/download_pinned.png Binary files differnew file mode 100644 index 00000000..b5b6dfb1 --- /dev/null +++ b/res/drawable-hdpi/download_pinned.png diff --git a/res/drawable-hdpi/downloading.png b/res/drawable-hdpi/downloading.png Binary files differdeleted file mode 100644 index afff39a9..00000000 --- a/res/drawable-hdpi/downloading.png +++ /dev/null diff --git a/res/drawable-hdpi/downloading_dark.png b/res/drawable-hdpi/downloading_dark.png Binary files differnew file mode 100644 index 00000000..3ccb1837 --- /dev/null +++ b/res/drawable-hdpi/downloading_dark.png diff --git a/res/drawable-hdpi/downloading_light.png b/res/drawable-hdpi/downloading_light.png Binary files differnew file mode 100644 index 00000000..07be3016 --- /dev/null +++ b/res/drawable-hdpi/downloading_light.png diff --git a/res/drawable-hdpi/ic_action_volume_dark.png b/res/drawable-hdpi/ic_action_volume_dark.png Binary files differnew file mode 100644 index 00000000..62550655 --- /dev/null +++ b/res/drawable-hdpi/ic_action_volume_dark.png diff --git a/res/drawable-hdpi/ic_action_volume_light.png b/res/drawable-hdpi/ic_action_volume_light.png Binary files differnew file mode 100644 index 00000000..1b1d182c --- /dev/null +++ b/res/drawable-hdpi/ic_action_volume_light.png diff --git a/res/drawable-hdpi/ic_drawer.png b/res/drawable-hdpi/ic_drawer.png Binary files differnew file mode 100644 index 00000000..c59f601c --- /dev/null +++ b/res/drawable-hdpi/ic_drawer.png diff --git a/res/drawable-hdpi/ic_menu_bookmark_dark.png b/res/drawable-hdpi/ic_menu_bookmark_dark.png Binary files differnew file mode 100644 index 00000000..e7cd08e4 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_bookmark_dark.png diff --git a/res/drawable-hdpi/ic_menu_bookmark_light.png b/res/drawable-hdpi/ic_menu_bookmark_light.png Binary files differnew file mode 100644 index 00000000..fdb46da3 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_bookmark_light.png diff --git a/res/drawable-hdpi/ic_menu_chat_dark.png b/res/drawable-hdpi/ic_menu_chat_dark.png Binary files differindex be04b06e..75363fce 100644 --- a/res/drawable-hdpi/ic_menu_chat_dark.png +++ b/res/drawable-hdpi/ic_menu_chat_dark.png diff --git a/res/drawable-hdpi/ic_menu_chat_light.png b/res/drawable-hdpi/ic_menu_chat_light.png Binary files differindex 3f58695c..e28933e4 100644 --- a/res/drawable-hdpi/ic_menu_chat_light.png +++ b/res/drawable-hdpi/ic_menu_chat_light.png diff --git a/res/drawable-hdpi/ic_menu_chat_send_dark.png b/res/drawable-hdpi/ic_menu_chat_send_dark.png Binary files differindex bd37dc59..c0e9b372 100644 --- a/res/drawable-hdpi/ic_menu_chat_send_dark.png +++ b/res/drawable-hdpi/ic_menu_chat_send_dark.png diff --git a/res/drawable-hdpi/ic_menu_chat_send_light.png b/res/drawable-hdpi/ic_menu_chat_send_light.png Binary files differindex 0c870d2c..ebcfe9e8 100644 --- a/res/drawable-hdpi/ic_menu_chat_send_light.png +++ b/res/drawable-hdpi/ic_menu_chat_send_light.png diff --git a/res/drawable-hdpi/ic_menu_exit.png b/res/drawable-hdpi/ic_menu_exit.png Binary files differdeleted file mode 100644 index 847a1ed3..00000000 --- a/res/drawable-hdpi/ic_menu_exit.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_menu_help.png b/res/drawable-hdpi/ic_menu_help.png Binary files differdeleted file mode 100644 index 9f11f434..00000000 --- a/res/drawable-hdpi/ic_menu_help.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_menu_library_dark.png b/res/drawable-hdpi/ic_menu_library_dark.png Binary files differnew file mode 100644 index 00000000..717cb3e1 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_library_dark.png diff --git a/res/drawable-hdpi/ic_menu_library_light.png b/res/drawable-hdpi/ic_menu_library_light.png Binary files differnew file mode 100644 index 00000000..17a45d77 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_library_light.png diff --git a/res/drawable-hdpi/ic_menu_playlist_dark.png b/res/drawable-hdpi/ic_menu_playlist_dark.png Binary files differnew file mode 100644 index 00000000..8e3babc7 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_playlist_dark.png diff --git a/res/drawable-hdpi/ic_menu_playlist_light.png b/res/drawable-hdpi/ic_menu_playlist_light.png Binary files differnew file mode 100644 index 00000000..4131dba4 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_playlist_light.png diff --git a/res/drawable-hdpi/ic_menu_podcast_dark.png b/res/drawable-hdpi/ic_menu_podcast_dark.png Binary files differnew file mode 100644 index 00000000..d1d62d03 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_podcast_dark.png diff --git a/res/drawable-hdpi/ic_menu_podcast_light.png b/res/drawable-hdpi/ic_menu_podcast_light.png Binary files differnew file mode 100644 index 00000000..4ce1b787 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_podcast_light.png diff --git a/res/drawable-hdpi/ic_menu_refresh_dark.png b/res/drawable-hdpi/ic_menu_refresh_dark.png Binary files differnew file mode 100644 index 00000000..2795cfa9 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_refresh_dark.png diff --git a/res/drawable-hdpi/ic_menu_refresh_light.png b/res/drawable-hdpi/ic_menu_refresh_light.png Binary files differnew file mode 100644 index 00000000..86d1b042 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_refresh_light.png diff --git a/res/drawable-hdpi/ic_menu_remove_dark.png b/res/drawable-hdpi/ic_menu_remove_dark.png Binary files differnew file mode 100644 index 00000000..878b378a --- /dev/null +++ b/res/drawable-hdpi/ic_menu_remove_dark.png diff --git a/res/drawable-hdpi/ic_menu_remove_light.png b/res/drawable-hdpi/ic_menu_remove_light.png Binary files differnew file mode 100644 index 00000000..ece5ad8d --- /dev/null +++ b/res/drawable-hdpi/ic_menu_remove_light.png diff --git a/res/drawable-hdpi/ic_menu_save_dark.png b/res/drawable-hdpi/ic_menu_save_dark.png Binary files differnew file mode 100644 index 00000000..b80828bf --- /dev/null +++ b/res/drawable-hdpi/ic_menu_save_dark.png diff --git a/res/drawable-hdpi/ic_menu_save_light.png b/res/drawable-hdpi/ic_menu_save_light.png Binary files differnew file mode 100644 index 00000000..a3a5e23a --- /dev/null +++ b/res/drawable-hdpi/ic_menu_save_light.png diff --git a/res/drawable-hdpi/ic_menu_search_dark.png b/res/drawable-hdpi/ic_menu_search_dark.png Binary files differnew file mode 100644 index 00000000..ef2b3013 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_search_dark.png diff --git a/res/drawable-hdpi/ic_menu_search_light.png b/res/drawable-hdpi/ic_menu_search_light.png Binary files differnew file mode 100644 index 00000000..756937df --- /dev/null +++ b/res/drawable-hdpi/ic_menu_search_light.png diff --git a/res/drawable-hdpi/ic_menu_settings.png b/res/drawable-hdpi/ic_menu_settings.png Binary files differdeleted file mode 100644 index 48775c1e..00000000 --- a/res/drawable-hdpi/ic_menu_settings.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_menu_settings_dark.png b/res/drawable-hdpi/ic_menu_settings_dark.png Binary files differnew file mode 100644 index 00000000..d6dd17ec --- /dev/null +++ b/res/drawable-hdpi/ic_menu_settings_dark.png diff --git a/res/drawable-hdpi/ic_menu_settings_light.png b/res/drawable-hdpi/ic_menu_settings_light.png Binary files differnew file mode 100644 index 00000000..70c29951 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_settings_light.png diff --git a/res/drawable-hdpi/ic_menu_shuffle.png b/res/drawable-hdpi/ic_menu_shuffle.png Binary files differdeleted file mode 100644 index 0613965c..00000000 --- a/res/drawable-hdpi/ic_menu_shuffle.png +++ /dev/null diff --git a/res/drawable-hdpi/ic_menu_shuffle_dark.png b/res/drawable-hdpi/ic_menu_shuffle_dark.png Binary files differnew file mode 100644 index 00000000..f77cfed2 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_shuffle_dark.png diff --git a/res/drawable-hdpi/ic_menu_shuffle_light.png b/res/drawable-hdpi/ic_menu_shuffle_light.png Binary files differnew file mode 100644 index 00000000..ded93939 --- /dev/null +++ b/res/drawable-hdpi/ic_menu_shuffle_light.png diff --git a/res/drawable-hdpi/launch.png b/res/drawable-hdpi/launch.png Binary files differindex 72f80486..9caa6675 100644 --- a/res/drawable-hdpi/launch.png +++ b/res/drawable-hdpi/launch.png diff --git a/res/drawable-hdpi/list_item_more.9.png b/res/drawable-hdpi/list_item_more.9.png Binary files differdeleted file mode 100644 index 79ca860d..00000000 --- a/res/drawable-hdpi/list_item_more.9.png +++ /dev/null diff --git a/res/drawable-hdpi/list_item_more_saved.9.png b/res/drawable-hdpi/list_item_more_saved.9.png Binary files differdeleted file mode 100644 index f3805bfb..00000000 --- a/res/drawable-hdpi/list_item_more_saved.9.png +++ /dev/null diff --git a/res/drawable-hdpi/list_item_more_shaded.9.png b/res/drawable-hdpi/list_item_more_shaded.9.png Binary files differdeleted file mode 100644 index 99c2f5b8..00000000 --- a/res/drawable-hdpi/list_item_more_shaded.9.png +++ /dev/null diff --git a/res/drawable-hdpi/main_offline.png b/res/drawable-hdpi/main_offline.png Binary files differdeleted file mode 100644 index a1d27cec..00000000 --- a/res/drawable-hdpi/main_offline.png +++ /dev/null diff --git a/res/drawable-hdpi/main_offline_dark.png b/res/drawable-hdpi/main_offline_dark.png Binary files differnew file mode 100644 index 00000000..a594530d --- /dev/null +++ b/res/drawable-hdpi/main_offline_dark.png diff --git a/res/drawable-hdpi/main_offline_light.png b/res/drawable-hdpi/main_offline_light.png Binary files differindex 69bee782..cabca581 100644 --- a/res/drawable-hdpi/main_offline_light.png +++ b/res/drawable-hdpi/main_offline_light.png diff --git a/res/drawable-hdpi/main_select_server.png b/res/drawable-hdpi/main_select_server.png Binary files differdeleted file mode 100644 index c2cefead..00000000 --- a/res/drawable-hdpi/main_select_server.png +++ /dev/null diff --git a/res/drawable-hdpi/main_select_server_dark.png b/res/drawable-hdpi/main_select_server_dark.png Binary files differnew file mode 100644 index 00000000..e3a9dd5d --- /dev/null +++ b/res/drawable-hdpi/main_select_server_dark.png diff --git a/res/drawable-hdpi/main_select_server_light.png b/res/drawable-hdpi/main_select_server_light.png Binary files differnew file mode 100644 index 00000000..4606410d --- /dev/null +++ b/res/drawable-hdpi/main_select_server_light.png diff --git a/res/drawable-hdpi/media_backward.png b/res/drawable-hdpi/media_backward.png Binary files differdeleted file mode 100644 index 3bb85e68..00000000 --- a/res/drawable-hdpi/media_backward.png +++ /dev/null diff --git a/res/drawable-hdpi/media_backward_dark.png b/res/drawable-hdpi/media_backward_dark.png Binary files differnew file mode 100644 index 00000000..b1dde4f5 --- /dev/null +++ b/res/drawable-hdpi/media_backward_dark.png diff --git a/res/drawable-hdpi/media_backward_light.png b/res/drawable-hdpi/media_backward_light.png Binary files differindex 14188c86..3e277267 100644 --- a/res/drawable-hdpi/media_backward_light.png +++ b/res/drawable-hdpi/media_backward_light.png diff --git a/res/drawable-hdpi/media_forward.png b/res/drawable-hdpi/media_forward.png Binary files differdeleted file mode 100644 index cf39f1f0..00000000 --- a/res/drawable-hdpi/media_forward.png +++ /dev/null diff --git a/res/drawable-hdpi/media_forward_dark.png b/res/drawable-hdpi/media_forward_dark.png Binary files differnew file mode 100644 index 00000000..eb2546c7 --- /dev/null +++ b/res/drawable-hdpi/media_forward_dark.png diff --git a/res/drawable-hdpi/media_forward_light.png b/res/drawable-hdpi/media_forward_light.png Binary files differindex 9e172d8f..185e3c39 100644 --- a/res/drawable-hdpi/media_forward_light.png +++ b/res/drawable-hdpi/media_forward_light.png diff --git a/res/drawable-hdpi/media_pause.png b/res/drawable-hdpi/media_pause.png Binary files differdeleted file mode 100644 index d4cab525..00000000 --- a/res/drawable-hdpi/media_pause.png +++ /dev/null diff --git a/res/drawable-hdpi/media_pause_dark.png b/res/drawable-hdpi/media_pause_dark.png Binary files differnew file mode 100644 index 00000000..b057588e --- /dev/null +++ b/res/drawable-hdpi/media_pause_dark.png diff --git a/res/drawable-hdpi/media_pause_light.png b/res/drawable-hdpi/media_pause_light.png Binary files differindex 8ebf9b45..e01815e3 100644 --- a/res/drawable-hdpi/media_pause_light.png +++ b/res/drawable-hdpi/media_pause_light.png diff --git a/res/drawable-hdpi/media_start.png b/res/drawable-hdpi/media_start.png Binary files differdeleted file mode 100644 index 2af5996f..00000000 --- a/res/drawable-hdpi/media_start.png +++ /dev/null diff --git a/res/drawable-hdpi/media_start_dark.png b/res/drawable-hdpi/media_start_dark.png Binary files differnew file mode 100644 index 00000000..dbfd337a --- /dev/null +++ b/res/drawable-hdpi/media_start_dark.png diff --git a/res/drawable-hdpi/media_start_light.png b/res/drawable-hdpi/media_start_light.png Binary files differindex 45cad73c..e4310efc 100644 --- a/res/drawable-hdpi/media_start_light.png +++ b/res/drawable-hdpi/media_start_light.png diff --git a/res/drawable-hdpi/media_stop.png b/res/drawable-hdpi/media_stop.png Binary files differdeleted file mode 100644 index 329eb906..00000000 --- a/res/drawable-hdpi/media_stop.png +++ /dev/null diff --git a/res/drawable-hdpi/media_stop_dark.png b/res/drawable-hdpi/media_stop_dark.png Binary files differnew file mode 100644 index 00000000..5ceb39f3 --- /dev/null +++ b/res/drawable-hdpi/media_stop_dark.png diff --git a/res/drawable-hdpi/media_stop_light.png b/res/drawable-hdpi/media_stop_light.png Binary files differindex 110d538e..8deca73e 100644 --- a/res/drawable-hdpi/media_stop_light.png +++ b/res/drawable-hdpi/media_stop_light.png diff --git a/res/drawable-hdpi/menu_browse.png b/res/drawable-hdpi/menu_browse.png Binary files differdeleted file mode 100644 index 54296909..00000000 --- a/res/drawable-hdpi/menu_browse.png +++ /dev/null diff --git a/res/drawable-hdpi/menu_home.png b/res/drawable-hdpi/menu_home.png Binary files differdeleted file mode 100644 index 3cec6246..00000000 --- a/res/drawable-hdpi/menu_home.png +++ /dev/null diff --git a/res/drawable-hdpi/menu_now_playing.png b/res/drawable-hdpi/menu_now_playing.png Binary files differdeleted file mode 100644 index 6ce5629a..00000000 --- a/res/drawable-hdpi/menu_now_playing.png +++ /dev/null diff --git a/res/drawable-hdpi/menu_playlists.png b/res/drawable-hdpi/menu_playlists.png Binary files differdeleted file mode 100644 index e9e83e3d..00000000 --- a/res/drawable-hdpi/menu_playlists.png +++ /dev/null diff --git a/res/drawable-hdpi/notification_close.png b/res/drawable-hdpi/notification_close.png Binary files differnew file mode 100644 index 00000000..916c9a0f --- /dev/null +++ b/res/drawable-hdpi/notification_close.png diff --git a/res/drawable-hdpi/notification_next.png b/res/drawable-hdpi/notification_next.png Binary files differindex 5835f654..078c310f 100644 --- a/res/drawable-hdpi/notification_next.png +++ b/res/drawable-hdpi/notification_next.png diff --git a/res/drawable-hdpi/notification_pause.png b/res/drawable-hdpi/notification_pause.png Binary files differindex 3324f88f..16627e44 100644 --- a/res/drawable-hdpi/notification_pause.png +++ b/res/drawable-hdpi/notification_pause.png diff --git a/res/drawable-hdpi/notification_play.png b/res/drawable-hdpi/notification_play.png Binary files differindex 8c95b6a5..02f38944 100644 --- a/res/drawable-hdpi/notification_play.png +++ b/res/drawable-hdpi/notification_play.png diff --git a/res/drawable-hdpi/notification_prev.png b/res/drawable-hdpi/notification_prev.png Binary files differdeleted file mode 100644 index 73fb16f2..00000000 --- a/res/drawable-hdpi/notification_prev.png +++ /dev/null diff --git a/res/drawable-hdpi/notification_previous.png b/res/drawable-hdpi/notification_previous.png Binary files differnew file mode 100644 index 00000000..9d10abd9 --- /dev/null +++ b/res/drawable-hdpi/notification_previous.png diff --git a/res/drawable-hdpi/notification_stop.png b/res/drawable-hdpi/notification_stop.png Binary files differdeleted file mode 100644 index ab98e188..00000000 --- a/res/drawable-hdpi/notification_stop.png +++ /dev/null diff --git a/res/drawable-hdpi/now_playing.png b/res/drawable-hdpi/now_playing.png Binary files differnew file mode 100644 index 00000000..02f38944 --- /dev/null +++ b/res/drawable-hdpi/now_playing.png diff --git a/res/drawable-hdpi/refresh.png b/res/drawable-hdpi/refresh.png Binary files differdeleted file mode 100644 index 2f887c26..00000000 --- a/res/drawable-hdpi/refresh.png +++ /dev/null diff --git a/res/drawable-hdpi/search.png b/res/drawable-hdpi/search.png Binary files differdeleted file mode 100644 index 43d8c87e..00000000 --- a/res/drawable-hdpi/search.png +++ /dev/null diff --git a/res/drawable-hdpi/stat_notify_download.png b/res/drawable-hdpi/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..aa1b6c92 --- /dev/null +++ b/res/drawable-hdpi/stat_notify_download.png diff --git a/res/drawable-hdpi/stat_notify_playing.png b/res/drawable-hdpi/stat_notify_playing.png Binary files differindex bfd3e6a5..02f38944 100644 --- a/res/drawable-hdpi/stat_notify_playing.png +++ b/res/drawable-hdpi/stat_notify_playing.png diff --git a/res/drawable-hdpi/volume.png b/res/drawable-hdpi/volume.png Binary files differdeleted file mode 100644 index 95134dfd..00000000 --- a/res/drawable-hdpi/volume.png +++ /dev/null diff --git a/res/drawable-mdpi-v11/notification_close.png b/res/drawable-mdpi-v11/notification_close.png Binary files differnew file mode 100644 index 00000000..a056fe61 --- /dev/null +++ b/res/drawable-mdpi-v11/notification_close.png diff --git a/res/drawable-mdpi-v11/notification_next.png b/res/drawable-mdpi-v11/notification_next.png Binary files differnew file mode 100644 index 00000000..7297577f --- /dev/null +++ b/res/drawable-mdpi-v11/notification_next.png diff --git a/res/drawable-mdpi-v11/notification_pause.png b/res/drawable-mdpi-v11/notification_pause.png Binary files differnew file mode 100644 index 00000000..5d3ca3f2 --- /dev/null +++ b/res/drawable-mdpi-v11/notification_pause.png diff --git a/res/drawable-mdpi-v11/notification_play.png b/res/drawable-mdpi-v11/notification_play.png Binary files differnew file mode 100644 index 00000000..999ce798 --- /dev/null +++ b/res/drawable-mdpi-v11/notification_play.png diff --git a/res/drawable-mdpi-v11/notification_previous.png b/res/drawable-mdpi-v11/notification_previous.png Binary files differnew file mode 100644 index 00000000..55a1f326 --- /dev/null +++ b/res/drawable-mdpi-v11/notification_previous.png diff --git a/res/drawable-mdpi-v11/stat_notify_download.png b/res/drawable-mdpi-v11/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..4164e0fa --- /dev/null +++ b/res/drawable-mdpi-v11/stat_notify_download.png diff --git a/res/drawable-mdpi-v11/stat_notify_playing.png b/res/drawable-mdpi-v11/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..999ce798 --- /dev/null +++ b/res/drawable-mdpi-v11/stat_notify_playing.png diff --git a/res/drawable-mdpi/action_toggle_list_dark.png b/res/drawable-mdpi/action_toggle_list_dark.png Binary files differnew file mode 100644 index 00000000..ace7fcee --- /dev/null +++ b/res/drawable-mdpi/action_toggle_list_dark.png diff --git a/res/drawable-mdpi/action_toggle_list_light.png b/res/drawable-mdpi/action_toggle_list_light.png Binary files differnew file mode 100644 index 00000000..fa6432da --- /dev/null +++ b/res/drawable-mdpi/action_toggle_list_light.png diff --git a/res/drawable-mdpi/download_cached.png b/res/drawable-mdpi/download_cached.png Binary files differnew file mode 100644 index 00000000..fa02cc7c --- /dev/null +++ b/res/drawable-mdpi/download_cached.png diff --git a/res/drawable-mdpi/download_none_dark.png b/res/drawable-mdpi/download_none_dark.png Binary files differnew file mode 100644 index 00000000..b6d614fc --- /dev/null +++ b/res/drawable-mdpi/download_none_dark.png diff --git a/res/drawable-mdpi/download_none_light.png b/res/drawable-mdpi/download_none_light.png Binary files differnew file mode 100644 index 00000000..2485c570 --- /dev/null +++ b/res/drawable-mdpi/download_none_light.png diff --git a/res/drawable-mdpi/download_pinned.png b/res/drawable-mdpi/download_pinned.png Binary files differnew file mode 100644 index 00000000..8e6e8e7a --- /dev/null +++ b/res/drawable-mdpi/download_pinned.png diff --git a/res/drawable-mdpi/downloading_dark.png b/res/drawable-mdpi/downloading_dark.png Binary files differnew file mode 100644 index 00000000..ae6c5c9c --- /dev/null +++ b/res/drawable-mdpi/downloading_dark.png diff --git a/res/drawable-mdpi/downloading_light.png b/res/drawable-mdpi/downloading_light.png Binary files differnew file mode 100644 index 00000000..abd5b748 --- /dev/null +++ b/res/drawable-mdpi/downloading_light.png diff --git a/res/drawable-mdpi/ic_action_volume_dark.png b/res/drawable-mdpi/ic_action_volume_dark.png Binary files differnew file mode 100644 index 00000000..2b5f1d11 --- /dev/null +++ b/res/drawable-mdpi/ic_action_volume_dark.png diff --git a/res/drawable-mdpi/ic_action_volume_light.png b/res/drawable-mdpi/ic_action_volume_light.png Binary files differnew file mode 100644 index 00000000..47071ccf --- /dev/null +++ b/res/drawable-mdpi/ic_action_volume_light.png diff --git a/res/drawable-mdpi/ic_drawer.png b/res/drawable-mdpi/ic_drawer.png Binary files differnew file mode 100644 index 00000000..1ed2c56e --- /dev/null +++ b/res/drawable-mdpi/ic_drawer.png diff --git a/res/drawable-mdpi/ic_menu_bookmark_dark.png b/res/drawable-mdpi/ic_menu_bookmark_dark.png Binary files differnew file mode 100644 index 00000000..3360f37e --- /dev/null +++ b/res/drawable-mdpi/ic_menu_bookmark_dark.png diff --git a/res/drawable-mdpi/ic_menu_bookmark_light.png b/res/drawable-mdpi/ic_menu_bookmark_light.png Binary files differnew file mode 100644 index 00000000..b4d916fb --- /dev/null +++ b/res/drawable-mdpi/ic_menu_bookmark_light.png diff --git a/res/drawable-mdpi/ic_menu_chat_dark.png b/res/drawable-mdpi/ic_menu_chat_dark.png Binary files differnew file mode 100644 index 00000000..74d98888 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_chat_dark.png diff --git a/res/drawable-mdpi/ic_menu_chat_light.png b/res/drawable-mdpi/ic_menu_chat_light.png Binary files differnew file mode 100644 index 00000000..468c1220 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_chat_light.png diff --git a/res/drawable-mdpi/ic_menu_chat_send_dark.png b/res/drawable-mdpi/ic_menu_chat_send_dark.png Binary files differnew file mode 100644 index 00000000..91db4a4a --- /dev/null +++ b/res/drawable-mdpi/ic_menu_chat_send_dark.png diff --git a/res/drawable-mdpi/ic_menu_chat_send_light.png b/res/drawable-mdpi/ic_menu_chat_send_light.png Binary files differnew file mode 100644 index 00000000..f2a3e724 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_chat_send_light.png diff --git a/res/drawable-mdpi/ic_menu_library_dark.png b/res/drawable-mdpi/ic_menu_library_dark.png Binary files differnew file mode 100644 index 00000000..0102d7ad --- /dev/null +++ b/res/drawable-mdpi/ic_menu_library_dark.png diff --git a/res/drawable-mdpi/ic_menu_library_light.png b/res/drawable-mdpi/ic_menu_library_light.png Binary files differnew file mode 100644 index 00000000..a30b4d39 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_library_light.png diff --git a/res/drawable-mdpi/ic_menu_playlist_dark.png b/res/drawable-mdpi/ic_menu_playlist_dark.png Binary files differnew file mode 100644 index 00000000..ebf00427 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_playlist_dark.png diff --git a/res/drawable-mdpi/ic_menu_playlist_light.png b/res/drawable-mdpi/ic_menu_playlist_light.png Binary files differnew file mode 100644 index 00000000..e248a488 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_playlist_light.png diff --git a/res/drawable-mdpi/ic_menu_podcast_dark.png b/res/drawable-mdpi/ic_menu_podcast_dark.png Binary files differnew file mode 100644 index 00000000..ad69156a --- /dev/null +++ b/res/drawable-mdpi/ic_menu_podcast_dark.png diff --git a/res/drawable-mdpi/ic_menu_podcast_light.png b/res/drawable-mdpi/ic_menu_podcast_light.png Binary files differnew file mode 100644 index 00000000..c15cb03f --- /dev/null +++ b/res/drawable-mdpi/ic_menu_podcast_light.png diff --git a/res/drawable-mdpi/ic_menu_refresh_dark.png b/res/drawable-mdpi/ic_menu_refresh_dark.png Binary files differnew file mode 100644 index 00000000..554c07dc --- /dev/null +++ b/res/drawable-mdpi/ic_menu_refresh_dark.png diff --git a/res/drawable-mdpi/ic_menu_refresh_light.png b/res/drawable-mdpi/ic_menu_refresh_light.png Binary files differnew file mode 100644 index 00000000..a2d90c16 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_refresh_light.png diff --git a/res/drawable-mdpi/ic_menu_remove_dark.png b/res/drawable-mdpi/ic_menu_remove_dark.png Binary files differnew file mode 100644 index 00000000..5ba24546 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_remove_dark.png diff --git a/res/drawable-mdpi/ic_menu_remove_light.png b/res/drawable-mdpi/ic_menu_remove_light.png Binary files differnew file mode 100644 index 00000000..93483b6c --- /dev/null +++ b/res/drawable-mdpi/ic_menu_remove_light.png diff --git a/res/drawable-mdpi/ic_menu_save_dark.png b/res/drawable-mdpi/ic_menu_save_dark.png Binary files differnew file mode 100644 index 00000000..89aa17cc --- /dev/null +++ b/res/drawable-mdpi/ic_menu_save_dark.png diff --git a/res/drawable-mdpi/ic_menu_save_light.png b/res/drawable-mdpi/ic_menu_save_light.png Binary files differnew file mode 100644 index 00000000..dcb3a2f6 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_save_light.png diff --git a/res/drawable-mdpi/ic_menu_search_dark.png b/res/drawable-mdpi/ic_menu_search_dark.png Binary files differnew file mode 100644 index 00000000..076085c5 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_search_dark.png diff --git a/res/drawable-mdpi/ic_menu_search_light.png b/res/drawable-mdpi/ic_menu_search_light.png Binary files differnew file mode 100644 index 00000000..026c8498 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_search_light.png diff --git a/res/drawable-mdpi/ic_menu_settings_dark.png b/res/drawable-mdpi/ic_menu_settings_dark.png Binary files differnew file mode 100644 index 00000000..fc2bf8c3 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_settings_dark.png diff --git a/res/drawable-mdpi/ic_menu_settings_light.png b/res/drawable-mdpi/ic_menu_settings_light.png Binary files differnew file mode 100644 index 00000000..0e65c682 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_settings_light.png diff --git a/res/drawable-mdpi/ic_menu_shuffle_dark.png b/res/drawable-mdpi/ic_menu_shuffle_dark.png Binary files differnew file mode 100644 index 00000000..7007fde5 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_shuffle_dark.png diff --git a/res/drawable-mdpi/ic_menu_shuffle_light.png b/res/drawable-mdpi/ic_menu_shuffle_light.png Binary files differnew file mode 100644 index 00000000..4d07c3b4 --- /dev/null +++ b/res/drawable-mdpi/ic_menu_shuffle_light.png diff --git a/res/drawable-mdpi/launch.png b/res/drawable-mdpi/launch.png Binary files differindex c07fc594..22e094eb 100644 --- a/res/drawable-mdpi/launch.png +++ b/res/drawable-mdpi/launch.png diff --git a/res/drawable-mdpi/main_offline_dark.png b/res/drawable-mdpi/main_offline_dark.png Binary files differnew file mode 100644 index 00000000..4990fb8e --- /dev/null +++ b/res/drawable-mdpi/main_offline_dark.png diff --git a/res/drawable-mdpi/main_offline_light.png b/res/drawable-mdpi/main_offline_light.png Binary files differnew file mode 100644 index 00000000..e70ec1c2 --- /dev/null +++ b/res/drawable-mdpi/main_offline_light.png diff --git a/res/drawable-mdpi/main_select_server_dark.png b/res/drawable-mdpi/main_select_server_dark.png Binary files differnew file mode 100644 index 00000000..119b1573 --- /dev/null +++ b/res/drawable-mdpi/main_select_server_dark.png diff --git a/res/drawable-mdpi/main_select_server_light.png b/res/drawable-mdpi/main_select_server_light.png Binary files differnew file mode 100644 index 00000000..7d8dad34 --- /dev/null +++ b/res/drawable-mdpi/main_select_server_light.png diff --git a/res/drawable-mdpi/media_backward_dark.png b/res/drawable-mdpi/media_backward_dark.png Binary files differnew file mode 100644 index 00000000..4f2233a1 --- /dev/null +++ b/res/drawable-mdpi/media_backward_dark.png diff --git a/res/drawable-mdpi/media_backward_light.png b/res/drawable-mdpi/media_backward_light.png Binary files differnew file mode 100644 index 00000000..425f2df7 --- /dev/null +++ b/res/drawable-mdpi/media_backward_light.png diff --git a/res/drawable-mdpi/media_forward_dark.png b/res/drawable-mdpi/media_forward_dark.png Binary files differnew file mode 100644 index 00000000..1641c0fa --- /dev/null +++ b/res/drawable-mdpi/media_forward_dark.png diff --git a/res/drawable-mdpi/media_forward_light.png b/res/drawable-mdpi/media_forward_light.png Binary files differnew file mode 100644 index 00000000..2e66868f --- /dev/null +++ b/res/drawable-mdpi/media_forward_light.png diff --git a/res/drawable-mdpi/media_pause_dark.png b/res/drawable-mdpi/media_pause_dark.png Binary files differnew file mode 100644 index 00000000..3580dab4 --- /dev/null +++ b/res/drawable-mdpi/media_pause_dark.png diff --git a/res/drawable-mdpi/media_pause_light.png b/res/drawable-mdpi/media_pause_light.png Binary files differnew file mode 100644 index 00000000..7e9ade73 --- /dev/null +++ b/res/drawable-mdpi/media_pause_light.png diff --git a/res/drawable-mdpi/media_start_dark.png b/res/drawable-mdpi/media_start_dark.png Binary files differnew file mode 100644 index 00000000..a2f198ae --- /dev/null +++ b/res/drawable-mdpi/media_start_dark.png diff --git a/res/drawable-mdpi/media_start_light.png b/res/drawable-mdpi/media_start_light.png Binary files differnew file mode 100644 index 00000000..d69107ba --- /dev/null +++ b/res/drawable-mdpi/media_start_light.png diff --git a/res/drawable-mdpi/media_stop_dark.png b/res/drawable-mdpi/media_stop_dark.png Binary files differnew file mode 100644 index 00000000..944482e6 --- /dev/null +++ b/res/drawable-mdpi/media_stop_dark.png diff --git a/res/drawable-mdpi/media_stop_light.png b/res/drawable-mdpi/media_stop_light.png Binary files differnew file mode 100644 index 00000000..ff1932a1 --- /dev/null +++ b/res/drawable-mdpi/media_stop_light.png diff --git a/res/drawable-mdpi/notification_close.png b/res/drawable-mdpi/notification_close.png Binary files differnew file mode 100644 index 00000000..2a8f9a36 --- /dev/null +++ b/res/drawable-mdpi/notification_close.png diff --git a/res/drawable-mdpi/notification_next.png b/res/drawable-mdpi/notification_next.png Binary files differnew file mode 100644 index 00000000..f85d45a5 --- /dev/null +++ b/res/drawable-mdpi/notification_next.png diff --git a/res/drawable-mdpi/notification_pause.png b/res/drawable-mdpi/notification_pause.png Binary files differnew file mode 100644 index 00000000..06c3cf9d --- /dev/null +++ b/res/drawable-mdpi/notification_pause.png diff --git a/res/drawable-mdpi/notification_play.png b/res/drawable-mdpi/notification_play.png Binary files differnew file mode 100644 index 00000000..0248c1cc --- /dev/null +++ b/res/drawable-mdpi/notification_play.png diff --git a/res/drawable-mdpi/notification_previous.png b/res/drawable-mdpi/notification_previous.png Binary files differnew file mode 100644 index 00000000..167d7d05 --- /dev/null +++ b/res/drawable-mdpi/notification_previous.png diff --git a/res/drawable-mdpi/now_playing.png b/res/drawable-mdpi/now_playing.png Binary files differnew file mode 100644 index 00000000..0248c1cc --- /dev/null +++ b/res/drawable-mdpi/now_playing.png diff --git a/res/drawable-mdpi/stat_notify_download.png b/res/drawable-mdpi/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..4c2a22de --- /dev/null +++ b/res/drawable-mdpi/stat_notify_download.png diff --git a/res/drawable-mdpi/stat_notify_playing.png b/res/drawable-mdpi/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..0248c1cc --- /dev/null +++ b/res/drawable-mdpi/stat_notify_playing.png diff --git a/res/drawable-xhdpi-v11/notification_close.png b/res/drawable-xhdpi-v11/notification_close.png Binary files differnew file mode 100644 index 00000000..f1013578 --- /dev/null +++ b/res/drawable-xhdpi-v11/notification_close.png diff --git a/res/drawable-xhdpi-v11/notification_next.png b/res/drawable-xhdpi-v11/notification_next.png Binary files differnew file mode 100644 index 00000000..ad070680 --- /dev/null +++ b/res/drawable-xhdpi-v11/notification_next.png diff --git a/res/drawable-xhdpi-v11/notification_pause.png b/res/drawable-xhdpi-v11/notification_pause.png Binary files differnew file mode 100644 index 00000000..709602aa --- /dev/null +++ b/res/drawable-xhdpi-v11/notification_pause.png diff --git a/res/drawable-xhdpi-v11/notification_play.png b/res/drawable-xhdpi-v11/notification_play.png Binary files differnew file mode 100644 index 00000000..e2bafa6a --- /dev/null +++ b/res/drawable-xhdpi-v11/notification_play.png diff --git a/res/drawable-xhdpi-v11/notification_previous.png b/res/drawable-xhdpi-v11/notification_previous.png Binary files differnew file mode 100644 index 00000000..d22488cb --- /dev/null +++ b/res/drawable-xhdpi-v11/notification_previous.png diff --git a/res/drawable-xhdpi-v11/stat_notify_download.png b/res/drawable-xhdpi-v11/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..96ceb383 --- /dev/null +++ b/res/drawable-xhdpi-v11/stat_notify_download.png diff --git a/res/drawable-xhdpi-v11/stat_notify_playing.png b/res/drawable-xhdpi-v11/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..e2bafa6a --- /dev/null +++ b/res/drawable-xhdpi-v11/stat_notify_playing.png diff --git a/res/drawable-xhdpi/action_toggle_list_dark.png b/res/drawable-xhdpi/action_toggle_list_dark.png Binary files differnew file mode 100644 index 00000000..92003c6b --- /dev/null +++ b/res/drawable-xhdpi/action_toggle_list_dark.png diff --git a/res/drawable-xhdpi/action_toggle_list_light.png b/res/drawable-xhdpi/action_toggle_list_light.png Binary files differnew file mode 100644 index 00000000..a4007ea5 --- /dev/null +++ b/res/drawable-xhdpi/action_toggle_list_light.png diff --git a/res/drawable-xhdpi/download_cached.png b/res/drawable-xhdpi/download_cached.png Binary files differnew file mode 100644 index 00000000..1ef7c805 --- /dev/null +++ b/res/drawable-xhdpi/download_cached.png diff --git a/res/drawable-xhdpi/download_none_dark.png b/res/drawable-xhdpi/download_none_dark.png Binary files differnew file mode 100644 index 00000000..7be3c2a4 --- /dev/null +++ b/res/drawable-xhdpi/download_none_dark.png diff --git a/res/drawable-xhdpi/download_none_light.png b/res/drawable-xhdpi/download_none_light.png Binary files differnew file mode 100644 index 00000000..817651d7 --- /dev/null +++ b/res/drawable-xhdpi/download_none_light.png diff --git a/res/drawable-xhdpi/download_pinned.png b/res/drawable-xhdpi/download_pinned.png Binary files differnew file mode 100644 index 00000000..09eb6ffb --- /dev/null +++ b/res/drawable-xhdpi/download_pinned.png diff --git a/res/drawable-xhdpi/downloading_dark.png b/res/drawable-xhdpi/downloading_dark.png Binary files differnew file mode 100644 index 00000000..3f14bdf4 --- /dev/null +++ b/res/drawable-xhdpi/downloading_dark.png diff --git a/res/drawable-xhdpi/downloading_light.png b/res/drawable-xhdpi/downloading_light.png Binary files differnew file mode 100644 index 00000000..643c15d0 --- /dev/null +++ b/res/drawable-xhdpi/downloading_light.png diff --git a/res/drawable-xhdpi/ic_action_volume_dark.png b/res/drawable-xhdpi/ic_action_volume_dark.png Binary files differnew file mode 100644 index 00000000..400de38b --- /dev/null +++ b/res/drawable-xhdpi/ic_action_volume_dark.png diff --git a/res/drawable-xhdpi/ic_action_volume_light.png b/res/drawable-xhdpi/ic_action_volume_light.png Binary files differnew file mode 100644 index 00000000..9a1128c1 --- /dev/null +++ b/res/drawable-xhdpi/ic_action_volume_light.png diff --git a/res/drawable-xhdpi/ic_drawer.png b/res/drawable-xhdpi/ic_drawer.png Binary files differnew file mode 100644 index 00000000..a5fa74de --- /dev/null +++ b/res/drawable-xhdpi/ic_drawer.png diff --git a/res/drawable-xhdpi/ic_menu_bookmark_dark.png b/res/drawable-xhdpi/ic_menu_bookmark_dark.png Binary files differnew file mode 100644 index 00000000..18f71365 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_bookmark_dark.png diff --git a/res/drawable-xhdpi/ic_menu_bookmark_light.png b/res/drawable-xhdpi/ic_menu_bookmark_light.png Binary files differnew file mode 100644 index 00000000..d5776317 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_bookmark_light.png diff --git a/res/drawable-xhdpi/ic_menu_chat_dark.png b/res/drawable-xhdpi/ic_menu_chat_dark.png Binary files differnew file mode 100644 index 00000000..28318219 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_chat_dark.png diff --git a/res/drawable-xhdpi/ic_menu_chat_light.png b/res/drawable-xhdpi/ic_menu_chat_light.png Binary files differnew file mode 100644 index 00000000..dcc95dcb --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_chat_light.png diff --git a/res/drawable-xhdpi/ic_menu_chat_send_dark.png b/res/drawable-xhdpi/ic_menu_chat_send_dark.png Binary files differnew file mode 100644 index 00000000..c0a5a3eb --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_chat_send_dark.png diff --git a/res/drawable-xhdpi/ic_menu_chat_send_light.png b/res/drawable-xhdpi/ic_menu_chat_send_light.png Binary files differnew file mode 100644 index 00000000..f9c3b9bb --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_chat_send_light.png diff --git a/res/drawable-xhdpi/ic_menu_library_dark.png b/res/drawable-xhdpi/ic_menu_library_dark.png Binary files differnew file mode 100644 index 00000000..b1612f65 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_library_dark.png diff --git a/res/drawable-xhdpi/ic_menu_library_light.png b/res/drawable-xhdpi/ic_menu_library_light.png Binary files differnew file mode 100644 index 00000000..1f93c8f2 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_library_light.png diff --git a/res/drawable-xhdpi/ic_menu_playlist_dark.png b/res/drawable-xhdpi/ic_menu_playlist_dark.png Binary files differnew file mode 100644 index 00000000..fd6cd498 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_playlist_dark.png diff --git a/res/drawable-xhdpi/ic_menu_playlist_light.png b/res/drawable-xhdpi/ic_menu_playlist_light.png Binary files differnew file mode 100644 index 00000000..e7e510d0 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_playlist_light.png diff --git a/res/drawable-xhdpi/ic_menu_podcast_dark.png b/res/drawable-xhdpi/ic_menu_podcast_dark.png Binary files differnew file mode 100644 index 00000000..40469b46 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_podcast_dark.png diff --git a/res/drawable-xhdpi/ic_menu_podcast_light.png b/res/drawable-xhdpi/ic_menu_podcast_light.png Binary files differnew file mode 100644 index 00000000..3748526a --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_podcast_light.png diff --git a/res/drawable-xhdpi/ic_menu_refresh_dark.png b/res/drawable-xhdpi/ic_menu_refresh_dark.png Binary files differnew file mode 100644 index 00000000..b6801006 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_refresh_dark.png diff --git a/res/drawable-xhdpi/ic_menu_refresh_light.png b/res/drawable-xhdpi/ic_menu_refresh_light.png Binary files differnew file mode 100644 index 00000000..38943f82 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_refresh_light.png diff --git a/res/drawable-xhdpi/ic_menu_remove_dark.png b/res/drawable-xhdpi/ic_menu_remove_dark.png Binary files differnew file mode 100644 index 00000000..09ce75e2 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_remove_dark.png diff --git a/res/drawable-xhdpi/ic_menu_remove_light.png b/res/drawable-xhdpi/ic_menu_remove_light.png Binary files differnew file mode 100644 index 00000000..94f7c8c1 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_remove_light.png diff --git a/res/drawable-xhdpi/ic_menu_save_dark.png b/res/drawable-xhdpi/ic_menu_save_dark.png Binary files differnew file mode 100644 index 00000000..1612fd0a --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_save_dark.png diff --git a/res/drawable-xhdpi/ic_menu_save_light.png b/res/drawable-xhdpi/ic_menu_save_light.png Binary files differnew file mode 100644 index 00000000..5dcd75d7 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_save_light.png diff --git a/res/drawable-xhdpi/ic_menu_search_dark.png b/res/drawable-xhdpi/ic_menu_search_dark.png Binary files differnew file mode 100644 index 00000000..1ae3dff0 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_search_dark.png diff --git a/res/drawable-xhdpi/ic_menu_search_light.png b/res/drawable-xhdpi/ic_menu_search_light.png Binary files differnew file mode 100644 index 00000000..705074bd --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_search_light.png diff --git a/res/drawable-xhdpi/ic_menu_settings_dark.png b/res/drawable-xhdpi/ic_menu_settings_dark.png Binary files differnew file mode 100644 index 00000000..ae917587 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_settings_dark.png diff --git a/res/drawable-xhdpi/ic_menu_settings_light.png b/res/drawable-xhdpi/ic_menu_settings_light.png Binary files differnew file mode 100644 index 00000000..29f961b2 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_settings_light.png diff --git a/res/drawable-xhdpi/ic_menu_shuffle_dark.png b/res/drawable-xhdpi/ic_menu_shuffle_dark.png Binary files differnew file mode 100644 index 00000000..e3a31a84 --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_shuffle_dark.png diff --git a/res/drawable-xhdpi/ic_menu_shuffle_light.png b/res/drawable-xhdpi/ic_menu_shuffle_light.png Binary files differnew file mode 100644 index 00000000..14eb942c --- /dev/null +++ b/res/drawable-xhdpi/ic_menu_shuffle_light.png diff --git a/res/drawable-xhdpi/launch.png b/res/drawable-xhdpi/launch.png Binary files differindex b9379f27..f73729d0 100644 --- a/res/drawable-xhdpi/launch.png +++ b/res/drawable-xhdpi/launch.png diff --git a/res/drawable-xhdpi/main_offline_dark.png b/res/drawable-xhdpi/main_offline_dark.png Binary files differnew file mode 100644 index 00000000..231e4715 --- /dev/null +++ b/res/drawable-xhdpi/main_offline_dark.png diff --git a/res/drawable-xhdpi/main_offline_light.png b/res/drawable-xhdpi/main_offline_light.png Binary files differnew file mode 100644 index 00000000..87937fcb --- /dev/null +++ b/res/drawable-xhdpi/main_offline_light.png diff --git a/res/drawable-xhdpi/main_select_server_dark.png b/res/drawable-xhdpi/main_select_server_dark.png Binary files differnew file mode 100644 index 00000000..b84f1851 --- /dev/null +++ b/res/drawable-xhdpi/main_select_server_dark.png diff --git a/res/drawable-xhdpi/main_select_server_light.png b/res/drawable-xhdpi/main_select_server_light.png Binary files differnew file mode 100644 index 00000000..ee154cc7 --- /dev/null +++ b/res/drawable-xhdpi/main_select_server_light.png diff --git a/res/drawable-xhdpi/media_backward_dark.png b/res/drawable-xhdpi/media_backward_dark.png Binary files differnew file mode 100644 index 00000000..3c9921a8 --- /dev/null +++ b/res/drawable-xhdpi/media_backward_dark.png diff --git a/res/drawable-xhdpi/media_backward_light.png b/res/drawable-xhdpi/media_backward_light.png Binary files differnew file mode 100644 index 00000000..aafd76fa --- /dev/null +++ b/res/drawable-xhdpi/media_backward_light.png diff --git a/res/drawable-xhdpi/media_forward_dark.png b/res/drawable-xhdpi/media_forward_dark.png Binary files differnew file mode 100644 index 00000000..b082b3a6 --- /dev/null +++ b/res/drawable-xhdpi/media_forward_dark.png diff --git a/res/drawable-xhdpi/media_forward_light.png b/res/drawable-xhdpi/media_forward_light.png Binary files differnew file mode 100644 index 00000000..20772843 --- /dev/null +++ b/res/drawable-xhdpi/media_forward_light.png diff --git a/res/drawable-xhdpi/media_pause_dark.png b/res/drawable-xhdpi/media_pause_dark.png Binary files differnew file mode 100644 index 00000000..aafdd4aa --- /dev/null +++ b/res/drawable-xhdpi/media_pause_dark.png diff --git a/res/drawable-xhdpi/media_pause_light.png b/res/drawable-xhdpi/media_pause_light.png Binary files differnew file mode 100644 index 00000000..2639777d --- /dev/null +++ b/res/drawable-xhdpi/media_pause_light.png diff --git a/res/drawable-xhdpi/media_start_dark.png b/res/drawable-xhdpi/media_start_dark.png Binary files differnew file mode 100644 index 00000000..9e63c90b --- /dev/null +++ b/res/drawable-xhdpi/media_start_dark.png diff --git a/res/drawable-xhdpi/media_start_light.png b/res/drawable-xhdpi/media_start_light.png Binary files differnew file mode 100644 index 00000000..2ff8c399 --- /dev/null +++ b/res/drawable-xhdpi/media_start_light.png diff --git a/res/drawable-xhdpi/media_stop_dark.png b/res/drawable-xhdpi/media_stop_dark.png Binary files differnew file mode 100644 index 00000000..9cb32909 --- /dev/null +++ b/res/drawable-xhdpi/media_stop_dark.png diff --git a/res/drawable-xhdpi/media_stop_light.png b/res/drawable-xhdpi/media_stop_light.png Binary files differnew file mode 100644 index 00000000..edf13ccf --- /dev/null +++ b/res/drawable-xhdpi/media_stop_light.png diff --git a/res/drawable-xhdpi/notification_close.png b/res/drawable-xhdpi/notification_close.png Binary files differnew file mode 100644 index 00000000..4230842e --- /dev/null +++ b/res/drawable-xhdpi/notification_close.png diff --git a/res/drawable-xhdpi/notification_next.png b/res/drawable-xhdpi/notification_next.png Binary files differnew file mode 100644 index 00000000..44dbbd12 --- /dev/null +++ b/res/drawable-xhdpi/notification_next.png diff --git a/res/drawable-xhdpi/notification_pause.png b/res/drawable-xhdpi/notification_pause.png Binary files differnew file mode 100644 index 00000000..e8d8c535 --- /dev/null +++ b/res/drawable-xhdpi/notification_pause.png diff --git a/res/drawable-xhdpi/notification_play.png b/res/drawable-xhdpi/notification_play.png Binary files differnew file mode 100644 index 00000000..532041fa --- /dev/null +++ b/res/drawable-xhdpi/notification_play.png diff --git a/res/drawable-xhdpi/notification_previous.png b/res/drawable-xhdpi/notification_previous.png Binary files differnew file mode 100644 index 00000000..87ee8d2f --- /dev/null +++ b/res/drawable-xhdpi/notification_previous.png diff --git a/res/drawable-xhdpi/now_playing.png b/res/drawable-xhdpi/now_playing.png Binary files differnew file mode 100644 index 00000000..532041fa --- /dev/null +++ b/res/drawable-xhdpi/now_playing.png diff --git a/res/drawable-xhdpi/stat_notify_download.png b/res/drawable-xhdpi/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..bd4cb567 --- /dev/null +++ b/res/drawable-xhdpi/stat_notify_download.png diff --git a/res/drawable-xhdpi/stat_notify_playing.png b/res/drawable-xhdpi/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..532041fa --- /dev/null +++ b/res/drawable-xhdpi/stat_notify_playing.png diff --git a/res/drawable-xxhdpi-v11/notification_close.png b/res/drawable-xxhdpi-v11/notification_close.png Binary files differnew file mode 100644 index 00000000..c3ac026a --- /dev/null +++ b/res/drawable-xxhdpi-v11/notification_close.png diff --git a/res/drawable-xxhdpi-v11/notification_next.png b/res/drawable-xxhdpi-v11/notification_next.png Binary files differnew file mode 100644 index 00000000..06911082 --- /dev/null +++ b/res/drawable-xxhdpi-v11/notification_next.png diff --git a/res/drawable-xxhdpi-v11/notification_pause.png b/res/drawable-xxhdpi-v11/notification_pause.png Binary files differnew file mode 100644 index 00000000..1513f9d9 --- /dev/null +++ b/res/drawable-xxhdpi-v11/notification_pause.png diff --git a/res/drawable-xxhdpi-v11/notification_play.png b/res/drawable-xxhdpi-v11/notification_play.png Binary files differnew file mode 100644 index 00000000..9138a760 --- /dev/null +++ b/res/drawable-xxhdpi-v11/notification_play.png diff --git a/res/drawable-xxhdpi-v11/notification_previous.png b/res/drawable-xxhdpi-v11/notification_previous.png Binary files differnew file mode 100644 index 00000000..b4456c16 --- /dev/null +++ b/res/drawable-xxhdpi-v11/notification_previous.png diff --git a/res/drawable-xxhdpi-v11/stat_notify_download.png b/res/drawable-xxhdpi-v11/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..b2dc5651 --- /dev/null +++ b/res/drawable-xxhdpi-v11/stat_notify_download.png diff --git a/res/drawable-xxhdpi-v11/stat_notify_playing.png b/res/drawable-xxhdpi-v11/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..9138a760 --- /dev/null +++ b/res/drawable-xxhdpi-v11/stat_notify_playing.png diff --git a/res/drawable-xxhdpi/action_toggle_list_dark.png b/res/drawable-xxhdpi/action_toggle_list_dark.png Binary files differnew file mode 100644 index 00000000..598fc312 --- /dev/null +++ b/res/drawable-xxhdpi/action_toggle_list_dark.png diff --git a/res/drawable-xxhdpi/action_toggle_list_light.png b/res/drawable-xxhdpi/action_toggle_list_light.png Binary files differnew file mode 100644 index 00000000..ceb3fade --- /dev/null +++ b/res/drawable-xxhdpi/action_toggle_list_light.png diff --git a/res/drawable-xxhdpi/download_none_dark.png b/res/drawable-xxhdpi/download_none_dark.png Binary files differnew file mode 100644 index 00000000..a0cb8a41 --- /dev/null +++ b/res/drawable-xxhdpi/download_none_dark.png diff --git a/res/drawable-xxhdpi/download_none_light.png b/res/drawable-xxhdpi/download_none_light.png Binary files differnew file mode 100644 index 00000000..7a1639ef --- /dev/null +++ b/res/drawable-xxhdpi/download_none_light.png diff --git a/res/drawable-xxhdpi/downloading_dark.png b/res/drawable-xxhdpi/downloading_dark.png Binary files differnew file mode 100644 index 00000000..afc4bf84 --- /dev/null +++ b/res/drawable-xxhdpi/downloading_dark.png diff --git a/res/drawable-xxhdpi/downloading_light.png b/res/drawable-xxhdpi/downloading_light.png Binary files differnew file mode 100644 index 00000000..ba31a979 --- /dev/null +++ b/res/drawable-xxhdpi/downloading_light.png diff --git a/res/drawable-xxhdpi/ic_action_volume_dark.png b/res/drawable-xxhdpi/ic_action_volume_dark.png Binary files differnew file mode 100644 index 00000000..7991a65d --- /dev/null +++ b/res/drawable-xxhdpi/ic_action_volume_dark.png diff --git a/res/drawable-xxhdpi/ic_action_volume_light.png b/res/drawable-xxhdpi/ic_action_volume_light.png Binary files differnew file mode 100644 index 00000000..8dfbf3f5 --- /dev/null +++ b/res/drawable-xxhdpi/ic_action_volume_light.png diff --git a/res/drawable-xxhdpi/ic_drawer.png b/res/drawable-xxhdpi/ic_drawer.png Binary files differnew file mode 100644 index 00000000..9c4685d6 --- /dev/null +++ b/res/drawable-xxhdpi/ic_drawer.png diff --git a/res/drawable-xxhdpi/ic_menu_bookmark_dark.png b/res/drawable-xxhdpi/ic_menu_bookmark_dark.png Binary files differnew file mode 100644 index 00000000..2523e14c --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_bookmark_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_bookmark_light.png b/res/drawable-xxhdpi/ic_menu_bookmark_light.png Binary files differnew file mode 100644 index 00000000..9e8c4591 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_bookmark_light.png diff --git a/res/drawable-xxhdpi/ic_menu_chat_dark.png b/res/drawable-xxhdpi/ic_menu_chat_dark.png Binary files differnew file mode 100644 index 00000000..60efb47d --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_chat_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_chat_light.png b/res/drawable-xxhdpi/ic_menu_chat_light.png Binary files differnew file mode 100644 index 00000000..02c89560 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_chat_light.png diff --git a/res/drawable-xxhdpi/ic_menu_chat_send_dark.png b/res/drawable-xxhdpi/ic_menu_chat_send_dark.png Binary files differnew file mode 100644 index 00000000..b86ca3d3 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_chat_send_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_chat_send_light.png b/res/drawable-xxhdpi/ic_menu_chat_send_light.png Binary files differnew file mode 100644 index 00000000..048b8aac --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_chat_send_light.png diff --git a/res/drawable-xxhdpi/ic_menu_library_dark.png b/res/drawable-xxhdpi/ic_menu_library_dark.png Binary files differnew file mode 100644 index 00000000..02a4f3f2 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_library_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_library_light.png b/res/drawable-xxhdpi/ic_menu_library_light.png Binary files differnew file mode 100644 index 00000000..52ce8203 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_library_light.png diff --git a/res/drawable-xxhdpi/ic_menu_playlist_dark.png b/res/drawable-xxhdpi/ic_menu_playlist_dark.png Binary files differnew file mode 100644 index 00000000..2c955eee --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_playlist_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_playlist_light.png b/res/drawable-xxhdpi/ic_menu_playlist_light.png Binary files differnew file mode 100644 index 00000000..d1877328 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_playlist_light.png diff --git a/res/drawable-xxhdpi/ic_menu_podcast_dark.png b/res/drawable-xxhdpi/ic_menu_podcast_dark.png Binary files differnew file mode 100644 index 00000000..a748dc60 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_podcast_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_podcast_light.png b/res/drawable-xxhdpi/ic_menu_podcast_light.png Binary files differnew file mode 100644 index 00000000..efa7b037 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_podcast_light.png diff --git a/res/drawable-xxhdpi/ic_menu_refresh_dark.png b/res/drawable-xxhdpi/ic_menu_refresh_dark.png Binary files differnew file mode 100644 index 00000000..0e5616bd --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_refresh_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_refresh_light.png b/res/drawable-xxhdpi/ic_menu_refresh_light.png Binary files differnew file mode 100644 index 00000000..7dea70df --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_refresh_light.png diff --git a/res/drawable-xxhdpi/ic_menu_remove_dark.png b/res/drawable-xxhdpi/ic_menu_remove_dark.png Binary files differnew file mode 100644 index 00000000..d5952ea0 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_remove_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_remove_light.png b/res/drawable-xxhdpi/ic_menu_remove_light.png Binary files differnew file mode 100644 index 00000000..c814869e --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_remove_light.png diff --git a/res/drawable-xxhdpi/ic_menu_save_dark.png b/res/drawable-xxhdpi/ic_menu_save_dark.png Binary files differnew file mode 100644 index 00000000..acb264ec --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_save_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_save_light.png b/res/drawable-xxhdpi/ic_menu_save_light.png Binary files differnew file mode 100644 index 00000000..fcd18ccd --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_save_light.png diff --git a/res/drawable-xxhdpi/ic_menu_search_dark.png b/res/drawable-xxhdpi/ic_menu_search_dark.png Binary files differnew file mode 100644 index 00000000..500ac03a --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_search_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_search_light.png b/res/drawable-xxhdpi/ic_menu_search_light.png Binary files differnew file mode 100644 index 00000000..fa64f9e8 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_search_light.png diff --git a/res/drawable-xxhdpi/ic_menu_settings_dark.png b/res/drawable-xxhdpi/ic_menu_settings_dark.png Binary files differnew file mode 100644 index 00000000..ded5dbb5 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_settings_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_settings_light.png b/res/drawable-xxhdpi/ic_menu_settings_light.png Binary files differnew file mode 100644 index 00000000..cd242306 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_settings_light.png diff --git a/res/drawable-xxhdpi/ic_menu_shuffle_dark.png b/res/drawable-xxhdpi/ic_menu_shuffle_dark.png Binary files differnew file mode 100644 index 00000000..b53733df --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_shuffle_dark.png diff --git a/res/drawable-xxhdpi/ic_menu_shuffle_light.png b/res/drawable-xxhdpi/ic_menu_shuffle_light.png Binary files differnew file mode 100644 index 00000000..4d5dff32 --- /dev/null +++ b/res/drawable-xxhdpi/ic_menu_shuffle_light.png diff --git a/res/drawable-xxhdpi/launch.png b/res/drawable-xxhdpi/launch.png Binary files differindex 797104fe..b067bd9f 100644 --- a/res/drawable-xxhdpi/launch.png +++ b/res/drawable-xxhdpi/launch.png diff --git a/res/drawable-xxhdpi/main_offline_dark.png b/res/drawable-xxhdpi/main_offline_dark.png Binary files differnew file mode 100644 index 00000000..c415e0a5 --- /dev/null +++ b/res/drawable-xxhdpi/main_offline_dark.png diff --git a/res/drawable-xxhdpi/main_offline_light.png b/res/drawable-xxhdpi/main_offline_light.png Binary files differnew file mode 100644 index 00000000..b7e1c380 --- /dev/null +++ b/res/drawable-xxhdpi/main_offline_light.png diff --git a/res/drawable-xxhdpi/main_select_server_dark.png b/res/drawable-xxhdpi/main_select_server_dark.png Binary files differnew file mode 100644 index 00000000..b85e3a1e --- /dev/null +++ b/res/drawable-xxhdpi/main_select_server_dark.png diff --git a/res/drawable-xxhdpi/main_select_server_light.png b/res/drawable-xxhdpi/main_select_server_light.png Binary files differnew file mode 100644 index 00000000..8fc39eff --- /dev/null +++ b/res/drawable-xxhdpi/main_select_server_light.png diff --git a/res/drawable-xxhdpi/media_backward_dark.png b/res/drawable-xxhdpi/media_backward_dark.png Binary files differnew file mode 100644 index 00000000..5b6c6148 --- /dev/null +++ b/res/drawable-xxhdpi/media_backward_dark.png diff --git a/res/drawable-xxhdpi/media_backward_light.png b/res/drawable-xxhdpi/media_backward_light.png Binary files differnew file mode 100644 index 00000000..32f7d3bc --- /dev/null +++ b/res/drawable-xxhdpi/media_backward_light.png diff --git a/res/drawable-xxhdpi/media_forward_dark.png b/res/drawable-xxhdpi/media_forward_dark.png Binary files differnew file mode 100644 index 00000000..ca4ee295 --- /dev/null +++ b/res/drawable-xxhdpi/media_forward_dark.png diff --git a/res/drawable-xxhdpi/media_forward_light.png b/res/drawable-xxhdpi/media_forward_light.png Binary files differnew file mode 100644 index 00000000..208e46e9 --- /dev/null +++ b/res/drawable-xxhdpi/media_forward_light.png diff --git a/res/drawable-xxhdpi/media_pause_dark.png b/res/drawable-xxhdpi/media_pause_dark.png Binary files differnew file mode 100644 index 00000000..4b5aacbc --- /dev/null +++ b/res/drawable-xxhdpi/media_pause_dark.png diff --git a/res/drawable-xxhdpi/media_pause_light.png b/res/drawable-xxhdpi/media_pause_light.png Binary files differnew file mode 100644 index 00000000..111f6d00 --- /dev/null +++ b/res/drawable-xxhdpi/media_pause_light.png diff --git a/res/drawable-xxhdpi/media_start_dark.png b/res/drawable-xxhdpi/media_start_dark.png Binary files differnew file mode 100644 index 00000000..641ad544 --- /dev/null +++ b/res/drawable-xxhdpi/media_start_dark.png diff --git a/res/drawable-xxhdpi/media_start_light.png b/res/drawable-xxhdpi/media_start_light.png Binary files differnew file mode 100644 index 00000000..a6286203 --- /dev/null +++ b/res/drawable-xxhdpi/media_start_light.png diff --git a/res/drawable-xxhdpi/media_stop_dark.png b/res/drawable-xxhdpi/media_stop_dark.png Binary files differnew file mode 100644 index 00000000..9a9c432a --- /dev/null +++ b/res/drawable-xxhdpi/media_stop_dark.png diff --git a/res/drawable-xxhdpi/media_stop_light.png b/res/drawable-xxhdpi/media_stop_light.png Binary files differnew file mode 100644 index 00000000..79eb8d95 --- /dev/null +++ b/res/drawable-xxhdpi/media_stop_light.png diff --git a/res/drawable-xxhdpi/notification_close.png b/res/drawable-xxhdpi/notification_close.png Binary files differnew file mode 100644 index 00000000..022a6780 --- /dev/null +++ b/res/drawable-xxhdpi/notification_close.png diff --git a/res/drawable-xxhdpi/notification_next.png b/res/drawable-xxhdpi/notification_next.png Binary files differnew file mode 100644 index 00000000..dfe129db --- /dev/null +++ b/res/drawable-xxhdpi/notification_next.png diff --git a/res/drawable-xxhdpi/notification_pause.png b/res/drawable-xxhdpi/notification_pause.png Binary files differnew file mode 100644 index 00000000..9c952207 --- /dev/null +++ b/res/drawable-xxhdpi/notification_pause.png diff --git a/res/drawable-xxhdpi/notification_play.png b/res/drawable-xxhdpi/notification_play.png Binary files differnew file mode 100644 index 00000000..4ee0a5eb --- /dev/null +++ b/res/drawable-xxhdpi/notification_play.png diff --git a/res/drawable-xxhdpi/notification_previous.png b/res/drawable-xxhdpi/notification_previous.png Binary files differnew file mode 100644 index 00000000..e6908126 --- /dev/null +++ b/res/drawable-xxhdpi/notification_previous.png diff --git a/res/drawable-xxhdpi/now_playing.png b/res/drawable-xxhdpi/now_playing.png Binary files differnew file mode 100644 index 00000000..4ee0a5eb --- /dev/null +++ b/res/drawable-xxhdpi/now_playing.png diff --git a/res/drawable-xxhdpi/stat_notify_download.png b/res/drawable-xxhdpi/stat_notify_download.png Binary files differnew file mode 100644 index 00000000..9d9a7f3e --- /dev/null +++ b/res/drawable-xxhdpi/stat_notify_download.png diff --git a/res/drawable-xxhdpi/stat_notify_playing.png b/res/drawable-xxhdpi/stat_notify_playing.png Binary files differnew file mode 100644 index 00000000..4ee0a5eb --- /dev/null +++ b/res/drawable-xxhdpi/stat_notify_playing.png diff --git a/res/layout-land/download.xml b/res/layout-land/download.xml index 5b4db35e..b896509e 100644 --- a/res/layout-land/download.xml +++ b/res/layout-land/download.xml @@ -40,55 +40,11 @@ android:layout_weight="1"
android:background="@android:color/transparent">
- <LinearLayout
- android:id="@+id/download_other_controls_layout"
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal">
-
- <Button
- android:id="@+id/download_jukebox"
- android:text="RC"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dip"
- android:padding="9dip"/>
- <Button
- android:id="@+id/download_equalizer"
- android:text="EQ"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dip"
- android:padding="9dip"/>
- <Button
- android:id="@+id/download_visualizer"
- android:text="VIS"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="3dip"
- android:padding="9dip"/>
- <ImageButton
- android:id="@+id/download_star"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:background="@drawable/menubar_button"
- android:src="@android:drawable/star_big_off"
- android:padding="10dip"/>
- </LinearLayout>
+ <include layout="@layout/download_action_buttons"/>
<LinearLayout
android:id="@+id/download_visualizer_view_layout"
+ android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:layout_marginLeft="12dip"
diff --git a/res/layout-large-land/abstract_fragment_container.xml b/res/layout-large-land/abstract_fragment_container.xml new file mode 100644 index 00000000..511d63aa --- /dev/null +++ b/res/layout-large-land/abstract_fragment_container.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
+
+ <FrameLayout
+ android:id="@+id/fragment_container"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="4"/>
+
+ <FrameLayout
+ android:id="@+id/fragment_second_container"
+ android:layout_width="0px"
+ android:layout_height="match_parent"
+ android:layout_weight="6"
+ android:visibility="gone"/>
+
+</LinearLayout>
\ No newline at end of file diff --git a/res/layout-port/download.xml b/res/layout-port/download.xml index 4b39286a..38ab069f 100644 --- a/res/layout-port/download.xml +++ b/res/layout-port/download.xml @@ -25,9 +25,8 @@ android:background="@android:color/transparent">
<RelativeLayout android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_weight="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:layout_above="@+id/download_song_title">
<ImageView
@@ -38,70 +37,25 @@ android:layout_alignParentTop="true"
android:scaleType="centerCrop"/>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/download_overlay_buttons"
- android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/overlayColor"
android:layout_alignParentBottom="true">
- <Button
- android:id="@+id/download_jukebox"
- android:text="RC"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:paddingTop="4dip"
- android:paddingLeft="14dip"
- android:paddingBottom="4dip"/>
-
- <Button
- android:id="@+id/download_equalizer"
- android:text="EQ"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:paddingTop="4dip"
- android:paddingLeft="7dip"
- android:paddingRight="7dip"
- android:paddingBottom="4dip"/>
-
- <Button
- android:id="@+id/download_visualizer"
- android:text="VIS"
- android:textStyle="bold"
- android:textSize="22sp"
- android:background="@drawable/menubar_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:paddingTop="4dip"
- android:paddingLeft="7dip"
- android:paddingRight="7dip"
- android:paddingBottom="4dip"/>
-
- <ImageButton
- android:id="@+id/download_star"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/download_jukebox"
- android:background="@drawable/menubar_button"
- android:src="@android:drawable/star_big_off"
- android:paddingTop="8dip"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- android:paddingBottom="8dip"/>
- </LinearLayout>
+ android:layout_centerHorizontal="true">
+
+ <include layout="@layout/download_action_buttons"/>
+ </LinearLayout>
+ </RelativeLayout>
<LinearLayout
android:id="@+id/download_visualizer_view_layout"
+ android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:layout_marginLeft="16dip"
diff --git a/res/layout/abstract_activity.xml b/res/layout/abstract_activity.xml new file mode 100644 index 00000000..ed16c695 --- /dev/null +++ b/res/layout/abstract_activity.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <!-- The main content view -->
+ <FrameLayout
+ android:id="@+id/content_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ <!-- The navigation drawer -->
+ <ListView android:id="@+id/left_drawer"
+ android:layout_width="240dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:choiceMode="singleChoice"
+ android:divider="@android:color/transparent"
+ android:dividerHeight="0dp"
+ android:background="?android:windowBackground"/>
+</android.support.v4.widget.DrawerLayout>
\ No newline at end of file diff --git a/res/layout/main.xml b/res/layout/abstract_fragment_activity.xml index f1509db6..605b988a 100644 --- a/res/layout/main.xml +++ b/res/layout/abstract_fragment_activity.xml @@ -1,81 +1,85 @@ -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:gravity="center_horizontal" - android:orientation="vertical" > - - <android.support.v4.view.ViewPager - android:id="@+id/pager" - android:layout_width="fill_parent" - android:layout_height="0px" - android:layout_weight="1" > - </android.support.v4.view.ViewPager> - - <View - android:layout_width="fill_parent" - android:layout_height="1px" - android:background="@color/dividerColor"/> - - <LinearLayout - android:id="@+id/bottom_bar" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="@drawable/media_button" - android:orientation="horizontal"> - - <ImageView - android:id="@+id/album_art" - android:layout_width="50dip" - android:layout_height="50dip" - android:layout_gravity="left|center" - android:scaleType="fitStart" - android:src="@drawable/unknown_album"/> - - <LinearLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_weight="1" - android:orientation="vertical" - android:paddingLeft="8dip"> - - <TextView - android:id="@+id/track_name" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:textColor="?android:textColorPrimary" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textSize="13sp" - android:text="@string/search.artists"/> - - <TextView - android:id="@+id/artist_name" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:textColor="?android:textColorSecondary" - android:singleLine="true" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textSize="12sp" - android:text="@string/search.albums"/> - </LinearLayout> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_previous" - android:src="?attr/media_button_backward" - android:layout_centerVertical="true"/> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_start" - android:src="?attr/media_button_start" - android:layout_centerVertical="true"/> - - <ImageButton - style="@style/PlaybackControl.Small" - android:id="@+id/download_next" - android:src="?attr/media_button_forward" - android:layout_centerVertical="true"/> - </LinearLayout> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical" >
+
+ <include layout="@layout/abstract_fragment_container" />
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="@color/dividerColor"/>
+
+ <LinearLayout
+ android:id="@+id/bottom_bar"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/media_button"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/album_art"
+ android:layout_width="50dip"
+ android:layout_height="50dip"
+ android:layout_gravity="left|center"
+ android:scaleType="fitStart"
+ android:src="@drawable/unknown_album"/>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="8dip">
+
+ <TextView
+ android:id="@+id/track_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textColor="?android:textColorPrimary"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textSize="13sp"
+ android:text="@string/search.artists"/>
+
+ <TextView
+ android:id="@+id/artist_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textColor="?android:textColorSecondary"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textSize="12sp"
+ android:text="@string/search.albums"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1">
+
+ <ImageButton
+ style="@style/PlaybackControl.Small"
+ android:id="@+id/download_previous"
+ android:src="?attr/media_button_backward"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+
+ <ImageButton
+ style="@style/PlaybackControl.Small"
+ android:id="@+id/download_start"
+ android:src="?attr/media_button_start"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+
+ <ImageButton
+ style="@style/PlaybackControl.Small"
+ android:id="@+id/download_next"
+ android:src="?attr/media_button_forward"
+ android:layout_width="0dp"
+ android:layout_weight="1"/>
+ </LinearLayout>
+ </LinearLayout>
</LinearLayout>
\ No newline at end of file diff --git a/res/layout/abstract_fragment_container.xml b/res/layout/abstract_fragment_container.xml new file mode 100644 index 00000000..d4a8607f --- /dev/null +++ b/res/layout/abstract_fragment_container.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fragment_container"
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1"/>
\ No newline at end of file diff --git a/res/layout/select_podcasts.xml b/res/layout/abstract_list_fragment.xml index ea4fb07c..bfce4792 100644 --- a/res/layout/select_podcasts.xml +++ b/res/layout/abstract_list_fragment.xml @@ -1,29 +1,29 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/select_podcasts_layout" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - - <View - android:layout_width="fill_parent" - android:layout_height="1px" - android:background="@color/dividerColor"/> - - <include layout="@layout/tab_progress" /> - - <TextView - android:id="@+id/select_podcasts_empty" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip" - android:text="@string/select_podcasts.empty" - android:visibility="gone" /> - - <ListView - android:id="@+id/select_podcasts_list" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1.0" - android:fastScrollEnabled="true"/> -</LinearLayout> +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/fragment_list_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical" >
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:background="@color/dividerColor"/>
+
+ <include layout="@layout/tab_progress" />
+
+ <TextView
+ android:id="@+id/fragment_list_empty"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip"
+ android:text="@string/common.empty"
+ android:visibility="gone" />
+
+ <ListView
+ android:id="@+id/fragment_list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0"
+ android:fastScrollEnabled="true"/>
+</LinearLayout>
diff --git a/res/layout/album_list_item.xml b/res/layout/album_list_item.xml index ee710539..9051a72e 100644 --- a/res/layout/album_list_item.xml +++ b/res/layout/album_list_item.xml @@ -51,10 +51,10 @@ <ImageView
android:id="@+id/album_more"
- android:src="@drawable/list_item_more"
+ android:src="?attr/download_none"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right|center_vertical"
- android:paddingRight="6dip"
+ android:paddingRight="10dip"
android:background="@drawable/menubar_button"/>
</LinearLayout>
diff --git a/res/layout/appwidget4x1.xml b/res/layout/appwidget4x1.xml index 5e55aa37..68fecb9a 100644 --- a/res/layout/appwidget4x1.xml +++ b/res/layout/appwidget4x1.xml @@ -5,7 +5,8 @@ android:minWidth="250dp" android:minHeight="40dp" android:background="@drawable/appwidget_bg" - android:orientation="horizontal" > + android:orientation="horizontal" + android:id="@+id/widget_root"> <ImageView android:id="@+id/appwidget_coverart" diff --git a/res/layout/appwidget4x2.xml b/res/layout/appwidget4x2.xml index 575ae1c2..8409bbbf 100644 --- a/res/layout/appwidget4x2.xml +++ b/res/layout/appwidget4x2.xml @@ -5,7 +5,8 @@ android:minWidth="250dp" android:minHeight="110dp" android:background="@drawable/appwidget_bg" - android:orientation="horizontal" > + android:orientation="horizontal" + android:id="@+id/widget_root"> <ImageView android:id="@+id/appwidget_coverart" diff --git a/res/layout/appwidget4x3.xml b/res/layout/appwidget4x3.xml index b4f685bc..e72a266d 100644 --- a/res/layout/appwidget4x3.xml +++ b/res/layout/appwidget4x3.xml @@ -3,7 +3,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/appwidget_bg" - android:orientation="vertical" > + android:orientation="vertical" + android:id="@+id/widget_root"> <ImageView android:id="@+id/appwidget_coverart" diff --git a/res/layout/appwidget4x4.xml b/res/layout/appwidget4x4.xml index 6e6c12ab..c885829b 100644 --- a/res/layout/appwidget4x4.xml +++ b/res/layout/appwidget4x4.xml @@ -3,7 +3,8 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:background="@drawable/appwidget_bg" > + android:background="@drawable/appwidget_bg" + android:id="@+id/widget_root"> <ImageView android:id="@+id/appwidget_coverart" diff --git a/res/layout/artist_list_item.xml b/res/layout/basic_list_item.xml index edf1930e..2295a9ba 100644 --- a/res/layout/artist_list_item.xml +++ b/res/layout/basic_list_item.xml @@ -1,38 +1,38 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="@android:color/transparent"> - - <TextView - android:id="@+id/artist_name" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="left|center_vertical" - android:paddingLeft="6dip" - android:paddingRight="6dip" - android:minHeight="50dip" - android:background="@android:color/transparent"/> - - <ImageButton - android:id="@+id/artist_star" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="right|center_vertical" - android:src="@drawable/ic_stat_star" - android:background="@android:color/transparent" - android:focusable="false" - android:visibility="gone"/> - - <ImageView - android:id="@+id/artist_more" - android:src="@drawable/list_item_more" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_gravity="right|center_vertical" - android:paddingRight="6dip" - android:background="@drawable/menubar_button"/> +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:background="@android:color/transparent">
+
+ <TextView
+ android:id="@+id/item_name"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="left|center_vertical"
+ android:paddingLeft="6dip"
+ android:paddingRight="6dip"
+ android:minHeight="50dip"
+ android:background="@android:color/transparent"/>
+
+ <ImageButton
+ android:id="@+id/item_star"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right|center_vertical"
+ android:src="@drawable/ic_stat_star"
+ android:background="@android:color/transparent"
+ android:focusable="false"
+ android:visibility="gone"/>
+
+ <ImageView
+ android:id="@+id/item_more"
+ android:src="?attr/download_none"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="right|center_vertical"
+ android:paddingRight="10dip"
+ android:background="@drawable/menubar_button"/>
</LinearLayout>
\ No newline at end of file diff --git a/res/layout/create_bookmark.xml b/res/layout/create_bookmark.xml new file mode 100644 index 00000000..f72b39d8 --- /dev/null +++ b/res/layout/create_bookmark.xml @@ -0,0 +1,26 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/comment_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="4dp" + android:textSize="20dp" + android:text="@string/common.comment" /> + <EditText + android:id="@+id/comment_text" + android:inputType="text" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginLeft="4dp" /> + </LinearLayout> +</LinearLayout> diff --git a/res/layout/download_action_buttons.xml b/res/layout/download_action_buttons.xml new file mode 100644 index 00000000..e3a45151 --- /dev/null +++ b/res/layout/download_action_buttons.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/download_other_controls_layout"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal">
+
+ <Button
+ android:id="@+id/download_jukebox"
+ android:text="RC"
+ style="@style/DownloadActionButton"/>
+
+ <Button
+ android:id="@+id/download_equalizer"
+ android:text="EQ"
+ style="@style/DownloadActionButton"/>
+
+ <Button
+ android:id="@+id/download_visualizer"
+ android:text="VIS"
+ style="@style/DownloadActionButton"/>
+
+ <ImageButton
+ android:id="@+id/download_star"
+ style="@style/DownloadActionImageButton"
+ android:src="@android:drawable/star_big_off"/>
+
+ <ImageButton
+ android:id="@+id/download_bookmark"
+ style="@style/DownloadActionImageButton"
+ android:src="?attr/bookmark"/>
+</LinearLayout>
\ No newline at end of file diff --git a/res/layout/download_media_buttons.xml b/res/layout/download_media_buttons.xml index 1835a373..1ccf6c68 100644 --- a/res/layout/download_media_buttons.xml +++ b/res/layout/download_media_buttons.xml @@ -54,7 +54,7 @@ <ImageButton style="@style/PlaybackControl.Small" android:id="@+id/download_toggle_list" - android:src="@drawable/action_toggle_list" + android:src="?attr/toggle_list" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> diff --git a/res/layout/drawer_list_item.xml b/res/layout/drawer_list_item.xml new file mode 100644 index 00000000..a85d043e --- /dev/null +++ b/res/layout/drawer_list_item.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dip"
+ android:paddingBottom="9dip">
+
+ <ImageView
+ android:id="@+id/drawer_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left|center_vertical"
+ android:paddingTop="1dip"
+ android:paddingBottom="1dip"
+ android:paddingRight="8dip"
+ android:paddingLeft="10dip"/>
+
+ <TextView
+ android:id="@+id/drawer_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="26sp"
+ android:textStyle="bold"
+ android:singleLine="true"/>
+</LinearLayout>
\ No newline at end of file diff --git a/res/layout/equalizer.xml b/res/layout/equalizer.xml index ee1a9560..6e3c7e5c 100644 --- a/res/layout/equalizer.xml +++ b/res/layout/equalizer.xml @@ -4,7 +4,6 @@ android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:background="@drawable/album_art_background"
android:padding="16dip">
<CheckBox
@@ -12,7 +11,6 @@ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/equalizer.enabled"
- android:textColor="#c0c0c0"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<ScrollView
diff --git a/res/layout/equalizer_bar.xml b/res/layout/equalizer_bar.xml index c34d1108..3a104e9b 100644 --- a/res/layout/equalizer_bar.xml +++ b/res/layout/equalizer_bar.xml @@ -6,8 +6,6 @@ <TextView
android:id="@+id/equalizer.frequency"
- android:textSize="12sp"
- android:textColor="#c0c0c0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
@@ -18,7 +16,6 @@ android:id="@+id/equalizer.level"
android:text="0 dB"
android:textSize="12sp"
- android:textColor="#c0c0c0"
android:gravity="right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/res/layout/help.xml b/res/layout/help.xml deleted file mode 100644 index f22dee37..00000000 --- a/res/layout/help.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <LinearLayout android:id="@+id/help_buttons" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_weight="0" - android:layout_alignParentBottom="true" - android:padding="4dip" - android:gravity="center_horizontal" - android:background="#ffcccccc"> - - <Button android:id="@+id/help_back" - android:text="@string/help.back" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginRight="5dip" - android:paddingLeft="25dip" - android:paddingRight="25dip"/> - - <Button android:id="@+id/help_close" - android:text="@string/help.close" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_marginLeft="5dip" - android:paddingLeft="25dip" - android:paddingRight="25dip"/> - </LinearLayout> - - - <WebView - android:id="@+id/help_contents" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_above="@id/help_buttons" - android:layout_weight="1" - android:fadingEdge="vertical" - android:fadingEdgeLength="12dip"/> - - </RelativeLayout> diff --git a/res/layout/jukebox_volume.xml b/res/layout/jukebox_volume.xml index 4bccaec7..fd718326 100644 --- a/res/layout/jukebox_volume.xml +++ b/res/layout/jukebox_volume.xml @@ -32,7 +32,7 @@ android:paddingRight="12dip" android:layout_alignParentLeft="true" android:layout_below="@+id/jukebox_volume_title" - android:src="@drawable/volume"/> + android:src="?attr/volume"/> <SeekBar android:layout_height="wrap_content" diff --git a/res/layout/main_buttons.xml b/res/layout/main_buttons.xml index 1e60838d..7729315c 100644 --- a/res/layout/main_buttons.xml +++ b/res/layout/main_buttons.xml @@ -15,7 +15,7 @@ android:minHeight="?android:attr/listPreferredItemHeight">
<ImageView
- android:src="@drawable/main_select_server"
+ android:src="?attr/select_server"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
@@ -71,7 +71,6 @@ <TextView
android:id="@+id/main_albums_newest"
android:text="@string/main.albums_newest"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -83,7 +82,6 @@ <TextView
android:id="@+id/main_albums_recent"
android:text="@string/main.albums_recent"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -95,7 +93,6 @@ <TextView
android:id="@+id/main_albums_frequent"
android:text="@string/main.albums_frequent"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -107,7 +104,6 @@ <TextView
android:id="@+id/main_albums_highest"
android:text="@string/main.albums_highest"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -119,7 +115,6 @@ <TextView
android:id="@+id/main_albums_starred"
android:text="@string/main.albums_starred"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -131,7 +126,6 @@ <TextView
android:id="@+id/main_albums_genres"
android:text="@string/main.albums_genres"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
@@ -143,7 +137,6 @@ <TextView
android:id="@+id/main_albums_random"
android:text="@string/main.albums_random"
- android:drawableRight="@drawable/list_item_more"
android:drawablePadding="6dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/res/layout/notification.xml b/res/layout/notification.xml index 22e2cb63..55c7be2a 100644 --- a/res/layout/notification.xml +++ b/res/layout/notification.xml @@ -14,10 +14,12 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" android:orientation="vertical" - android:paddingLeft="11.0dip"> + android:paddingLeft="11.0dip" + android:layout_gravity="center_vertical"> <TextView android:id="@+id/notification_title" @@ -28,76 +30,54 @@ android:ellipsize="marquee" android:focusable="true" android:singleLine="true" /> - - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="horizontal" > - - <LinearLayout - android:layout_width="0.0dp" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_weight="1.0" - android:orientation="vertical"> - <TextView - android:id="@+id/notification_artist" - style="@android:style/TextAppearance.StatusBar.EventContent" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:ellipsize="end" - android:scrollHorizontally="true" - android:singleLine="true" /> + <TextView + android:id="@+id/notification_artist" + style="@android:style/TextAppearance.StatusBar.EventContent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:ellipsize="end" + android:scrollHorizontally="true" + android:singleLine="true" /> - <TextView - android:id="@+id/notification_album" - style="@android:style/TextAppearance.StatusBar.EventContent" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="left" - android:ellipsize="end" - android:scrollHorizontally="true" - android:singleLine="true" /> - </LinearLayout> + <TextView + android:id="@+id/notification_album" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:visibility="gone"/> + </LinearLayout> - <ImageButton - android:id="@+id/control_previous" - android:src="@drawable/notification_prev" - android:background="@drawable/btn_bg" - android:layout_width="34dip" - android:layout_height="34dip" - android:layout_gravity="center|right" - android:layout_marginRight="10dip" - android:layout_marginTop="2dip" - android:layout_weight="0.0" - android:scaleType="fitXY"/> + <ImageButton + android:id="@+id/control_previous" + android:src="@drawable/notification_previous" + android:background="@drawable/btn_bg" + android:layout_width="46dip" + android:layout_height="fill_parent" + android:layout_gravity="center|right" + android:padding="8.0dip" + android:layout_weight="0.0" + android:scaleType="fitCenter"/> - <ImageButton - android:id="@+id/control_pause" - android:src="@drawable/notification_pause" - android:background="@drawable/btn_bg" - android:layout_width="34dip" - android:layout_height="34dip" - android:layout_gravity="center|right" - android:layout_marginRight="10dip" - android:layout_marginTop="2dip" - android:layout_weight="0.0" - android:scaleType="fitXY"/> + <ImageButton + android:id="@+id/control_pause" + android:src="@drawable/notification_pause" + android:background="@drawable/btn_bg" + android:layout_width="46dip" + android:layout_height="fill_parent" + android:layout_gravity="center|right" + android:padding="8.0dip" + android:layout_weight="0.0" + android:scaleType="fitCenter"/> - <ImageButton - android:id="@+id/control_next" - android:src="@drawable/notification_next" - android:background="@drawable/btn_bg" - android:layout_width="34dip" - android:layout_height="34dip" - android:layout_gravity="center|right" - android:layout_marginRight="10dip" - android:layout_marginTop="2dip" - android:layout_weight="0.0" - android:scaleType="fitXY"/> - </LinearLayout> - </LinearLayout> + <ImageButton + android:id="@+id/control_next" + android:src="@drawable/notification_next" + android:background="@drawable/btn_bg" + android:layout_width="46dip" + android:layout_height="fill_parent" + android:layout_gravity="center|right" + android:padding="8.0dip" + android:layout_weight="0.0" + android:scaleType="fitCenter"/> </LinearLayout> diff --git a/res/layout/notification_expanded.xml b/res/layout/notification_expanded.xml index 70e7269c..e2246506 100644 --- a/res/layout/notification_expanded.xml +++ b/res/layout/notification_expanded.xml @@ -70,7 +70,7 @@ android:layout_weight="0.0" android:background="@drawable/btn_bg" android:scaleType="fitXY" - android:src="@drawable/notification_prev" /> + android:src="@drawable/notification_previous" /> <ImageButton android:id="@+id/control_pause" diff --git a/res/layout/play_video.xml b/res/layout/play_video.xml deleted file mode 100644 index 6a9f3f74..00000000 --- a/res/layout/play_video.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> - - <WebView - android:id="@+id/play_video_contents" - android:layout_width="fill_parent" - android:layout_height="fill_parent"/> - -</FrameLayout> diff --git a/res/layout/playlist_list_item.xml b/res/layout/playlist_list_item.xml deleted file mode 100644 index 1ec5753f..00000000 --- a/res/layout/playlist_list_item.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - - <TextView - android:id="@+id/playlist_name" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textAppearance="?android:attr/textAppearanceMedium" - android:gravity="left|center_vertical" - android:paddingLeft="6dip" - android:paddingRight="6dip" - android:minHeight="50dip"/> - - <ImageView - android:id="@+id/playlist_more" - android:src="@drawable/list_item_more" - android:layout_width="wrap_content" - android:layout_height="fill_parent" - android:layout_gravity="right|center_vertical" - android:paddingRight="6dip" - android:background="@drawable/menubar_button"/> -</LinearLayout>
\ No newline at end of file diff --git a/res/layout/search.xml b/res/layout/search.xml deleted file mode 100644 index d1c5c84c..00000000 --- a/res/layout/search.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/search_layout"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
-
- <include layout="@layout/tab_progress"/>
-
- <ListView
- android:id="@+id/search_list"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0"
- android:fastScrollEnabled="true"
- />
-</LinearLayout>
\ No newline at end of file diff --git a/res/layout/search_buttons.xml b/res/layout/search_buttons.xml index 10b72166..3e3acfac 100644 --- a/res/layout/search_buttons.xml +++ b/res/layout/search_buttons.xml @@ -5,17 +5,6 @@ android:layout_height="wrap_content">
<TextView
- android:id="@+id/search_search"
- android:text="@string/search.search"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:drawablePadding="0dp"
- android:drawableLeft="@drawable/search"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:gravity="center"
- android:padding="12dp"/>
-
- <TextView
android:id="@+id/search_artists"
android:text="@string/search.artists"
android:layout_width="fill_parent"
@@ -82,4 +71,3 @@ android:paddingBottom="8dp"/>
</LinearLayout>
-
diff --git a/res/layout/select_album_footer.xml b/res/layout/select_album_footer.xml deleted file mode 100644 index c1a30a1a..00000000 --- a/res/layout/select_album_footer.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:background="@android:color/transparent"
- android:paddingTop="6dp"
- android:paddingBottom="0dp"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <Button android:id="@+id/select_album_more"
- android:text="@string/select_album.more"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone"
- android:layout_marginLeft="6dp"
- android:layout_marginRight="6dp"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="fill_parent"/>
-
-</LinearLayout>
-
diff --git a/res/layout/select_artist.xml b/res/layout/select_artist.xml deleted file mode 100644 index fef51d3c..00000000 --- a/res/layout/select_artist.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/select_artist_layout"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
-
- <include layout="@layout/tab_progress"/>
-
- <ListView android:id="@+id/select_artist_list"
- android:textFilterEnabled="true"
- android:fastScrollEnabled="true"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0"/>
-</LinearLayout>
-
diff --git a/res/layout/select_artist_header.xml b/res/layout/select_artist_header.xml index 0b3d151b..ba1b3d47 100644 --- a/res/layout/select_artist_header.xml +++ b/res/layout/select_artist_header.xml @@ -14,7 +14,7 @@ android:minHeight="?android:attr/listPreferredItemHeight">
<ImageView
- android:src="@drawable/main_select_server"
+ android:src="?attr/select_server"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
diff --git a/res/layout/select_genres.xml b/res/layout/select_genres.xml deleted file mode 100644 index 95f9d415..00000000 --- a/res/layout/select_genres.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/select_genre_layout" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical" > - - <include layout="@layout/tab_progress" /> - - <TextView - android:id="@+id/select_genre_empty" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:padding="10dip" - android:text="@string/select_genre.empty" - android:visibility="gone" /> - - <ListView - android:id="@+id/select_genre_list" - android:layout_width="fill_parent" - android:layout_height="0dip" - android:layout_weight="1.0" - android:textFilterEnabled="true" - android:fastScrollEnabled="true"/> - </LinearLayout> -</FrameLayout>
\ No newline at end of file diff --git a/res/layout/select_playlist.xml b/res/layout/select_playlist.xml deleted file mode 100644 index e18283bd..00000000 --- a/res/layout/select_playlist.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/select_playlist_layout"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <View
- android:layout_width="fill_parent"
- android:layout_height="1px"
- android:background="@color/dividerColor"/>
-
- <include layout="@layout/tab_progress"/>
-
- <TextView
- android:id="@+id/select_playlist_empty"
- android:text="@string/select_playlist.empty"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="10dip"
- android:visibility="gone"/>
-
- <ListView android:id="@+id/select_playlist_list"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1.0"
- android:fastScrollEnabled="true"/>
-
-</LinearLayout>
-
diff --git a/res/layout/song_list_item.xml b/res/layout/song_list_item.xml index 90060894..3bf7ab44 100644 --- a/res/layout/song_list_item.xml +++ b/res/layout/song_list_item.xml @@ -48,12 +48,20 @@ android:visibility="gone"/>
<TextView
- android:id="@+id/song_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right|center_vertical"
- android:drawablePadding="1dip"
- android:paddingRight="6dip"/>
+ android:id="@+id/song_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right|center_vertical"
+ android:drawablePadding="1dip"
+ android:paddingRight="2dip"/>
+
+ <ImageView
+ android:id="@+id/song_status_icon"
+ android:layout_width="24dip"
+ android:layout_height="24dip"
+ android:layout_gravity="center_vertical"
+ android:src="?attr/downloading"
+ android:visibility="gone"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
@@ -87,10 +95,10 @@ <ImageView
android:id="@+id/artist_more"
- android:src="@drawable/list_item_more"
+ android:src="?attr/download_none"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="right|center_vertical"
- android:paddingRight="6dip"
+ android:paddingRight="10dip"
android:background="@drawable/menubar_button"/>
</LinearLayout>
diff --git a/res/menu/chat.xml b/res/menu/abstract_top_menu.xml index 685aba18..46419d0f 100644 --- a/res/menu/chat.xml +++ b/res/menu/abstract_top_menu.xml @@ -1,19 +1,19 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:compat="http://schemas.android.com/apk/res-auto"> - <item - android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" - android:title="@string/menu.refresh" - compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item - android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" - android:title="@string/menu.exit"/> -</menu>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:compat="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menu_refresh"
+ android:icon="?attr/refresh"
+ android:title="@string/menu.refresh"
+ compat:showAsAction="always|withText"/>
+
+ <item
+ android:id="@+id/menu_search"
+ android:icon="?attr/search"
+ android:title="@string/menu.search"
+ compat:showAsAction="always|withText"/>
+
+ <item
+ android:id="@+id/menu_exit"
+ android:title="@string/menu.exit"/>
+</menu>
diff --git a/res/menu/drawer_menu.xml b/res/menu/drawer_menu.xml new file mode 100644 index 00000000..c2969938 --- /dev/null +++ b/res/menu/drawer_menu.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:compat="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/menu_exit"
+ android:title="@string/menu.exit"/>
+</menu>
diff --git a/res/menu/empty.xml b/res/menu/empty.xml index 979eefe4..9bb43bf7 100644 --- a/res/menu/empty.xml +++ b/res/menu/empty.xml @@ -3,7 +3,7 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> </menu> diff --git a/res/menu/main.xml b/res/menu/main.xml index 1390b68b..5e504242 100644 --- a/res/menu/main.xml +++ b/res/menu/main.xml @@ -3,24 +3,18 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_search" - android:icon="@drawable/action_search" + android:icon="?attr/search" android:title="@string/menu.search" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/menu.shuffle" compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_help" - android:icon="@drawable/action_help" - android:title="@string/menu.help"/> <item android:id="@+id/menu_about" - android:icon="@drawable/action_help" android:title="@string/menu.about"/> <item @@ -31,14 +25,7 @@ android:id="@+id/menu_changelog" android:title="@string/changelog_full_title"/> - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item + <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> - </menu> diff --git a/res/menu/nowplaying.xml b/res/menu/nowplaying.xml index ae411240..3c9c5ba6 100644 --- a/res/menu/nowplaying.xml +++ b/res/menu/nowplaying.xml @@ -3,27 +3,25 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/download.menu_shuffle" compat:showAsAction="ifRoom|withText"/> <item android:id="@+id/menu_remove_all" - android:icon="@drawable/action_remove_all" + android:icon="?attr/remove" android:title="@string/download.menu_remove_all" compat:showAsAction="ifRoom|withText"/> <item android:id="@+id/menu_save_playlist" - android:icon="@drawable/action_save" + android:icon="?attr/save" android:title="@string/download.menu_save" compat:showAsAction="ifRoom|withText"/> <item android:id="@+id/menu_screen_on_off" - android:icon="@drawable/action_screen_on_off" - android:title="@string/download.menu_screen_on" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/download.menu_screen_on"/> <item android:id="@+id/menu_toggle_timer" @@ -32,9 +30,8 @@ <item android:id="@+id/menu_toggle_now_playing" android:title="@string/download.show_downloading"/> - - <item + + <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> </menu> diff --git a/res/menu/nowplaying_downloading.xml b/res/menu/nowplaying_downloading.xml index fbdb78f4..50ab00f3 100644 --- a/res/menu/nowplaying_downloading.xml +++ b/res/menu/nowplaying_downloading.xml @@ -3,19 +3,9 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_remove_all" - android:icon="@drawable/action_remove_all" + android:icon="?attr/remove" android:title="@string/download.menu_remove_all" compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_screen_on_off" - android:icon="@drawable/action_screen_on_off" - android:title="@string/download.menu_screen_on" - compat:showAsAction="ifRoom|withText"/> - - <item - android:id="@+id/menu_toggle_timer" - android:title="@string/download.start_timer"/> <item android:id="@+id/menu_toggle_now_playing" @@ -23,6 +13,5 @@ <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> </menu> diff --git a/res/menu/nowplaying_offline.xml b/res/menu/nowplaying_offline.xml index 3800c013..41d1d5d1 100644 --- a/res/menu/nowplaying_offline.xml +++ b/res/menu/nowplaying_offline.xml @@ -4,28 +4,25 @@ <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/download.menu_shuffle" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_remove_all" - android:icon="@drawable/action_remove_all" + android:icon="?attr/remove" android:title="@string/download.menu_remove_all" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_screen_on_off" - android:icon="@drawable/action_screen_on_off" - android:title="@string/download.menu_screen_on" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/download.menu_screen_on"/> <item android:id="@+id/menu_toggle_timer" android:title="@string/download.start_timer"/> - <item + <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> </menu> diff --git a/res/menu/search.xml b/res/menu/search.xml index fa361566..cab9c4f6 100644 --- a/res/menu/search.xml +++ b/res/menu/search.xml @@ -3,23 +3,12 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_search" - android:icon="@drawable/action_search" + android:icon="?attr/search" android:title="@string/menu.search" compat:showAsAction="ifRoom|withText"/> <item - android:id="@+id/menu_help" - android:icon="@drawable/ic_menu_help" - android:title="@string/menu.help"/> - - <item - android:id="@+id/menu_settings" - android:icon="@drawable/ic_menu_settings" - android:title="@string/menu.settings"/> - - <item android:id="@+id/menu_exit" - android:icon="@drawable/ic_menu_exit" android:title="@string/menu.exit"/> </menu> diff --git a/res/menu/select_album.xml b/res/menu/select_album.xml index 329c479c..469561f1 100644 --- a/res/menu/select_album.xml +++ b/res/menu/select_album.xml @@ -3,19 +3,19 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_play_now" - android:icon="@drawable/action_play_all" + android:icon="?media_button_start" android:title="@string/menu.play" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/menu.shuffle" compat:showAsAction="ifRoom|withText"/> </menu> diff --git a/res/menu/select_album_list.xml b/res/menu/select_album_list.xml index 635a36bf..60b636e3 100644 --- a/res/menu/select_album_list.xml +++ b/res/menu/select_album_list.xml @@ -3,7 +3,7 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> </menu> diff --git a/res/menu/select_artist.xml b/res/menu/select_artist.xml index 3c694cd2..d1e1f4e3 100644 --- a/res/menu/select_artist.xml +++ b/res/menu/select_artist.xml @@ -3,29 +3,23 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/menu.shuffle" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_search" - android:icon="@drawable/action_search" + android:icon="?attr/search" android:title="@string/menu.search" compat:showAsAction="ifRoom|withText"/> - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item + <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> </menu> diff --git a/res/menu/select_bookmark_context.xml b/res/menu/select_bookmark_context.xml new file mode 100644 index 00000000..af11c86f --- /dev/null +++ b/res/menu/select_bookmark_context.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:compat="http://schemas.android.com/apk/res-auto"> + + <item + android:id="@+id/bookmark_menu_info" + android:title="@string/common.info"/> + + <item + android:id="@+id/song_menu_download" + android:title="@string/common.download"/> + + <item + android:id="@+id/song_menu_pin" + android:title="@string/common.pin"/> + + <item + android:id="@+id/song_menu_delete" + android:title="@string/common.delete"/> + + <item + android:id="@+id/bookmark_menu_delete" + android:title="@string/bookmark.delete"/> +</menu> diff --git a/res/menu/select_genres.xml b/res/menu/select_genres.xml index 7ce7f1a0..837b3534 100644 --- a/res/menu/select_genres.xml +++ b/res/menu/select_genres.xml @@ -3,17 +3,7 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item - android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" - android:title="@string/menu.exit"/> </menu>
\ No newline at end of file diff --git a/res/menu/select_playlist.xml b/res/menu/select_playlist.xml deleted file mode 100644 index 4c4cc302..00000000 --- a/res/menu/select_playlist.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:compat="http://schemas.android.com/apk/res-auto"> - <item - android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" - android:title="@string/menu.refresh" - compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_search" - android:icon="@drawable/action_search" - android:title="@string/menu.search" - compat:showAsAction="always|withText"/> - - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item - android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" - android:title="@string/menu.exit"/> -</menu> diff --git a/res/menu/select_podcast_episode.xml b/res/menu/select_podcast_episode.xml index 7e79d0f7..8472325a 100644 --- a/res/menu/select_podcast_episode.xml +++ b/res/menu/select_podcast_episode.xml @@ -3,7 +3,7 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> @@ -13,6 +13,5 @@ <item android:id="@+id/menu_delete" - android:icon="@drawable/action_remove_all" android:title="@string/common.delete"/> </menu> diff --git a/res/menu/select_podcast_episode_offline.xml b/res/menu/select_podcast_episode_offline.xml index cb6d1a3b..4d464c1f 100644 --- a/res/menu/select_podcast_episode_offline.xml +++ b/res/menu/select_podcast_episode_offline.xml @@ -3,12 +3,11 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_delete" - android:icon="@drawable/action_remove_all" android:title="@string/common.delete"/> </menu> diff --git a/res/menu/select_podcasts.xml b/res/menu/select_podcasts.xml index 6c1ffa07..212feb04 100644 --- a/res/menu/select_podcasts.xml +++ b/res/menu/select_podcasts.xml @@ -3,27 +3,25 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> + <item + android:id="@+id/menu_search" + android:icon="?attr/search" + android:title="@string/menu.search" + compat:showAsAction="always|withText"/> + <item android:id="@+id/menu_add_podcast" - android:icon="@drawable/action_exit" android:title="@string/menu.add_podcast"/> <item android:id="@+id/menu_check" - android:icon="@drawable/action_refresh" android:title="@string/menu.check_podcasts"/> - <item - android:id="@+id/menu_settings" - android:icon="@drawable/action_settings" - android:title="@string/menu.settings"/> - - <item + <item android:id="@+id/menu_exit" - android:icon="@drawable/action_exit" android:title="@string/menu.exit"/> </menu>
\ No newline at end of file diff --git a/res/menu/select_podcasts_context_offline.xml b/res/menu/select_podcasts_context_offline.xml new file mode 100644 index 00000000..cbc76224 --- /dev/null +++ b/res/menu/select_podcasts_context_offline.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:compat="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/podcast_channel_info" + android:title="@string/common.info"/> +</menu>
\ No newline at end of file diff --git a/res/menu/select_song.xml b/res/menu/select_song.xml index 658e3ffe..d60dedac 100644 --- a/res/menu/select_song.xml +++ b/res/menu/select_song.xml @@ -3,45 +3,37 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_play_now" - android:icon="@drawable/action_play_all" + android:icon="?attr/media_button_start" android:title="@string/menu.play" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/menu.shuffle" compat:showAsAction="ifRoom|withText"/> <item android:id="@+id/menu_select" - android:icon="@drawable/action_select" - android:title="@string/menu.select" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/menu.select"/> <item android:id="@+id/menu_download" - android:icon="@drawable/action_save" - android:title="@string/common.download" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/common.download"/> <item android:id="@+id/menu_cache" - android:icon="@drawable/action_save" - android:title="@string/common.pin" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/common.pin"/> <item android:id="@+id/menu_delete" - android:icon="@drawable/action_remove_all" - android:title="@string/common.delete" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/common.delete"/> <item android:id="@+id/menu_add_playlist" @@ -53,7 +45,5 @@ <item android:id="@+id/menu_play_last" - android:icon="@drawable/action_play_all" - android:title="@string/menu.play_last" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/menu.play_last"/> </menu> diff --git a/res/menu/select_song_offline.xml b/res/menu/select_song_offline.xml index 7588d9ad..88e9758d 100644 --- a/res/menu/select_song_offline.xml +++ b/res/menu/select_song_offline.xml @@ -3,37 +3,31 @@ xmlns:compat="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_play_now" - android:icon="@drawable/action_play_all" + android:icon="?attr/media_button_start" android:title="@string/menu.play" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_refresh" - android:icon="@drawable/action_refresh" + android:icon="?attr/refresh" android:title="@string/menu.refresh" compat:showAsAction="always|withText"/> <item android:id="@+id/menu_shuffle" - android:icon="@drawable/action_shuffle" + android:icon="?attr/shuffle" android:title="@string/menu.shuffle" compat:showAsAction="ifRoom|withText"/> <item android:id="@+id/menu_select" - android:icon="@drawable/action_select" - android:title="@string/menu.select" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/menu.select"/> <item android:id="@+id/menu_delete" - android:icon="@drawable/action_remove_all" - android:title="@string/common.delete" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/common.delete"/> <item android:id="@+id/menu_play_last" - android:icon="@drawable/action_play_all" - android:title="@string/menu.play_last" - compat:showAsAction="ifRoom|withText"/> + android:title="@string/menu.play_last"/> </menu> diff --git a/res/raw/changelog.xml b/res/raw/changelog.xml index d4ec275a..819263ac 100644 --- a/res/raw/changelog.xml +++ b/res/raw/changelog.xml @@ -1,5 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <changelog> + <release version="4.2.0" versioncode="69" releasedate="11/14/2013"> + <change>Changed from tabs to Pull Out Drawer like newer Google docs specify</change> + <change>Major UI update with better scaling icons</change> + <change>Updated main app icon (thanks Ben Sumner)</change> + <change>Added tablet layout that better uses extra space</change> + <change>New Bookmarks tab</change> + <change>Persistent notification is like other music apps now (change in settings)</change> + <change>Ability to hide Podcasts/Bookmarks/Chat tabs</change> + <change>Pressing next with repeat all on loops back to beginning</change> + <change>Increase right padding so context buttons are easier to press</change> + </release> + <release version="4.1.8" versioncode="66" releasedate="10/26/2013"> + <change>Fix offline shuffle mode</change> + </release> + <release version="4.1.7" versioncode="65" releasedate="10/21/2013"> + <change>Settings screen now broken down by sections</change> + <change>Added option to choose whether or not to pause on headphone/bluetooth disconnect</change> + <change>Added confirm for clearing current queue</change> + <change>Added option to hide widget while nothing is playing</change> + <change>Fix not being able to change position in Jukebox mode</change> + <change>Fix position not being saved sometimes when pausing during a streamed song</change> + <change>Fix sometimes the letters not matching the position on the artist list</change> + <change>Various minor bug fixes</change> + </release> + <release version="4.1.6" versioncode="64" releasedate="10/3/2013"> + <change>Fix recent update sometimes messing up downloaded song</change> + <change>Fix changing position while streaming a song</change> + </release> + <release version="4.1.5" versioncode="63" releasedate="9/27/2013"> + <change>Notification while doing background downloads, clicking will show you the download list</change> + <change>Put songs in the root directory in a new folder called Root at the bottom of the list</change> + <change>Speedup of saving/loading current playing list (mostly matters for those using large playlists)</change> + <change>Cache most common folder listings for better experience while network is intermittent</change> + <change>Speedup of offline playlist loading</change> + <change>Fix app reloading data/losing position on orientation change</change> + <change>Fix Show Album from now playing list</change> + <change>Fix using shuffle in offline mode sometimes using online songs</change> + <change>Various optimizations and bug fixes</change> + </release> <release version="4.1.4" versioncode="61" releasedate="8/25/2013"> <change>Fix for freezes on 4.3</change> <change>Fix for starred songs/albums not being clickable</change> diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml new file mode 100644 index 00000000..594ff0b9 --- /dev/null +++ b/res/values-es/strings.xml @@ -0,0 +1,401 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="common.appname">DSub</string> + <string name="common.ok">OK</string> + <string name="common.save">Guardar</string> + <string name="common.cancel">Cancelar</string> + <string name="common.play_now">Reproducir</string> + <string name="common.play_shuffled">Reproducir en aleatorio</string> + <string name="common.play_next">Siguiente en la cola</string> + <string name="common.play_last">Reproducir al final</string> + <string name="common.download">Caché</string> + <string name="common.pin">Caché permanente</string> + <string name="common.delete">Borrar</string> + <string name="common.star">Poner estrella</string> + <string name="common.unstar">Quitar estrella</string> + <string name="common.info">Detalles</string> + <string name="common.name">Nombre</string> + <string name="common.comment">Comentar</string> + <string name="common.public">Público</string> + <string name="common.play_external">Reproducir vídeo</string> + <string name="common.stream_external">Stream Video</string> + <string name="common.confirm">Confirmar</string> + <string name="common.confirm_message">Quieres %1$s %2$s?</string> + + <string name="button_bar.home">Inicio</string> + <string name="button_bar.browse">Biblioteca</string> + <string name="button_bar.search">Buscar</string> + <string name="button_bar.playlists">Listas de reproducción</string> + <string name="button_bar.now_playing">Ahora suena</string> + <string name="button_bar.podcasts">Podcasts</string> + <string name="button_bar.chat">Chat</string> + + <string name="main.welcome_title">Bienvenido!</string> + <string name="main.welcome_text">Bienvenido a DSub! Ahora la aplicación está configurada para usar el servidor de demostración de Subsonic. Cuando configures tu servidor personal (disponible en <b>subsonic.org</b>), accede a <b>Preferencias</b> y cambia la configuración para conectarte.</string> + <string name="main.about_title">Acerca de DSub</string> + <string name="main.about_text">Autor: Scott Jackson + \nEmail: daneren2005@gmail.com + \nVersión: %1$s + \nEspacio usado: %2$s of %3$s + \nEspacio disponible: %4$s of %5$s</string> + <string name="main.select_server">Seleccionar servidor</string> + <string name="main.shuffle">Reproducción aleatoria</string> + <string name="main.offline">Modo Offline</string> + <string name="main.online">Modo Online</string> + <string name="main.settings">Preferencias</string> + <string name="main.albums_title">Discos</string> + <string name="main.albums_newest">Añadidos recientemente</string> + <string name="main.albums_recent">Reproducidos recientemente</string> + <string name="main.albums_frequent">Más reproducidos</string> + <string name="main.albums_highest">Mejor valorados</string> + <string name="main.albums_starred">Con estrella</string> + <string name="main.albums_random">Aleatorio</string> + <string name="main.albums_genres">Géneros</string> + <string name="main.back_confirm">Pulsa atrás de nuevo para salir</string> + + <string name="menu.search">Buscar</string> + <string name="menu.shuffle">Aleatorio</string> + <string name="menu.refresh">Actualizar</string> + <string name="menu.select">Seleccionar todo</string> + <string name="menu.play">Reproducir</string> + <string name="menu.play_last">Reproducir al final</string> + <string name="menu.exit">Salir</string> + <string name="menu.settings">Preferencias</string> + <string name="menu.help">Ayuda</string> + <string name="menu.about">Acerca de</string> + <string name="menu.add_playlist">Añadir a lista de reproducción</string> + <string name="menu.remove_playlist">Borrar de lista de reproducción</string> + <string name="menu.deleted_playlist">Listas borradas %s</string> + <string name="menu.deleted_playlist_error">Error al borrar la lista de reproducción %s</string> + <string name="menu.log">Enviar Log</string> + <string name="menu.set_timer">Ajustar temporizador</string> + <string name="menu.check_podcasts">Comprobar nuevos episodios</string> + <string name="menu.add_podcast">Añadir canal</string> + <string name="menu.cast">Enviar al dispositivo</string> + + <string name="playlist.label">Listas de reproducción</string> + <string name="playlist.update_info">Actualizar información</string> + <string name="playlist.updated_info">Información actualizada para la lista %s</string> + <string name="playlist.updated_info_error">Error al actualizar la información de la lista %s</string> + <string name="playlist.overwrite">Sobreescribir lista de reproducción actual</string> + <string name="playlist.add_to">Añadir a lista de reproducción</string> + <string name="playlist.create_new">Crear nueva</string> + + <string name="help.label">Ayuda</string> + <string name="help.title">Bienvenido a DSub!</string> + <string name="help.back">Atrás</string> + <string name="help.close">Cerrar</string> + <string name="help.url">file:///android_asset/html/en/index.html</string> + <string name="help.loading">Cargando...</string> + + <string name="play_video.loading">Cargando vídeo...</string> + <string name="play_video.noplugin">Por favor instala Adobe Flash player desde el Android Market.</string> + + <string name="search.label">Buscar</string> + <string name="search.title">Buscar</string> + <string name="search.search">Click para buscar</string> + <string name="search.no_match">No hay coincidencias, inténtelo de nuevo</string> + <string name="search.artists">Artista</string> + <string name="search.albums">Disco</string> + <string name="search.songs">Canción</string> + <string name="search.more">Mostrar más</string> + + <string name="progress.wait">Espere por favor...</string> + + <string name="music_library.label">Biblioteca de medios</string> + <string name="music_library.label_offline">Archivos Offline</string> + + <string name="select_album.empty">Vacío</string> + <string name="select_album.select">Seleccionar todo</string> + <string name="select_album.n_selected">Seleccionadas %d canciones</string> + <string name="select_album.n_unselected">%d canciones deseleccionadas</string> + <string name="select_album.more">Más</string> + <string name="select_album.offline">Offline</string> + <string name="select_album.searching">Buscando...</string> + <string name="select_album.no_sdcard">Error: No hay tarjeta SD disponible</string> + <string name="select_album.no_network">Aviso: No hay red disponible</string> + <string name="select_album.not_licensed">Servidor sin licencia. Quedan %d días de prueba</string> + <string name="select_album.donate_dialog_message">Consigue descargas ilimitadas haciendo una donación a Subsonic</string> + <string name="select_album.donate_dialog_now">Ahora</string> + <string name="select_album.donate_dialog_later">Más tarde</string> + <string name="select_album.donate_dialog_0_trial_days_left">Periodo de prueba terminado</string> + + <string name="offline.sync_dialog_title">Canciones offline esperando a ser sincronizadas</string> + <string name="offline.sync_dialog_message">Procesar %1$d offline scrobbles? + \nProcesar %2$d estrellas offline? + </string> + <string name="offline.sync_dialog_default">Usar esta acción por defecto</string> + <string name="offline.sync_success">%1$d canciones sincronizadas correctamente</string> + <string name="offline.sync_partial">%1$d de %2$d canciones sincronizadas</string> + <string name="offline.sync_error">Error al sincronizar canciones</string> + + <string name="select_genre.empty">No se han encontrado géneros</string> + <string name="select_genre.blank">Vacío</string> + + <string name="select_podcasts.empty">No se han encontrado podcasts</string> + <string name="select_podcasts.error">Ha habido un error descargando este podcast en el servidor. El servidor debe descargarlo antes.</string> + <string name="select_podcasts.skipped">Este podcast no ha sido descargado en el servidor. El servidor debe descargarlo antes.</string> + <string name="select_podcasts.initializing">Este podcast está siendo reiniciado en el servidor. Por favor, actualice en unos segundos.</string> + <string name="select_podcasts.server_download">Descargar en el servidor</string> + <string name="select_podcasts.server_delete">Borrar en el servidor</string> + <string name="select_podcasts.downloading">Descargando %s en el servidor</string> + <string name="select_podcasts.refreshing">El servidor está comprobando nuevos podcasts ahora</string> + <string name="select_podcasts.deleted">Podcasts eliminados %s</string> + <string name="select_podcasts.deleted_error">Error al elimintar el podcast %s</string> + <string name="select_podcasts.add_url">URL:</string> + <string name="select_podcasts.created_error">Error al agregar podcast</string> + <string name="select_podcasts.invalid_podcast_channel">Canal de podcast no valido: %s</string> + + <string name="select_playlist.empty">No hay listas de reproducción guardadas en el servidor</string> + + <string name="download.empty">Lista de reproducción vaía</string> + <string name="download.shuffle_loading">Cargando lista aleatoria...</string> + <string name="download.playerstate_downloading">Descargando - %s</string> + <string name="download.playerstate_buffering">Buffering</string> + <string name="download.playerstate_playing_shuffle">Reproduciendo en aleatorio</string> + <string name="download.menu_show_album">Mostrar disco</string> + <string name="download.menu_lyrics">Letras</string> + <string name="download.menu_remove">Eliminar de la cola</string> + <string name="download.menu_delete">Borrar cache</string> + <string name="download.menu_remove_all">Borrar todo</string> + <string name="download.menu_screen_on">Pantalla encendida</string> + <string name="download.menu_screen_off">Pantalla apagada</string> + <string name="download.menu_shuffle">Aleatorio</string> + <string name="download.menu_toggle">Cambiar</string> + <string name="download.menu_save">Guardar lista de reproducción</string> + <string name="download.menu_shuffle_notification">Lista de reproducción en aleatorio</string> + <string name="download.playlist_title">Guardar lista de reproducción</string> + <string name="download.playlist_name">Introduce un nombre válido para la lista de reproducción:</string> + <string name="download.playlist_saving">Guardando lista de reproducción \"%s\"...</string> + <string name="download.playlist_done">Lista de reproducción guardada.</string> + <string name="download.playlist_error">Error al guardar la lista de reproducción, inténtelo más tarde.</string> + <string name="download.repeat_off">Repetir off</string> + <string name="download.repeat_all">Repetir todo</string> + <string name="download.repeat_single">Repetir canción</string> + <string name="download.visualizer_on">Visualizador encendido.</string> + <string name="download.visualizer_off">Visualizador apagado.</string> + <string name="download.jukebox_on">Control remoto encendido. La música se está reproduciendo en el ordenador.</string> + <string name="download.jukebox_off">Control remoto apagado. La música se está reproduciendo en el dispositivo móvil.</string> + <string name="download.jukebox_volume">Volumen remoto</string> + <string name="download.jukebox_server_too_old">Control remoto no soportado. Por favor, actualice su servidor Subsonic.</string> + <string name="download.jukebox_offline">Control remoto no disponible en modo offline.</string> + <string name="download.jukebox_not_authorized">Control remoto no permitido. Por favor, active el modo jukebox en <b>Users > Settings</b> en su servidor Subsonic.</string> + <string name="download.show_downloading">Mostrar descargas</string> + <string name="download.show_now_playing">Mostrar reproduciendo ahora</string> + <string name="download.timer_length">Temporizador</string> + <string name="download.start_timer">Iniciar temporizador</string> + <string name="download.stop_timer">Detener temporizador</string> + <string name="download.need_download">El vídeo ha de ser descargado antes</string> + <string name="download.no_streaming_player">Ningún reproductor puede reproducir este stream</string> + <string name="download.playing_out_of">Reproduciendo: %1$d/%2$d</string> + + <string name="starring_content_starred">Marcado con estrella \"%s\"</string> + <string name="starring_content_unstarred">Sin marca de estrella \"%s\"</string> + <string name="starring_content_error">Error al actualizar \"%s\", inténtelo más tarde.</string> + + <string name="playlist_error">Error al obtener las listas de reproducción</string> + <string name="updated_playlist">Añadida %1$s canción a \"%2$s\"</string> + <string name="updated_playlist_error">Error al actualizar \"%s\", inténtelo más tarde.</string> + <string name="removed_playlist">Borrar %1$s canciones de \"%2$s\"</string> + + <string name="song_details.all">%1$s %2$s</string> + <string name="song_details.kbps">%d kbps</string> + <string name="song_details.error">Error</string> + <string name="song_details.skipped">Saltados</string> + <string name="song_details.downloading">Descargando</string> + + <string name="lyrics.nomatch">No se han encontrado letras</string> + + <string name="error.label">Error</string> + + <string name="settings.title">Ajustes de DSub</string> + <string name="settings.test_connection_title">Comprobar conexión</string> + <string name="settings.servers_add">Añadir servidor</string> + <string name="settings.servers_remove">Borrar servidor</string> + <string name="settings.servers_title">Servidores</string> + <string name="settings.server_unused">Sin usar</string> + <string name="settings.server_name">Nombre</string> + <string name="settings.server_address">Dirección del servidor</string> + <string name="settings.server_username">Usuario</string> + <string name="settings.server_password">Contraseña</string> + <string name="settings.server_open_browser">Abrir en el navegador</string> + <string name="settings.cache_title">Caché de música</string> + <string name="settings.preload_wifi">Canciones para precargar (Wifi)</string> + <string name="settings.preload_mobile">Canciones pare precargar (Móvil)</string> + <string name="settings.cache_size">Tamaño de caché (MB)</string> + <string name="settings.cache_location">Ruta de caché</string> + <string name="settings.cache_location_error">Ruta de caché no válida. Utilizando la opción por defecto.</string> + <string name="settings.cache_clear">Limpiar cache</string> + <string name="settings.cache_clear_complete">Caché limpiada</string> + <string name="settings.testing_connection">Probando conexión...</string> + <string name="settings.testing_ok">Conexión correcta</string> + <string name="settings.testing_unlicensed">Conexión correcta. Servidor sin licencia.</string> + <string name="settings.connection_failure">Error de conexión.</string> + <string name="settings.invalid_url">Introduzca una URL válida.</string> + <string name="settings.invalid_username">Por favor, especifique un usuario válido.</string> + <string name="settings.appearance_title">Apariencia</string> + <string name="settings.theme_title">Tema</string> + <string name="settings.theme_light">Claro</string> + <string name="settings.theme_dark">Oscuro</string> + <string name="settings.theme_black">Negro</string> + <string name="settings.theme_holo">Holo</string> + <string name="settings.theme_light_fullscreen">Claro pantalla completa</string> + <string name="settings.theme_dark_fullscreen">Oscuro pantalla completa</string> + <string name="settings.theme_black_fullscreen">Negro pantalla completa</string> + <string name="settings.theme_holo_fullscreen">Holo pantalla completa</string> + <string name="settings.track_title">Mostrar número de pista</string> + <string name="settings.track_summary">Mostrar número de pista al inicio de la canción si existe</string> + <string name="settings.network_title">Red</string> + <string name="settings.max_bitrate_wifi">Bitrate máximo - Wi-Fi</string> + <string name="settings.max_bitrate_mobile">Bitrate máximo - Móvil</string> + <string name="settings.max_bitrate_32">32 Kbps</string> + <string name="settings.max_bitrate_64">64 Kbps</string> + <string name="settings.max_bitrate_80">80 Kbps</string> + <string name="settings.max_bitrate_96">96 Kbps</string> + <string name="settings.max_bitrate_112">112 Kbps</string> + <string name="settings.max_bitrate_128">128 Kbps</string> + <string name="settings.max_bitrate_160">160 Kbps</string> + <string name="settings.max_bitrate_192">192 Kbps</string> + <string name="settings.max_bitrate_256">256 Kbps</string> + <string name="settings.max_bitrate_320">320 Kbps</string> + <string name="settings.max_video_bitrate_wifi">Bitrate de vídeo máximo - Wi-Fi</string> + <string name="settings.max_video_bitrate_mobile">Bitrate de vídeo máximo - Móvil</string> + <string name="settings.max_video_bitrate_200">200 Kbps</string> + <string name="settings.max_video_bitrate_300">300 Kbps</string> + <string name="settings.max_video_bitrate_400">400 Kbps</string> + <string name="settings.max_video_bitrate_500">500 Kbps</string> + <string name="settings.max_video_bitrate_700">700 Kbps</string> + <string name="settings.max_video_bitrate_1000">1000 Kbps</string> + <string name="settings.max_video_bitrate_1500">1500 Kbps</string> + <string name="settings.max_video_bitrate_2000">2000 Kbps</string> + <string name="settings.max_video_bitrate_3000">3000 Kbps</string> + <string name="settings.max_video_bitrate_5000">5000 Kbps</string> + <string name="settings.max_bitrate_unlimited">Ilimitado</string> + <string name="settings.wifi_required_title">Streaming sólo en Wi-Fi</string> + <string name="settings.wifi_required_summary">Sólo utilizar streaming si estás conectado a Wi-Fi</string> + <string name="settings.network_timeout_title">Network Timeout</string> + <string name="settings.network_timeout_10000">10 seconds</string> + <string name="settings.network_timeout_15000">15 seconds</string> + <string name="settings.network_timeout_30000">30 seconds</string> + <string name="settings.network_timeout_45000">45 seconds</string> + <string name="settings.network_timeout_60000">60 seconds</string> + <string name="settings.preload_1">1 canción</string> + <string name="settings.preload_2">2 canciones</string> + <string name="settings.preload_3">3 canciones</string> + <string name="settings.preload_5">5 canciones</string> + <string name="settings.preload_10">10 canciones</string> + <string name="settings.preload_unlimited">Ilimitado</string> + <string name="settings.clear_search_history">Borrar historial de búsqueda</string> + <string name="settings.search_history_cleared">Historial de búsqueda borrado</string> + <string name="settings.other_title">Otros ajustes</string> + <string name="settings.scrobble_title">Scrobblear a Last.fm</string> + <string name="settings.scrobble_summary">Recuerde configurar su usuario y contraseña de Last.fm en su servidor</string> + <string name="settings.hide_media_title">Ocultar del resto</string> + <string name="settings.hide_media_summary">Ocultar archivos de música de otras aplicaciones.</string> + <string name="settings.hide_media_toast">Se aplicará la próxima vez que Android escanee la música de su teléfono.</string> + <string name="settings.media_button_title">Botones multimedia</string> + <string name="settings.media_button_summary">Responder a los botones Bluetooth, teléfono y manos libres</string> + <string name="settings.screen_lit_title">Mantener pantalla encendida</string> + <string name="settings.screen_lit_summary">Mantener la pantalla encendida durantes las descargas mejora la velocidad de descarga.</string> + <string name="settings.playlist_title">Listas de reproducción</string> + <string name="settings.playlist_random_size_title">Tamaño aleatorio</string> + <string name="settings.buffer_length">Tamaño del buffer (0 = totalmente en caché)</string> + <string name="settings.sleep_timer_title">Temporizador</string> + <string name="settings.sleep_timer_duration_title">Duración del temporizador</string> + <string name="settings.sleep_timer_off">Encendido</string> + <string name="settings.sleep_timer_on">Apagado</string> + <string name="settings.sleep_timer_always_on">Siempre encendido</string> + <string name="settings.temp_loss_title">Pérdida temporal de foco</string> + <string name="settings.temp_loss_pause">Pausar siempre</string> + <string name="settings.temp_loss_pause_lower">Pausar, bajar el volumen cuando sea solicitado</string> + <string name="settings.temp_loss_lower">Bajar volumen siempre</string> + <string name="settings.temp_loss_nothing">No hacer nada</string> + <string name="settings.persistent_title">Notificación permanente</string> + <string name="settings.persistent_summary">Mostrar la notificación incluso tras pausar. Pulsar botón stop para quitarlo.</string> + <string name="settings.gapless_playback">Reproducción sin pausas</string> + <string name="settings.gapless_playback_summary">El Galaxy S3 parece sufrir algunos bloqueos y funcionamentos extraños desde la introducción de la reproducción sin pausas. Desmarca esta opción para solucionar el problema.</string> + <string name="settings.chat_refresh">Tiempo de actualización de chat (Segundos)</string> + <string name="settings.chat_enabled">Chat habilitado</string> + <string name="settings.chat_enabled_summary">Para mostrar o no mostrar la pestaña de chat. Reinicia la aplicación tras el cambio.</string> + <string name="settings.video_title">Vídeo</string> + <string name="settings.video_player">Reproductor de vídeo</string> + <string name="settings.video_raw">Raw (Requiere Subsonic 4.8+)</string> + <string name="settings.video_hls">HTTP Live Stream (HLS) (Requiere Subsonic 4.8+)</string> + <string name="settings.video_transcode">Transcodificación directa (Requisitos de vídeo -> configurar mp4 o similar en el servidor)</string> + <string name="settings.video_flash">Flash (Requiere Plugin)</string> + + <string name="shuffle.title">Iniciar aleatorio por</string> + <string name="shuffle.startYear">Año inicial:</string> + <string name="shuffle.endYear">Año final:</string> + <string name="shuffle.genre">Género:</string> + <string name="shuffle.pick_genre">Seleccionar género</string> + + <string name="music_service.retry">Error de red. Reintentando %1$d de %2$d.</string> + + <string name="background_task.wait">Por favor, espere...</string> + <string name="background_task.loading">Cargando.</string> + <string name="background_task.no_network">Este programa requiere de acceso a la red. Encienda el Wi-Fi o la conexión de datos móviles.</string> + <string name="background_task.network_error">Error de red. Por favor, compruebe la dirección del servidor o inténtelo más tarde.</string> + <string name="background_task.not_found">Recurso no encontrado. Por favor, compruebe la dirección del servidor.</string> + <string name="background_task.parse_error">Respuesta desconocida. Por favor, compruebe la dirección del servidor.</string> + + <string name="service.connecting">Conectando con el servidor, espere por favor.</string> + + <string name="parser.reading">Leyendo desde el servidor.</string> + <string name="parser.reading_done">Leyendo desde el servidor. Hecho!</string> + <string name="parser.upgrade_client">Versiones incompatibles. Por favor, actualice la aplicación DSub de Android.</string> + <string name="parser.upgrade_server">Versiones incompatibles. Por favor, actualice su servidor Subsonic.</string> + <string name="parser.not_authenticated">Usuario o contraseña inconrrectos.</string> + <string name="parser.not_authorized">Sin autorización. Compruebe los permisos en el servidor Subsonic.</string> + <string name="parser.artist_count">Recibidos %d artistas.</string> + + <string name="select_artist.refresh">Actualizar</string> + <string name="select_artist.folder">Seleccionar carpeta</string> + <string name="select_artist.all_folders">Todas las carpetas</string> + + <string name="equalizer.label">Ecualizador</string> + <string name="equalizer.enabled">Activado</string> + <string name="equalizer.preset">Seleccionar preset</string> + + <string name="widget.4x1">DSub (4x1)</string> + <string name="widget.4x2">DSub (4x2)</string> + <string name="widget.4x3">DSub (4x3)</string> + <string name="widget.4x4">DSub (4x4)</string> + <string name="widget.initial_text">Toca para seleccionar música</string> + <string name="widget.sdcard_busy">Tarjeta SD no disponible</string> + <string name="widget.sdcard_missing">No hay tarjeta SD</string> + + <string name="util.bytes_format.gigabyte">0.00 GB</string> + <string name="util.bytes_format.megabyte">0.00 MB</string> + <string name="util.bytes_format.kilobyte">0 KB</string> + <string name="util.bytes_format.byte">0 B</string> + + <string name="changelog_full_title">Log de cambios</string> + <string name="changelog_title">Novedades</string> + <string name="changelog_ok_button">OK</string> + <string name="changelog_show_full">Más…</string> + + <string name="chat.send_a_message">Enviar un mensaje</string> + + <string name="changelog_version_format" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">Version <xliff:g id="version_name">%s</xliff:g></string> + + <plurals name="select_album_n_songs"> + <item quantity="zero">Sin canciones</item> + <item quantity="one">Una canción</item> + <item quantity="other">%d canciones</item> + </plurals> + <plurals name="select_album_n_songs_downloading"> + <item quantity="one">Una canción programada para descarga.</item> + <item quantity="other">%d canciones programadas para descarga.</item> + </plurals> + <plurals name="select_album_n_songs_added"> + <item quantity="one">Canción añadida a la cola.</item> + <item quantity="other">%d canciones añadidas a la cola.</item> + </plurals> + <plurals name="select_album_donate_dialog_n_trial_days_left"> + <item quantity="one">Queda un día del periodo de prueba</item> + <item quantity="other">Quedan %d días del periodo de prueba</item> + </plurals> + +</resources> diff --git a/res/values-large/dimens.xml b/res/values-large/dimens.xml new file mode 100644 index 00000000..4e29290d --- /dev/null +++ b/res/values-large/dimens.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="Button">64dip</dimen>
+ <dimen name="Button.Small">54dip</dimen>
+</resources>
\ No newline at end of file diff --git a/res/values-v16/themes.xml b/res/values-v16/themes.xml new file mode 100644 index 00000000..aabcfaa9 --- /dev/null +++ b/res/values-v16/themes.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="DSub.TextViewStyle" parent="android:Widget.TextView">
+ <item name="android:fontFamily">sans-serif-light</item>
+ </style>
+
+ <style name="DSub.ButtonStyle" parent="android:Widget.Holo.Button">
+ <item name="android:fontFamily">sans-serif-light</item>
+ </style>
+</resources>
\ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index b558d68e..7e90c727 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1,5 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <resources> + <string-array name="drawerItems"> + <item>@string/button_bar.home</item> + <item>@string/button_bar.browse</item> + <item>@string/button_bar.playlists</item> + <item>@string/button_bar.podcasts</item> + <item>@string/button_bar.bookmarks</item> + <item>@string/button_bar.chat</item> + <item>@string/menu.settings</item> + </string-array> + + <string-array name="drawerItemsDescriptions"> + <item>Home</item> + <item>Artist</item> + <item>Playlist</item> + <item>Podcast</item> + <item>Bookmark</item> + <item>Chat</item> + <item>Settings</item> + </string-array> + + <array name="drawerItemIconsLight"> + <item>@drawable/main_offline_light</item> + <item>@drawable/ic_menu_library_light</item> + <item>@drawable/ic_menu_playlist_light</item> + <item>@drawable/ic_menu_podcast_light</item> + <item>@drawable/ic_menu_bookmark_light</item> + <item>@drawable/ic_menu_chat_light</item> + <item>@drawable/ic_menu_settings_light</item> + </array> + + <array name="drawerItemIconsDark"> + <item>@drawable/main_offline_dark</item> + <item>@drawable/ic_menu_library_dark</item> + <item>@drawable/ic_menu_playlist_dark</item> + <item>@drawable/ic_menu_podcast_dark</item> + <item>@drawable/ic_menu_bookmark_dark</item> + <item>@drawable/ic_menu_chat_dark</item> + <item>@drawable/ic_menu_settings_dark</item> + </array> <string-array name="themeValues"> <item>light</item> @@ -137,6 +176,19 @@ <item>@string/settings.temp_loss_nothing</item> </string-array> + <string-array name="disconnectPauseValues"> + <item>0</item> + <item>1</item> + <item>2</item> + <item>3</item> + </string-array> + <string-array name="disconnectPauseNames"> + <item>@string/settings.disconnect_pause_both</item> + <item>@string/settings.disconnect_pause_headphone</item> + <item>@string/settings.disconnect_pause_bluetooth</item> + <item>@string/settings.disconnect_pause_neither</item> + </string-array> + <string-array name="videoPlayerValues"> <item>raw</item> <item>hls</item> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 8f669cd2..ae0939f1 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -7,6 +7,17 @@ <attr name="media_button_repeat_off" format="reference"/> <attr name="media_button_start" format="reference"/> <attr name="media_button_stop" format="reference"/> - <attr name="chat" format="reference"/> - <attr name="chat_send" format="reference" /> + <attr name="chat_send" format="reference"/> + <attr name="download_none" format="reference"/> + <attr name="shuffle" format="reference"/> + <attr name="refresh" format="reference"/> + <attr name="search" format="reference"/> + <attr name="remove" format="reference"/> + <attr name="save" format="reference"/> + <attr name="volume" format="reference"/> + <attr name="toggle_list" format="reference"/> + <attr name="select_server" format="reference"/> + <attr name="downloading" format="reference"/> + <attr name="bookmark" format="reference"/> + <attr name="drawerItemsIcons" format="reference"/> </resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml new file mode 100644 index 00000000..b504b105 --- /dev/null +++ b/res/values/dimens.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <dimen name="Button">54dip</dimen>
+ <dimen name="Button.Small">46dip</dimen>
+</resources>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 87667e51..52c899e2 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -22,13 +22,15 @@ <string name="common.stream_external">Stream Video</string>
<string name="common.confirm">Confirm</string>
<string name="common.confirm_message">Do you want to %1$s %2$s?</string>
+ <string name="common.empty">None found</string>
<string name="button_bar.home">Home</string>
<string name="button_bar.browse">Library</string>
<string name="button_bar.search">Search</string>
<string name="button_bar.playlists">Playlists</string>
- <string name="button_bar.now_playing">Playing</string>
+ <string name="button_bar.now_playing">Now Playing</string>
<string name="button_bar.podcasts">Podcasts</string>
+ <string name="button_bar.bookmarks">Bookmarks</string>
<string name="button_bar.chat">Chat</string>
<string name="main.welcome_title">Welcome!</string>
@@ -130,10 +132,8 @@ <string name="offline.sync_partial">Successfully synced %1$d of %2$d songs</string>
<string name="offline.sync_error">Failed to sync songs</string>
- <string name="select_genre.empty">No genres found</string>
<string name="select_genre.blank">Blank</string>
- <string name="select_podcasts.empty">No podcasts found</string>
<string name="select_podcasts.error">This podcast had an error while downloading on the server. The server must download it first.</string>
<string name="select_podcasts.skipped">This podcast has not been downloaded on the server. The server must download it first.</string>
<string name="select_podcasts.initializing">This podcast channel is being initialized on the server. Please reload after a moment.</string>
@@ -147,8 +147,6 @@ <string name="select_podcasts.created_error">Failed to add podcast</string>
<string name="select_podcasts.invalid_podcast_channel">Invalid podcast channel: %s</string>
- <string name="select_playlist.empty">No saved playlists on server</string>
-
<string name="download.empty">Playlist is empty</string>
<string name="download.shuffle_loading">Shuffle list is loading...</string>
<string name="download.playerstate_downloading">Downloading - %s</string>
@@ -189,6 +187,8 @@ <string name="download.need_download">Video needs to be downloaded first</string>
<string name="download.no_streaming_player">No player can play this stream</string>
<string name="download.playing_out_of">Playing: %1$d/%2$d</string>
+ <string name="download.save_bookmark_title">Create bookmark</string>
+ <string name="download.save_bookmark">Bookmark created</string>
<string name="starring_content_starred">Starred \"%s\"</string>
<string name="starring_content_unstarred">Unstarred \"%s\"</string>
@@ -198,6 +198,17 @@ <string name="updated_playlist">Added %1$s songs to \"%2$s\"</string>
<string name="updated_playlist_error">Failed to update \"%s\", please try later.</string>
<string name="removed_playlist">Removed %1$s songs from \"%2$s\"</string>
+
+ <string name="bookmark.delete">Delete bookmark</string>
+ <string name="bookmark.delete_title">Delete the bookmark for</string>
+ <string name="bookmark.deleted">Deleted the bookmark for \"%s\"</string>
+ <string name="bookmark.deleted_error">Failed to delete the bookmark for \"%s\"</string>
+ <string name="bookmark.details_title">Bookmark Details</string>
+ <string name="bookmark.details">Song: %1$s
+ \nPosition: %2$s
+ \nCreated: %3$s
+ \nLast Updated: %4$s
+ \nComment: %5$s</string>
<string name="song_details.all">%1$s %2$s</string>
<string name="song_details.kbps">%d kbps</string>
@@ -290,7 +301,7 @@ <string name="settings.search_history_cleared">Search history cleared</string>
<string name="settings.other_title">Other settings</string>
<string name="settings.scrobble_title">Scrobble to Last.fm</string>
- <string name="settings.scrobble_summary">Remember to set up your Last.fm user and password on the DSub server</string>
+ <string name="settings.scrobble_summary">Remember to set up your Last.fm user and password on the Subsonic server</string>
<string name="settings.hide_media_title">Hide from other</string>
<string name="settings.hide_media_summary">Hide music files from other apps.</string>
<string name="settings.hide_media_toast">Takes effect next time Android scans your phone for music.</string>
@@ -311,19 +322,32 @@ <string name="settings.temp_loss_pause_lower">Pause, lower volume when requested</string>
<string name="settings.temp_loss_lower">Always lower volume</string>
<string name="settings.temp_loss_nothing">Do Nothing</string>
+ <string name="settings.disconnect_pause_title">Pause on Disconnect</string>
+ <string name="settings.disconnect_pause_both">Pause on either</string>
+ <string name="settings.disconnect_pause_headphone">Pause only for headphone</string>
+ <string name="settings.disconnect_pause_bluetooth">Pause only for bluetooth</string>
+ <string name="settings.disconnect_pause_neither">Do Nothing</string>
<string name="settings.persistent_title">Persistent Notification</string>
<string name="settings.persistent_summary">Show the notification even after pausing. Press the stop button to clear it away.</string>
<string name="settings.gapless_playback">Gapless Playback</string>
<string name="settings.gapless_playback_summary">The Galaxy S3 seems to be experiencing freezes/other weird issue since the introduction of gapless playback. Turn this off to fix the issue.</string>
<string name="settings.chat_refresh">Chat Refresh Rate (Secs)</string>
<string name="settings.chat_enabled">Chat Enabled</string>
- <string name="settings.chat_enabled_summary">Whether or not to display the chat tab. Restart app after changing.</string>
+ <string name="settings.chat_enabled_summary">Whether or not to display the chat listing in the pull out drawer</string>
<string name="settings.video_title">Video</string>
<string name="settings.video_player">Video Player</string>
<string name="settings.video_raw">Raw (Requires Subsonic 4.8+)</string>
<string name="settings.video_hls">HTTP Live Stream (HLS) (Requires Subsonic 4.8+)</string>
<string name="settings.video_transcode">Direct Transcode (Requires video -> mp4 or similar setup on Server)</string>
<string name="settings.video_flash">Flash (Requires Plugin)</string>
+ <string name="settings.cache_screen_title">Cache/Network</string>
+ <string name="settings.playback_title">Playback</string>
+ <string name="settings.hide_widget_title">Hide Widget</string>
+ <string name="settings.hide_widget_summary">Hide widget after exiting app</string>
+ <string name="settings.podcasts_enabled">Podcasts Enabled</string>
+ <string name="settings.podcasts_enabled_summary">Whether or not to display the podcast listing in the pull out drawer</string>
+ <string name="settings.bookmarks_enabled">Bookmarks Enabled</string>
+ <string name="settings.bookmarks_enabled_summary">Whether or not to display the bookmarks listing in the pull out drawer</string>
<string name="settings.sync_title">Sync</string>
<string name="settings.sync_enabled">Sync Enabled</string>
<string name="settings.sync_enabled_summary">Whether or not playlists or podcasts are periodically checked for changes</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml index 4dcce34f..b1475eb6 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -6,15 +6,15 @@ <item name="android:padding">6dip</item> <item name="android:layout_marginLeft">4dip</item> <item name="android:layout_marginRight">4dip</item> - <item name="android:layout_width">54dip</item> - <item name="android:layout_height">54dip</item> + <item name="android:layout_width">@dimen/Button</item> + <item name="android:layout_height">@dimen/Button</item> <item name="android:contentDescription">@null</item> </style> <style name="PlaybackControl.Small" parent="@style/PlaybackControl"> <item name="android:padding">4dip</item> - <item name="android:layout_width">46dip</item> - <item name="android:layout_height">46dip</item> + <item name="android:layout_width">@dimen/Button.Small</item> + <item name="android:layout_height">@dimen/Button.Small</item> </style> <style name="MenuBarButton"> @@ -27,6 +27,28 @@ <item name="android:textColor">?android:textColorPrimary</item> </style> + <style name="DownloadActionButton"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:textStyle">bold</item> + <item name="android:textSize">22sp</item> + <item name="android:background">@drawable/menubar_button</item> + <item name="android:paddingTop">4dip</item> + <item name="android:paddingBottom">4dip</item> + <item name="android:paddingRight">4dip</item> + <item name="android:paddingLeft">4dip</item> + </style> + + <style name="DownloadActionImageButton"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:background">@drawable/menubar_button</item> + <item name="android:paddingTop">8dip</item> + <item name="android:paddingBottom">8dip</item> + <item name="android:paddingRight">16dip</item> + <item name="android:paddingLeft">16dip</item> + </style> + <style name="DragDropListView"> <item name="drag_enabled">true</item> <item name="collapsed_height">1dp</item> diff --git a/res/values/themes.xml b/res/values/themes.xml index b2aa8277..1b2078a7 100644 --- a/res/values/themes.xml +++ b/res/values/themes.xml @@ -10,22 +10,48 @@ <item name="media_button_repeat_off">@drawable/media_repeat_off_light</item> <item name="media_button_start">@drawable/media_start_light</item> <item name="media_button_stop">@drawable/media_stop_light</item> - <item name="chat">@drawable/ic_menu_chat_light</item> - <item name="chat_send">@drawable/ic_menu_chat_send_light</item> + <item name="chat_send">@drawable/ic_menu_chat_send_light</item> + <item name="download_none">@drawable/download_none_light</item> + <item name="shuffle">@drawable/ic_menu_shuffle_light</item> + <item name="refresh">@drawable/ic_menu_refresh_light</item> + <item name="search">@drawable/ic_menu_search_light</item> + <item name="remove">@drawable/ic_menu_remove_light</item> + <item name="save">@drawable/ic_menu_save_light</item> + <item name="volume">@drawable/ic_action_volume_light</item> + <item name="toggle_list">@drawable/action_toggle_list_light</item> + <item name="select_server">@drawable/main_select_server_light</item> + <item name="downloading">@drawable/downloading_light</item> + <item name="bookmark">@drawable/ic_menu_bookmark_light</item> + <item name="drawerItemsIcons">@array/drawerItemIconsLight</item> + <item name="android:textViewStyle">@style/DSub.TextViewStyle</item> + <item name="android:buttonStyle">@style/DSub.ButtonStyle</item> </style> <style name="Theme.DSub.Dark" parent="@style/Theme.AppCompat"> <item name="actionBarStyle">@style/Widget.DSub.ActionBarStyle.Dark</item> <item name="android:actionBarStyle">@style/Widget.DSub.ActionBarStyle.Dark</item> <item name="android:textColorSecondary">@color/cyan</item> - <item name="offline_icon">@drawable/main_offline</item> - <item name="media_button_backward">@drawable/media_backward</item> - <item name="media_button_forward">@drawable/media_forward</item> - <item name="media_button_pause">@drawable/media_pause</item> + <item name="offline_icon">@drawable/main_offline_dark</item> + <item name="media_button_backward">@drawable/media_backward_dark</item> + <item name="media_button_forward">@drawable/media_forward_dark</item> + <item name="media_button_pause">@drawable/media_pause_dark</item> <item name="media_button_repeat_off">@drawable/media_repeat_off</item> - <item name="media_button_start">@drawable/media_start</item> - <item name="media_button_stop">@drawable/media_stop</item> - <item name="chat">@drawable/ic_menu_chat_dark</item> - <item name="chat_send">@drawable/ic_menu_chat_send_dark</item> + <item name="media_button_start">@drawable/media_start_dark</item> + <item name="media_button_stop">@drawable/media_stop_dark</item> + <item name="chat_send">@drawable/ic_menu_chat_send_dark</item> + <item name="download_none">@drawable/download_none_dark</item> + <item name="shuffle">@drawable/ic_menu_shuffle_dark</item> + <item name="refresh">@drawable/ic_menu_refresh_dark</item> + <item name="search">@drawable/ic_menu_search_dark</item> + <item name="remove">@drawable/ic_menu_remove_dark</item> + <item name="save">@drawable/ic_menu_save_dark</item> + <item name="volume">@drawable/ic_action_volume_dark</item> + <item name="toggle_list">@drawable/action_toggle_list_dark</item> + <item name="select_server">@drawable/main_select_server_dark</item> + <item name="downloading">@drawable/downloading_dark</item> + <item name="bookmark">@drawable/ic_menu_bookmark_dark</item> + <item name="drawerItemsIcons">@array/drawerItemIconsDark</item> + <item name="android:textViewStyle">@style/DSub.TextViewStyle</item> + <item name="android:buttonStyle">@style/DSub.ButtonStyle</item> </style> <style name="Theme.DSub.Black" parent="Theme.DSub.Dark"> <item name="android:windowBackground">@android:color/black</item> @@ -33,17 +59,29 @@ <style name="Theme.DSub.Holo" parent="@style/Theme.AppCompat"> <item name="actionBarStyle">@style/Widget.DSub.ActionBarStyle.Holo</item> <item name="android:actionBarStyle">@style/Widget.DSub.ActionBarStyle.Holo</item> - <item name="android:textColorSecondary">@color/cyan</item> <item name="android:windowBackground">@drawable/background</item> - <item name="offline_icon">@drawable/main_offline</item> - <item name="media_button_backward">@drawable/media_backward</item> - <item name="media_button_forward">@drawable/media_forward</item> - <item name="media_button_pause">@drawable/media_pause</item> + <item name="offline_icon">@drawable/main_offline_dark</item> + <item name="media_button_backward">@drawable/media_backward_dark</item> + <item name="media_button_forward">@drawable/media_forward_dark</item> + <item name="media_button_pause">@drawable/media_pause_dark</item> <item name="media_button_repeat_off">@drawable/media_repeat_off</item> - <item name="media_button_start">@drawable/media_start</item> - <item name="media_button_stop">@drawable/media_stop</item> - <item name="chat">@drawable/ic_menu_chat_dark</item> + <item name="media_button_start">@drawable/media_start_dark</item> + <item name="media_button_stop">@drawable/media_stop_dark</item> <item name="chat_send">@drawable/ic_menu_chat_send_dark</item> + <item name="download_none">@drawable/download_none_dark</item> + <item name="shuffle">@drawable/ic_menu_shuffle_dark</item> + <item name="refresh">@drawable/ic_menu_refresh_dark</item> + <item name="search">@drawable/ic_menu_search_dark</item> + <item name="remove">@drawable/ic_menu_remove_dark</item> + <item name="save">@drawable/ic_menu_save_dark</item> + <item name="volume">@drawable/ic_action_volume_dark</item> + <item name="toggle_list">@drawable/action_toggle_list_dark</item> + <item name="select_server">@drawable/main_select_server_dark</item> + <item name="downloading">@drawable/downloading_dark</item> + <item name="bookmark">@drawable/ic_menu_bookmark_dark</item> + <item name="drawerItemsIcons">@array/drawerItemIconsDark</item> + <item name="android:textViewStyle">@style/DSub.TextViewStyle</item> + <item name="android:buttonStyle">@style/DSub.ButtonStyle</item> </style> <style name="Theme.DSub.Light.Fullscreen" parent="Theme.DSub.Light"> @@ -79,4 +117,10 @@ <item name="backgroundStacked">@android:color/transparent</item> <item name="android:backgroundStacked">@android:color/transparent</item> </style> + + <style name="DSub.TextViewStyle" parent="android:Widget.TextView"> + </style> + + <style name="DSub.ButtonStyle" parent="android:Widget.Holo.Button"> + </style> </resources> diff --git a/res/xml/settings.xml b/res/xml/settings.xml index feb7a81e..6f7527ab 100644 --- a/res/xml/settings.xml +++ b/res/xml/settings.xml @@ -1,232 +1,279 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - android:title="@string/settings.title"> + android:title="@string/settings.title"> - <PreferenceCategory + <PreferenceScreen + android:title="@string/settings.servers_title"> + + <PreferenceCategory android:key="server" - android:title="@string/settings.servers_title"> - - <Preference - android:key="serverAdd" - android:title="@string/settings.servers_add"/> - - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.appearance_title"> - - <ListPreference - android:title="@string/settings.theme_title" - android:key="theme" - android:defaultValue="holo" - android:entryValues="@array/themeValues" - android:entries="@array/themeNames"/> - - <CheckBoxPreference - android:title="@string/settings.track_title" - android:summary="@string/settings.track_summary" - android:key="displayTrack" - android:defaultValue="false"/> - - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.video_title"> - - <ListPreference - android:title="@string/settings.video_player" - android:key="videoPlayer" - android:defaultValue="raw" - android:entryValues="@array/videoPlayerValues" - android:entries="@array/videoPlayerNames"/> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.network_title"> - - <ListPreference - android:title="@string/settings.max_bitrate_wifi" - android:key="maxBitrateWifi" - android:defaultValue="0" - android:entryValues="@array/maxBitrateValues" - android:entries="@array/maxBitrateNames"/> - - <ListPreference - android:title="@string/settings.max_bitrate_mobile" - android:key="maxBitrateMobile" - android:defaultValue="0" - android:entryValues="@array/maxBitrateValues" - android:entries="@array/maxBitrateNames"/> - - <ListPreference - android:title="@string/settings.max_video_bitrate_wifi" - android:key="maxVideoBitrateWifi" - android:defaultValue="0" - android:entryValues="@array/maxVideoBitrateValues" - android:entries="@array/maxVideoBitrateNames"/> - - <ListPreference - android:title="@string/settings.max_video_bitrate_mobile" - android:key="maxVideoBitrateMobile" - android:defaultValue="0" - android:entryValues="@array/maxVideoBitrateValues" - android:entries="@array/maxVideoBitrateNames"/> - - <CheckBoxPreference - android:title="@string/settings.wifi_required_title" - android:summary="@string/settings.wifi_required_summary" - android:key="wifiRequiredForDownload" - android:defaultValue="false"/> - - <ListPreference - android:title="@string/settings.network_timeout_title" - android:key="networkTimeout" - android:defaultValue="15000" - android:entryValues="@array/networkTimeoutValues" - android:entries="@array/networkTimeoutNames"/> - - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.playlist_title"> + android:title="@string/settings.servers_title"> + + <Preference + android:key="serverAdd" + android:order="1000000" + android:title="@string/settings.servers_add"/> + </PreferenceCategory> + + </PreferenceScreen> + + <PreferenceScreen + android:title="@string/settings.appearance_title"> + + <PreferenceCategory + android:title="@string/settings.appearance_title"> + + <ListPreference + android:title="@string/settings.theme_title" + android:key="theme" + android:defaultValue="holo" + android:entryValues="@array/themeValues" + android:entries="@array/themeNames"/> + + <CheckBoxPreference + android:title="@string/settings.track_title" + android:summary="@string/settings.track_summary" + android:key="displayTrack" + android:defaultValue="false"/> + + <CheckBoxPreference + android:title="@string/settings.hide_widget_title" + android:summary="@string/settings.hide_widget_summary" + android:key="hideWidget" + android:defaultValue="false"/> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/button_bar.chat"> + + <CheckBoxPreference + android:title="@string/settings.chat_enabled" + android:summary="@string/settings.chat_enabled_summary" + android:key="chatEnabled" + android:defaultValue="true"/> <EditTextPreference - android:title="@string/settings.buffer_length" - android:key="bufferLength" - android:defaultValue="5" - android:digits="0123456789"/> - - <EditTextPreference - android:title="@string/settings.playlist_random_size_title" - android:key="randomSize" - android:defaultValue="20" + android:title="@string/settings.chat_refresh" + android:key="chatRefreshRate" + android:defaultValue="30" android:digits="0123456789"/> - + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.other_title"> + + <CheckBoxPreference + android:title="@string/settings.podcasts_enabled" + android:summary="@string/settings.podcasts_enabled_summary" + android:key="podcastsEnabled" + android:defaultValue="true"/> + + <CheckBoxPreference + android:title="@string/settings.bookmarks_enabled" + android:summary="@string/settings.bookmarks_enabled_summary" + android:key="bookmarksEnabled" + android:defaultValue="true"/> + </PreferenceCategory> + </PreferenceScreen> + + <PreferenceScreen + android:title="@string/settings.cache_screen_title"> + + <PreferenceCategory + android:title="@string/settings.network_title"> + + <ListPreference + android:title="@string/settings.max_bitrate_wifi" + android:key="maxBitrateWifi" + android:defaultValue="0" + android:entryValues="@array/maxBitrateValues" + android:entries="@array/maxBitrateNames"/> + + <ListPreference + android:title="@string/settings.max_bitrate_mobile" + android:key="maxBitrateMobile" + android:defaultValue="0" + android:entryValues="@array/maxBitrateValues" + android:entries="@array/maxBitrateNames"/> + + <ListPreference + android:title="@string/settings.max_video_bitrate_wifi" + android:key="maxVideoBitrateWifi" + android:defaultValue="0" + android:entryValues="@array/maxVideoBitrateValues" + android:entries="@array/maxVideoBitrateNames"/> + <ListPreference - android:title="@string/settings.temp_loss_title" - android:key="tempLoss" - android:defaultValue="1" - android:entryValues="@array/tempLossValues" - android:entries="@array/tempLossNames"/> + android:title="@string/settings.max_video_bitrate_mobile" + android:key="maxVideoBitrateMobile" + android:defaultValue="0" + android:entryValues="@array/maxVideoBitrateValues" + android:entries="@array/maxVideoBitrateNames"/> <CheckBoxPreference - android:title="@string/settings.persistent_title" - android:summary="@string/settings.persistent_summary" - android:key="persistentNotification" - android:defaultValue="false"/> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.cache_title"> - - <EditTextPreference - android:title="@string/settings.cache_size" - android:key="cacheSize" - android:defaultValue="2000" + android:title="@string/settings.wifi_required_title" + android:summary="@string/settings.wifi_required_summary" + android:key="wifiRequiredForDownload" + android:defaultValue="false"/> + + <ListPreference + android:title="@string/settings.network_timeout_title" + android:key="networkTimeout" + android:defaultValue="15000" + android:entryValues="@array/networkTimeoutValues" + android:entries="@array/networkTimeoutNames"/> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.cache_title"> + + <EditTextPreference + android:title="@string/settings.cache_size" + android:key="cacheSize" + android:defaultValue="2000" android:digits="0123456789"/> - <EditTextPreference - android:title="@string/settings.cache_location" - android:key="cacheLocation"/> - - <ListPreference - android:title="@string/settings.preload_wifi" - android:key="preloadCountWifi" - android:defaultValue="3" - android:entryValues="@array/preloadCountValues" - android:entries="@array/preloadCountNames"/> - - <ListPreference - android:title="@string/settings.preload_mobile" - android:key="preloadCountMobile" - android:defaultValue="3" - android:entryValues="@array/preloadCountValues" - android:entries="@array/preloadCountNames"/> - - <Preference + <EditTextPreference + android:title="@string/settings.cache_location" + android:key="cacheLocation"/> + + <ListPreference + android:title="@string/settings.preload_wifi" + android:key="preloadCountWifi" + android:defaultValue="3" + android:entryValues="@array/preloadCountValues" + android:entries="@array/preloadCountNames"/> + + <ListPreference + android:title="@string/settings.preload_mobile" + android:key="preloadCountMobile" + android:defaultValue="3" + android:entryValues="@array/preloadCountValues" + android:entries="@array/preloadCountNames"/> + + <Preference android:key="clearCache" android:title="@string/settings.cache_clear" android:persistent="false"/> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.sync_title"> - - <CheckBoxPreference - android:title="@string/settings.sync_enabled" - android:summary="@string/settings.sync_enabled_summary" - android:key="syncEnabled" - android:defaultValue="true"/> - - <ListPreference - android:title="@string/settings.sync_interval" - android:key="syncInterval" - android:defaultValue="60" - android:entryValues="@array/syncIntervalValues" - android:entries="@array/syncIntervalNames"/> - - <CheckBoxPreference - android:title="@string/settings.sync_wifi" - android:summary="@string/settings.sync_wifi_summary" - android:key="syncWifi" - android:defaultValue="true"/> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/button_bar.chat"> - - <CheckBoxPreference - android:title="@string/settings.chat_enabled" - android:summary="@string/settings.chat_enabled_summary" - android:key="chatEnabled" - android:defaultValue="true"/> - - <EditTextPreference - android:title="@string/settings.chat_refresh" - android:key="chatRefreshRate" - android:defaultValue="30" - android:digits="0123456789"/> - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/settings.other_title"> - - <CheckBoxPreference - android:title="@string/settings.scrobble_title" - android:summary="@string/settings.scrobble_summary" - android:key="scrobble" - android:defaultValue="false"/> - - <CheckBoxPreference - android:title="@string/settings.hide_media_title" - android:summary="@string/settings.hide_media_summary" - android:key="hideMedia" - android:defaultValue="false"/> - - <CheckBoxPreference - android:title="@string/settings.media_button_title" - android:summary="@string/settings.media_button_summary" - android:key="mediaButtons" - android:defaultValue="true"/> - - <CheckBoxPreference - android:title="@string/settings.screen_lit_title" - android:summary="@string/settings.screen_lit_summary" - android:key="screenLitOnDownload" - android:defaultValue="true"/> - - <CheckBoxPreference - android:title="@string/settings.gapless_playback" - android:summary="@string/settings.gapless_playback_summary" - android:key="gaplessPlayback" - android:defaultValue="true"/> - - <Preference - android:key="clearSearchHistory" - android:title="@string/settings.clear_search_history" - android:persistent="false"/> - - </PreferenceCategory> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.sync_title"> + + <CheckBoxPreference + android:title="@string/settings.sync_enabled" + android:summary="@string/settings.sync_enabled_summary" + android:key="syncEnabled" + android:defaultValue="true"/> + + <ListPreference + android:title="@string/settings.sync_interval" + android:key="syncInterval" + android:defaultValue="60" + android:entryValues="@array/syncIntervalValues" + android:entries="@array/syncIntervalNames"/> + <CheckBoxPreference + android:title="@string/settings.sync_wifi" + android:summary="@string/settings.sync_wifi_summary" + android:key="syncWifi" + android:defaultValue="true"/> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.other_title"> + + <CheckBoxPreference + android:title="@string/settings.hide_media_title" + android:summary="@string/settings.hide_media_summary" + android:key="hideMedia" + android:defaultValue="false"/> + + <CheckBoxPreference + android:title="@string/settings.screen_lit_title" + android:summary="@string/settings.screen_lit_summary" + android:key="screenLitOnDownload" + android:defaultValue="true"/> + + <Preference + android:key="clearSearchHistory" + android:title="@string/settings.clear_search_history" + android:persistent="false"/> + </PreferenceCategory> + </PreferenceScreen> + + <PreferenceScreen + android:title="@string/settings.playback_title"> + + <PreferenceCategory + android:title="@string/settings.playback_title"> + + <EditTextPreference + android:title="@string/settings.buffer_length" + android:key="bufferLength" + android:defaultValue="5" + android:digits="0123456789"/> + + <EditTextPreference + android:title="@string/settings.playlist_random_size_title" + android:key="randomSize" + android:defaultValue="20" + android:digits="0123456789"/> + + <ListPreference + android:title="@string/settings.temp_loss_title" + android:key="tempLoss" + android:defaultValue="1" + android:entryValues="@array/tempLossValues" + android:entries="@array/tempLossNames"/> + + <ListPreference + android:title="@string/settings.disconnect_pause_title" + android:key="pauseOnDisconnect" + android:defaultValue="0" + android:entryValues="@array/disconnectPauseValues" + android:entries="@array/disconnectPauseNames"/> + + <CheckBoxPreference + android:title="@string/settings.persistent_title" + android:summary="@string/settings.persistent_summary" + android:key="persistentNotification" + android:defaultValue="false"/> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.video_title"> + + <ListPreference + android:title="@string/settings.video_player" + android:key="videoPlayer" + android:defaultValue="raw" + android:entryValues="@array/videoPlayerValues" + android:entries="@array/videoPlayerNames"/> + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/settings.other_title"> + + <CheckBoxPreference + android:title="@string/settings.scrobble_title" + android:summary="@string/settings.scrobble_summary" + android:key="scrobble" + android:defaultValue="false"/> + + <CheckBoxPreference + android:title="@string/settings.media_button_title" + android:summary="@string/settings.media_button_summary" + android:key="mediaButtons" + android:defaultValue="true"/> + + <CheckBoxPreference + android:title="@string/settings.gapless_playback" + android:summary="@string/settings.gapless_playback_summary" + android:key="gaplessPlayback" + android:defaultValue="true"/> + </PreferenceCategory> + </PreferenceScreen> </PreferenceScreen> diff --git a/src/github/daneren2005/dsub/activity/DownloadActivity.java b/src/github/daneren2005/dsub/activity/DownloadActivity.java index 447bbb34..e302d59e 100644 --- a/src/github/daneren2005/dsub/activity/DownloadActivity.java +++ b/src/github/daneren2005/dsub/activity/DownloadActivity.java @@ -23,25 +23,11 @@ import android.os.Bundle; import android.view.MenuItem; import android.view.MotionEvent; import github.daneren2005.dsub.fragments.DownloadFragment; -import android.app.Dialog; -import android.view.LayoutInflater; + import android.widget.EditText; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; -import android.util.Log; -import android.view.View; -import github.daneren2005.dsub.domain.MusicDirectory; -import github.daneren2005.dsub.service.DownloadFile; -import github.daneren2005.dsub.service.MusicService; -import github.daneren2005.dsub.service.MusicServiceFactory; -import github.daneren2005.dsub.util.SilentBackgroundTask; -import github.daneren2005.dsub.util.Util; -import java.util.LinkedList; -import java.util.List; + +import github.daneren2005.dsub.util.Constants; public class DownloadActivity extends SubsonicActivity { private static final String TAG = DownloadActivity.class.getSimpleName(); @@ -57,25 +43,14 @@ public class DownloadActivity extends SubsonicActivity { if (findViewById(R.id.download_container) != null && savedInstanceState == null) { currentFragment = new DownloadFragment(); + if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { + Bundle args = new Bundle(); + args.putBoolean(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true); + currentFragment.setArguments(args); + } currentFragment.setPrimaryFragment(true); getSupportFragmentManager().beginTransaction().add(R.id.download_container, currentFragment, currentFragment.getSupportTag() + "").commit(); } - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if(item.getItemId() == android.R.id.home) { - Intent i = new Intent(); - i.setClass(this, MainActivity.class); - i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(i); - return true; - } else { - return super.onOptionsItemSelected(item); - } } @Override @@ -86,11 +61,4 @@ public class DownloadActivity extends SubsonicActivity { return false; } } - - @Override - public void onBackPressed() { - if(onBackPressedSupport()) { - super.onBackPressed(); - } - } } diff --git a/src/github/daneren2005/dsub/activity/EqualizerActivity.java b/src/github/daneren2005/dsub/activity/EqualizerActivity.java deleted file mode 100644 index d9605fc5..00000000 --- a/src/github/daneren2005/dsub/activity/EqualizerActivity.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2011 (C) Sindre Mehus - */ -package github.daneren2005.dsub.activity; - -import java.util.HashMap; -import java.util.Map; - -import android.app.Activity; -import android.content.SharedPreferences; -import android.media.audiofx.Equalizer; -import android.os.Bundle; -import android.util.Log; -import android.view.ContextMenu; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.LinearLayout; -import android.widget.SeekBar; -import android.widget.TextView; -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.audiofx.EqualizerController; -import github.daneren2005.dsub.service.DownloadServiceImpl; -import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.Util; - -/** - * Equalizer controls. - * - * @author Sindre Mehus - * @version $Id$ - */ -public class EqualizerActivity extends Activity { - private static final String TAG = EqualizerActivity.class.getSimpleName(); - - private static final int MENU_GROUP_PRESET = 100; - - private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>(); - private EqualizerController equalizerController; - private Equalizer equalizer; - private short masterLevel = 0; - - @Override - public void onCreate(Bundle bundle) { - super.onCreate(bundle); - setContentView(R.layout.equalizer); - equalizerController = DownloadServiceImpl.getInstance().getEqualizerController(); - equalizer = equalizerController.getEqualizer(); - - initEqualizer(); - - final View presetButton = findViewById(R.id.equalizer_preset); - registerForContextMenu(presetButton); - presetButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - presetButton.showContextMenu(); - } - }); - - CheckBox enabledCheckBox = (CheckBox) findViewById(R.id.equalizer_enabled); - enabledCheckBox.setChecked(equalizer.getEnabled()); - enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - setEqualizerEnabled(b); - } - }); - } - - @Override - protected void onPause() { - super.onPause(); - equalizerController.saveSettings(); - - if(!equalizer.getEnabled()) { - equalizerController.release(); - } - } - - @Override - protected void onResume() { - super.onResume(); - equalizerController = DownloadServiceImpl.getInstance().getEqualizerController(); - equalizer = equalizerController.getEqualizer(); - } - - @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu, view, menuInfo); - - short currentPreset; - try { - currentPreset = equalizer.getCurrentPreset(); - } catch (Exception x) { - currentPreset = -1; - } - - for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++) { - MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset)); - if (preset == currentPreset) { - menuItem.setChecked(true); - } - } - menu.setGroupCheckable(MENU_GROUP_PRESET, true, true); - } - - @Override - public boolean onContextItemSelected(MenuItem menuItem) { - short preset = (short) menuItem.getItemId(); - equalizer.usePreset(preset); - updateBars(false); - return true; - } - - private void setEqualizerEnabled(boolean enabled) { - SharedPreferences prefs = Util.getPreferences(EqualizerActivity.this); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled); - editor.commit(); - equalizer.setEnabled(enabled); - updateBars(true); - } - - private void updateBars(boolean changedEnabled) { - boolean isEnabled = equalizer.getEnabled(); - short minEQLevel = equalizer.getBandLevelRange()[0]; - short maxEQLevel = equalizer.getBandLevelRange()[1]; - for (Map.Entry<Short, SeekBar> entry : bars.entrySet()) { - short band = entry.getKey(); - SeekBar bar = entry.getValue(); - bar.setEnabled(isEnabled); - if(band >= (short)0) { - short setLevel; - if(changedEnabled) { - setLevel = (short)(equalizer.getBandLevel(band) - masterLevel); - bar.setProgress(equalizer.getBandLevel(band) - minEQLevel); - } else { - bar.setProgress(equalizer.getBandLevel(band) - minEQLevel); - setLevel = (short)(equalizer.getBandLevel(band) + masterLevel); - } - if(setLevel < minEQLevel) { - setLevel = minEQLevel; - } else if(setLevel > maxEQLevel) { - setLevel = maxEQLevel; - } - equalizer.setBandLevel(band, setLevel); - } else if(!isEnabled) { - bar.setProgress(-minEQLevel); - } - } - - if(!isEnabled) { - masterLevel = 0; - SharedPreferences prefs = Util.getPreferences(EqualizerActivity.this); - SharedPreferences.Editor editor = prefs.edit(); - editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel); - editor.commit(); - } - } - - private void initEqualizer() { - LinearLayout layout = (LinearLayout) findViewById(R.id.equalizer_layout); - - final short minEQLevel = equalizer.getBandLevelRange()[0]; - final short maxEQLevel = equalizer.getBandLevelRange()[1]; - - // Setup Pregain - SharedPreferences prefs = Util.getPreferences(this); - masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0); - initPregain(layout, minEQLevel, maxEQLevel); - - for (short i = 0; i < equalizer.getNumberOfBands(); i++) { - final short band = i; - - View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null); - TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); - - freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz"); - - bars.put(band, bar); - bar.setMax(maxEQLevel - minEQLevel); - short level = equalizer.getBandLevel(band); - if(equalizer.getEnabled()) { - level = (short) (level - masterLevel); - } - bar.setProgress(level - minEQLevel); - bar.setEnabled(equalizer.getEnabled()); - updateLevelText(levelTextView, level); - - bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - short level = (short) (progress + minEQLevel); - if (fromUser) { - equalizer.setBandLevel(band, (short)(level + masterLevel)); - } - updateLevelText(levelTextView, level); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); - layout.addView(bandBar); - } - } - - private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) { - View bandBar = LayoutInflater.from(this).inflate(R.layout.equalizer_bar, null); - TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); - - freqTextView.setText("Master"); - - bars.put((short)-1, bar); - bar.setMax(maxEQLevel - minEQLevel); - bar.setProgress(masterLevel - minEQLevel); - bar.setEnabled(equalizer.getEnabled()); - updateLevelText(levelTextView, masterLevel); - - bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - masterLevel = (short) (progress + minEQLevel); - if (fromUser) { - SharedPreferences prefs = Util.getPreferences(EqualizerActivity.this); - SharedPreferences.Editor editor = prefs.edit(); - editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel); - editor.commit(); - for (short i = 0; i < equalizer.getNumberOfBands(); i++) { - short level = (short) ((bars.get(i).getProgress() + minEQLevel) + masterLevel); - equalizer.setBandLevel(i, level); - } - } - updateLevelText(levelTextView, masterLevel); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); - layout.addView(bandBar); - } - - private void updateLevelText(TextView levelTextView, short level) { - levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB"); - } - -} diff --git a/src/github/daneren2005/dsub/activity/HelpActivity.java b/src/github/daneren2005/dsub/activity/HelpActivity.java deleted file mode 100644 index 6dc516bf..00000000 --- a/src/github/daneren2005/dsub/activity/HelpActivity.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2009 (C) Sindre Mehus - */ - -package github.daneren2005.dsub.activity; - -import android.app.Activity; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.Window; -import android.webkit.WebView; -import android.webkit.WebViewClient; -import android.widget.Button; -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.util.Util; - -/** - * An HTML-based help screen with Back and Done buttons at the bottom. - * - * @author Sindre Mehus - */ -public final class HelpActivity extends Activity { - - private WebView webView; - private Button backButton; - - @Override - protected void onCreate(Bundle bundle) { - super.onCreate(bundle); - getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS); - - setContentView(R.layout.help); - - webView = (WebView) findViewById(R.id.help_contents); - webView.getSettings().setJavaScriptEnabled(true); - webView.setWebViewClient(new HelpClient()); - if (bundle != null) { - webView.restoreState(bundle); - } else { - webView.loadUrl(getResources().getString(R.string.help_url)); - } - - backButton = (Button) findViewById(R.id.help_back); - backButton.setOnClickListener(new Button.OnClickListener() { - @Override - public void onClick(View view) { - webView.goBack(); - } - }); - - Button doneButton = (Button) findViewById(R.id.help_close); - doneButton.setOnClickListener(new Button.OnClickListener() { - @Override - public void onClick(View view) { - finish(); - } - }); - } - - @Override - public void onResume() { - super.onResume(); - } - - @Override - protected void onSaveInstanceState(Bundle state) { - webView.saveState(state); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - if (webView.canGoBack()) { - webView.goBack(); - return true; - } - } - return super.onKeyDown(keyCode, event); - } - - private final class HelpClient extends WebViewClient { - @Override - public void onLoadResource(WebView webView, String url) { - setProgressBarIndeterminateVisibility(true); - setTitle(getResources().getString(R.string.help_loading)); - super.onLoadResource(webView, url); - } - - @Override - public void onPageFinished(WebView view, String url) { - setProgressBarIndeterminateVisibility(false); - setTitle(view.getTitle()); - backButton.setEnabled(view.canGoBack()); - } - - @Override - public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { - Util.toast(HelpActivity.this, description); - } - } -} diff --git a/src/github/daneren2005/dsub/activity/QueryReceiverActivity.java b/src/github/daneren2005/dsub/activity/QueryReceiverActivity.java index 15d0c6a6..7a19fcb5 100644 --- a/src/github/daneren2005/dsub/activity/QueryReceiverActivity.java +++ b/src/github/daneren2005/dsub/activity/QueryReceiverActivity.java @@ -24,12 +24,14 @@ import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.provider.SearchRecentSuggestions; + +import github.daneren2005.dsub.fragments.SubsonicFragment; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.provider.DSubSearchProvider; /** - * Receives search queries and forwards to the SelectAlbumActivity. + * Receives search queries and forwards to the SearchFragment. * * @author Sindre Mehus */ @@ -46,8 +48,9 @@ public class QueryReceiverActivity extends Activity { DSubSearchProvider.MODE); suggestions.saveRecentQuery(query, null); - Intent intent = new Intent(QueryReceiverActivity.this, SearchActivity.class); + Intent intent = new Intent(QueryReceiverActivity.this, SubsonicFragmentActivity.class); intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent); } finish(); diff --git a/src/github/daneren2005/dsub/activity/SearchActivity.java b/src/github/daneren2005/dsub/activity/SearchActivity.java deleted file mode 100644 index 1dfe4790..00000000 --- a/src/github/daneren2005/dsub/activity/SearchActivity.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see <http://www.gnu.org/licenses/>. - - Copyright 2009 (C) Sindre Mehus - */ - -package github.daneren2005.dsub.activity; - -import github.daneren2005.dsub.R; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.MenuItem; - -import github.daneren2005.dsub.fragments.SearchFragment; -import github.daneren2005.dsub.util.Constants; - -public class SearchActivity extends SubsonicActivity { - private static final String TAG = SearchActivity.class.getSimpleName(); - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.download_activity); - - if (findViewById(R.id.download_container) != null && savedInstanceState == null) { - currentFragment = new SearchFragment(); - currentFragment.setPrimaryFragment(true); - getSupportFragmentManager().beginTransaction().add(R.id.download_container, currentFragment, currentFragment.getSupportTag() + "").commit(); - } - - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setHomeButtonEnabled(true); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - - if(currentFragment != null && currentFragment instanceof SearchFragment) { - String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY); - boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); - boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false); - - if (query != null) { - ((SearchFragment)currentFragment).search(query, autoplay); - } else { - ((SearchFragment)currentFragment).populateList(); - if (requestsearch) { - onSearchRequested(); - } - } - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if(item.getItemId() == android.R.id.home) { - Intent i = new Intent(); - i.setClass(this, MainActivity.class); - i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(i); - return true; - } else { - return super.onOptionsItemSelected(item); - } - } - - public void onSupportNewIntent(Intent intent) { - onNewIntent(intent); - } - - @Override - public void onBackPressed() { - if(onBackPressedSupport()) { - super.onBackPressed(); - } - } -}
\ No newline at end of file diff --git a/src/github/daneren2005/dsub/activity/SettingsActivity.java b/src/github/daneren2005/dsub/activity/SettingsActivity.java index 902c55d8..6bf3dde4 100644 --- a/src/github/daneren2005/dsub/activity/SettingsActivity.java +++ b/src/github/daneren2005/dsub/activity/SettingsActivity.java @@ -18,6 +18,7 @@ */ package github.daneren2005.dsub.activity; +import android.annotation.TargetApi; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; @@ -25,6 +26,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.preference.EditTextPreference; import android.preference.ListPreference; @@ -35,6 +37,8 @@ import android.preference.PreferenceScreen; import android.provider.SearchRecentSuggestions; import android.text.InputType; import android.util.Log; +import android.view.MenuItem; + import github.daneren2005.dsub.R; import github.daneren2005.dsub.provider.DSubSearchProvider; import github.daneren2005.dsub.service.DownloadService; @@ -70,6 +74,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer private ListPreference preloadCountMobile; private EditTextPreference randomSize; private ListPreference tempLoss; + private ListPreference pauseDisconnect; private EditTextPreference bufferLength; private Preference addServerPreference; private PreferenceCategory serversCategory; @@ -80,6 +85,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer private int serverCount = 3; private SharedPreferences settings; + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) @Override public void onCreate(Bundle savedInstanceState) { applyTheme(); @@ -98,9 +104,10 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer preloadCountMobile = (ListPreference) findPreference(Constants.PREFERENCES_KEY_PRELOAD_COUNT_MOBILE); randomSize = (EditTextPreference) findPreference(Constants.PREFERENCES_KEY_RANDOM_SIZE); tempLoss = (ListPreference) findPreference(Constants.PREFERENCES_KEY_TEMP_LOSS); + pauseDisconnect = (ListPreference) findPreference(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT); bufferLength = (EditTextPreference) findPreference(Constants.PREFERENCES_KEY_BUFFER_LENGTH); - addServerPreference = (Preference) findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); serversCategory = (PreferenceCategory) findPreference(Constants.PREFERENCES_KEY_SERVER_KEY); + addServerPreference = (Preference) findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); chatRefreshRate = (EditTextPreference) findPreference(Constants.PREFERENCES_KEY_CHAT_REFRESH); videoPlayer = (ListPreference) findPreference(Constants.PREFERENCES_KEY_VIDEO_PLAYER); syncInterval = (ListPreference) findPreference(Constants.PREFERENCES_KEY_SYNC_INTERVAL); @@ -145,22 +152,20 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer return false; } }); - + addServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { + @Override + public boolean onPreferenceClick(Preference preference) { serverCount++; - String instance = String.valueOf(serverCount); + String instance = String.valueOf(serverCount); + + Preference addServerPreference = findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); + serversCategory.addPreference(addServer(serverCount)); - Preference addServerPreference = findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); - serversCategory.removePreference(addServerPreference); - serversCategory.addPreference(addServer(serverCount)); - serversCategory.addPreference(addServerPreference); - SharedPreferences.Editor editor = settings.edit(); editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount); editor.commit(); - + serverSettings.put(instance, new ServerSettings(instance)); return true; @@ -192,18 +197,22 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer } }); - serversCategory.removePreference(addServerPreference); + serversCategory.setOrderingAsAdded(false); for (int i = 1; i <= serverCount; i++) { String instance = String.valueOf(i); serversCategory.addPreference(addServer(i)); serverSettings.put(instance, new ServerSettings(instance)); } - serversCategory.addPreference(addServerPreference); SharedPreferences prefs = Util.getPreferences(this); prefs.registerOnSharedPreferenceChangeListener(this); update(); + + if(Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + getActionBar().setDisplayHomeAsUpEnabled(true); + getActionBar().setHomeButtonEnabled(true); + } } @Override @@ -214,6 +223,16 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer prefs.unregisterOnSharedPreferenceChangeListener(this); } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + + return false; + } + @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Log.d(TAG, "Preference changed: " + key); @@ -269,6 +288,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer preloadCountMobile.setSummary(preloadCountMobile.getEntry()); randomSize.setSummary(randomSize.getText()); tempLoss.setSummary(tempLoss.getEntry()); + pauseDisconnect.setSummary(pauseDisconnect.getEntry()); bufferLength.setSummary(bufferLength.getText() + " seconds"); chatRefreshRate.setSummary(chatRefreshRate.getText()); videoPlayer.setSummary(videoPlayer.getEntry()); @@ -385,6 +405,8 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer screen.addPreference(serverTestConnectionPreference); screen.addPreference(serverOpenBrowser); + screen.setOrder(instance); + return screen; } diff --git a/src/github/daneren2005/dsub/activity/SubsonicActivity.java b/src/github/daneren2005/dsub/activity/SubsonicActivity.java index 5bb75657..83baeb6a 100644 --- a/src/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/src/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -1,53 +1,97 @@ +/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
package github.daneren2005.dsub.activity;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
+import android.content.res.TypedArray;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
+import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
+import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
+import android.widget.ListView;
import android.widget.Spinner;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.fragments.SearchFragment;
import github.daneren2005.dsub.fragments.SubsonicFragment;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.service.DownloadServiceImpl;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ImageLoader;
import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.view.DrawerAdapter;
+
import java.io.File;
import java.io.PrintWriter;
+import java.util.AbstractList;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
public class SubsonicActivity extends ActionBarActivity implements OnItemSelectedListener {
private static final String TAG = SubsonicActivity.class.getSimpleName();
private static ImageLoader IMAGE_LOADER;
protected static String theme;
+ private String[] drawerItemsDescriptions;
+ private String[] drawerItems;
+ private boolean drawerIdle = true;
+ private boolean[] enabledItems = {true, true, true};
private boolean destroyed = false;
- protected TabPagerAdapter pagerAdapter;
- protected ViewPager viewPager;
+ private boolean finished = false;
protected List<SubsonicFragment> backStack = new ArrayList<SubsonicFragment>();
protected SubsonicFragment currentFragment;
+ protected View primaryContainer;
+ protected View secondaryContainer;
Spinner actionBarSpinner;
ArrayAdapter<CharSequence> spinnerAdapter;
+ ViewGroup rootView;
+ DrawerLayout drawer;
+ ActionBarDrawerToggle drawerToggle;
+ ListView drawerList;
+ View lastSelectedView = null;
+ int lastSelectedPosition = 0;
+ boolean drawerOpen = false;
@Override
protected void onCreate(Bundle bundle) {
@@ -65,6 +109,15 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte actionBarSpinner.setAdapter(spinnerAdapter);
getSupportActionBar().setCustomView(actionbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ drawerToggle.syncState();
}
@Override
@@ -76,6 +129,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte if (theme != null && !theme.equals(Util.getTheme(this))) {
restart();
}
+
+ populateDrawer();
}
@Override
@@ -90,50 +145,157 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte super.finish();
Util.disablePendingTransition(this);
}
+
+ @Override
+ public void setContentView(int viewId) {
+ super.setContentView(R.layout.abstract_activity);
+ rootView = (ViewGroup) findViewById(R.id.content_frame);
+ LayoutInflater layoutInflater = getLayoutInflater();
+ layoutInflater.inflate(viewId, rootView);
+
+
+ drawerList = (ListView) findViewById(R.id.left_drawer);
+
+ drawerList.setOnItemClickListener(new ListView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if("Settings".equals(drawerItemsDescriptions[position])) {
+ startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class));
+ drawer.closeDrawers();
+ } else {
+ startFragmentActivity(drawerItemsDescriptions[position]);
+
+ if(lastSelectedView != view) {
+ lastSelectedView.setBackgroundResource(android.R.color.transparent);
+ view.setBackgroundResource(R.color.dividerColor);
+ lastSelectedView = view;
+ lastSelectedPosition = position;
+ }
+ }
+ }
+ });
+
+ drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+ drawerToggle = new ActionBarDrawerToggle(this, drawer, R.drawable.ic_drawer, R.string.common_appname, R.string.common_appname) {
+ @Override
+ public void onDrawerClosed(View view) {
+ setTitle(currentFragment.getTitle());
+
+ drawerIdle = true;
+ drawerOpen = false;
+
+ supportInvalidateOptionsMenu();
+ }
+
+ @Override
+ public void onDrawerOpened(View view) {
+ if(lastSelectedView == null) {
+ lastSelectedView = drawerList.getChildAt(lastSelectedPosition);
+ lastSelectedView.setBackgroundResource(R.color.dividerColor);
+ }
+
+ getSupportActionBar().setTitle(R.string.common_appname);
+ getSupportActionBar().setDisplayShowCustomEnabled(false);
+
+ drawerIdle = true;
+ drawerOpen = true;
+
+ supportInvalidateOptionsMenu();
+ }
+
+ @Override
+ public void onDrawerSlide(View drawerView, float slideOffset) {
+ super.onDrawerSlide(drawerView, slideOffset);
+ drawerIdle = false;
+ }
+ };
+ drawer.setDrawerListener(drawerToggle);
+ drawerToggle.setDrawerIndicatorEnabled(false);
+
+ drawer.setOnTouchListener(new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent event) {
+ if (drawerIdle && currentFragment != null && currentFragment.getGestureDetector() != null) {
+ return currentFragment.getGestureDetector().onTouchEvent(event);
+ } else {
+ return false;
+ }
+ }
+ });
+
+ // Check whether this is a tablet or not
+ secondaryContainer = findViewById(R.id.fragment_second_container);
+ if(secondaryContainer != null) {
+ primaryContainer = findViewById(R.id.fragment_container);
+ }
+ }
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
- if(viewPager == null) {
- String[] ids = new String[backStack.size() + 1];
- ids[0] = currentFragment.getTag();
- int i = 1;
- for(SubsonicFragment frag: backStack) {
- ids[i] = frag.getTag();
- i++;
- }
- savedInstanceState.putStringArray(Constants.MAIN_BACK_STACK, ids);
- savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE, backStack.size() + 1);
- } else {
- pagerAdapter.onSaveInstanceState(savedInstanceState);
- }
+ String[] ids = new String[backStack.size() + 1];
+ ids[0] = currentFragment.getTag();
+ int i = 1;
+ for(SubsonicFragment frag: backStack) {
+ ids[i] = frag.getTag();
+ i++;
+ }
+ savedInstanceState.putStringArray(Constants.MAIN_BACK_STACK, ids);
+ savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE, backStack.size() + 1);
+ savedInstanceState.putInt(Constants.FRAGMENT_POSITION, lastSelectedPosition);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
- if(viewPager == null) {
- super.onRestoreInstanceState(savedInstanceState);
- int size = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE);
- String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK);
- FragmentManager fm = getSupportFragmentManager();
- currentFragment = (SubsonicFragment)fm.findFragmentByTag(ids[0]);
- currentFragment.setPrimaryFragment(true);
- supportInvalidateOptionsMenu();
- for(int i = 1; i < size; i++) {
- SubsonicFragment frag = (SubsonicFragment)fm.findFragmentByTag(ids[i]);
- backStack.add(frag);
+ super.onRestoreInstanceState(savedInstanceState);
+ int size = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE);
+ String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK);
+ FragmentManager fm = getSupportFragmentManager();
+ currentFragment = (SubsonicFragment)fm.findFragmentByTag(ids[0]);
+ currentFragment.setPrimaryFragment(true);
+ currentFragment.setSupportTag(ids[0]);
+ supportInvalidateOptionsMenu();
+ for(int i = 1; i < size; i++) {
+ SubsonicFragment frag = (SubsonicFragment)fm.findFragmentByTag(ids[i]);
+ frag.setSupportTag(ids[i]);
+ if(secondaryContainer != null) {
+ frag.setPrimaryFragment(false, true);
}
- recreateSpinner();
- } else {
- pagerAdapter.onRestoreInstanceState(savedInstanceState);
- super.onRestoreInstanceState(savedInstanceState);
+ backStack.add(frag);
+ }
+
+ // Current fragment is hidden in secondaryContainer
+ if(secondaryContainer == null && findViewById(currentFragment.getRootId()) == null) {
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.remove(currentFragment);
+ trans.commit();
+ getSupportFragmentManager().executePendingTransactions();
+
+ trans = getSupportFragmentManager().beginTransaction();
+ trans.add(backStack.get(backStack.size() - 1).getRootId(), currentFragment, ids[0]);
+ trans.commit();
+ }
+ // Current fragment needs to be moved over to secondaryContainer
+ else if(secondaryContainer != null && secondaryContainer.findViewById(currentFragment.getRootId()) == null && backStack.size() > 0) {
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.remove(currentFragment);
+ trans.commit();
+ getSupportFragmentManager().executePendingTransactions();
+
+ trans = getSupportFragmentManager().beginTransaction();
+ trans.add(R.id.fragment_second_container, currentFragment, ids[0]);
+ trans.commit();
+
+ secondaryContainer.setVisibility(View.VISIBLE);
}
+
+ lastSelectedPosition = savedInstanceState.getInt(Constants.FRAGMENT_POSITION);
+ recreateSpinner();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
- if(pagerAdapter != null) {
- pagerAdapter.onCreateOptionsMenu(menu, menuInflater);
+ if(drawerOpen == true) {
+ menuInflater.inflate(R.menu.drawer_menu, menu);
} else if(currentFragment != null) {
currentFragment.onCreateOptionsMenu(menu, menuInflater);
}
@@ -141,12 +303,14 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte }
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if(pagerAdapter != null) {
- return pagerAdapter.onOptionsItemSelected(item);
- } else if(currentFragment != null) {
- return currentFragment.onOptionsItemSelected(item);
+ if(drawerToggle.onOptionsItemSelected(item)) {
+ return true;
+ } else if(item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
}
- return true;
+
+ return currentFragment.onOptionsItemSelected(item);
}
@Override
@@ -165,12 +329,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte @Override
public void setTitle(CharSequence title) {
- super.setTitle(title);
- if(pagerAdapter != null) {
- pagerAdapter.recreateSpinner();
- } else {
- recreateSpinner();
- }
+ getSupportActionBar().setTitle(title);
+ recreateSpinner();
}
public void setSubtitle(CharSequence title) {
getSupportActionBar().setSubtitle(title);
@@ -181,11 +341,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte int top = spinnerAdapter.getCount() - 1;
if(position < top) {
for(int i = top; i > position; i--) {
- if(pagerAdapter != null) {
- pagerAdapter.removeCurrent();
- } else {
- removeCurrent();
- }
+ removeCurrent();
}
}
}
@@ -194,40 +350,189 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte public void onNothingSelected(AdapterView<?> parent) {
}
-
- public boolean onBackPressedSupport() {
- if(pagerAdapter != null) {
- return pagerAdapter.onBackPressed();
- } else {
- if(backStack.size() > 0) {
- removeCurrent();
- return false;
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ if(currentFragment != null && currentFragment instanceof SearchFragment) {
+ String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
+ boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
+ boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
+
+ if (query != null) {
+ ((SearchFragment)currentFragment).search(query, autoplay);
} else {
- return true;
+ ((SearchFragment)currentFragment).populateList();
+ if (requestsearch) {
+ onSearchRequested();
+ }
}
+ } else if(intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
+ setIntent(intent);
+
+ SearchFragment fragment = new SearchFragment();
+ replaceFragment(fragment, currentFragment.getRootId(), fragment.getSupportTag());
}
}
+ private void populateDrawer() {
+ SharedPreferences prefs = Util.getPreferences(this);
+ boolean podcastsEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_PODCASTS_ENABLED, true);
+ boolean bookmarksEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_BOOKMARKS_ENABLED, true) && !Util.isOffline(this);
+ boolean chatEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_CHAT_ENABLED, true) && !Util.isOffline(this);
+
+ if(drawerItems == null || !enabledItems[0] == podcastsEnabled || !enabledItems[1] == bookmarksEnabled || !enabledItems[2] == chatEnabled) {
+ drawerItems = getResources().getStringArray(R.array.drawerItems);
+ drawerItemsDescriptions = getResources().getStringArray(R.array.drawerItemsDescriptions);
+
+ // Remove listings that user wants hidden
+ int alreadyRemoved = 0;
+ List<String> drawerItemsList = new ArrayList<String>(Arrays.asList(drawerItems));
+ List<String> drawerItemsDescriptionsList = new ArrayList<String>(Arrays.asList(drawerItemsDescriptions));
+ List<Integer> drawerItemsIconsList = new ArrayList<Integer>();
+
+ int[] arrayAttr = {R.attr.drawerItemsIcons};
+ TypedArray arrayType = obtainStyledAttributes(arrayAttr);
+ int arrayId = arrayType.getResourceId(0, 0);
+ TypedArray iconType = getResources().obtainTypedArray(arrayId);
+ for(int i = 0; i < drawerItemsList.size(); i++) {
+ drawerItemsIconsList.add(iconType.getResourceId(i, 0));
+ }
+ iconType.recycle();
+ arrayType.recycle();
+
+ // Selectively remove podcast listing [3]
+ if(!podcastsEnabled) {
+ drawerItemsList.remove(3 - alreadyRemoved);
+ drawerItemsDescriptionsList.remove(3 - alreadyRemoved);
+ drawerItemsIconsList.remove(3 - alreadyRemoved);
+ alreadyRemoved++;
+ }
+
+ // Selectively remove bookmarks listing [4]
+ if(!bookmarksEnabled) {
+ drawerItemsList.remove(4 - alreadyRemoved);
+ drawerItemsDescriptionsList.remove(4 - alreadyRemoved);
+ drawerItemsIconsList.remove(4 - alreadyRemoved);
+ alreadyRemoved++;
+ }
+
+ // Selectively remove chat listing: [5]
+ if(!chatEnabled) {
+ drawerItemsList.remove(5 - alreadyRemoved);
+ drawerItemsDescriptionsList.remove(5 - alreadyRemoved);
+ drawerItemsIconsList.remove(5 - alreadyRemoved);
+ alreadyRemoved++;
+ }
+
+ // Put list back together
+ if(alreadyRemoved > 0) {
+ drawerItems = drawerItemsList.toArray(new String[0]);
+ drawerItemsDescriptions = drawerItemsDescriptionsList.toArray(new String[0]);
+ }
+
+ drawerList.setAdapter(new DrawerAdapter(this, drawerItemsList, drawerItemsIconsList));
+ enabledItems[0] = podcastsEnabled;
+ enabledItems[1] = bookmarksEnabled;
+ enabledItems[2] = chatEnabled;
+ }
+ }
+
+ public void startFragmentActivity(String fragmentType) {
+ Intent intent = new Intent();
+ intent.setClass(SubsonicActivity.this, SubsonicFragmentActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ if(!"".equals(fragmentType)) {
+ intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
+ }
+ startActivity(intent);
+ finish();
+ }
+
+ protected void exit() {
+ if(this.getClass() != SubsonicFragmentActivity.class) {
+ Intent intent = new Intent(this, SubsonicFragmentActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
+ Util.startActivityWithoutTransition(this, intent);
+ } else {
+ finished = true;
+ this.stopService(new Intent(this, DownloadServiceImpl.class));
+ this.finish();
+ }
+ }
+
+ public boolean onBackPressedSupport() {
+ if(backStack.size() > 0) {
+ removeCurrent();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if(onBackPressedSupport()) {
+ super.onBackPressed();
+ }
+ }
+
public void replaceFragment(SubsonicFragment fragment, int id, int tag) {
- if(pagerAdapter != null) {
- pagerAdapter.replaceCurrent(fragment, id, tag);
+ replaceFragment(fragment, id, tag, false);
+ }
+ public void replaceFragment(SubsonicFragment fragment, int id, int tag, boolean replaceCurrent) {
+ if(currentFragment != null) {
+ currentFragment.setPrimaryFragment(false, secondaryContainer != null);
+ }
+ backStack.add(currentFragment);
+
+ currentFragment = fragment;
+ currentFragment.setPrimaryFragment(true);
+ supportInvalidateOptionsMenu();
+
+ if(secondaryContainer == null) {
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.add(id, fragment, tag + "");
+ trans.commit();
} else {
- if(currentFragment != null) {
- currentFragment.setPrimaryFragment(false);
+ // Make sure secondary container is visible now
+ secondaryContainer.setVisibility(View.VISIBLE);
+
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+
+ // Check to see if you need to put on top of old left or not
+ if(backStack.size() > 1) {
+ // Move old right to left if there is a backstack already
+ SubsonicFragment newLeftFragment = backStack.get(backStack.size() - 1);
+ trans.remove(newLeftFragment);
+
+ // Only move right to left if replaceCurrent is false
+ if(!replaceCurrent) {
+ SubsonicFragment oldLeftFragment = backStack.get(backStack.size() - 2);
+ int leftId = oldLeftFragment.getRootId();
+
+ // Make sure remove is finished before adding
+ trans.commit();
+ getSupportFragmentManager().executePendingTransactions();
+
+ trans = getSupportFragmentManager().beginTransaction();
+ trans.add(leftId, newLeftFragment, newLeftFragment.getSupportTag() + "");
+ } else {
+ backStack.remove(backStack.size() - 1);
+ }
}
- backStack.add(currentFragment);
- currentFragment = fragment;
- currentFragment.setPrimaryFragment(true);
- supportInvalidateOptionsMenu();
+ // Add fragment to the right container
+ trans.add(R.id.fragment_second_container, fragment, tag + "");
- FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
- trans.add(id, fragment, tag + "");
+ // Commit it all
trans.commit();
- recreateSpinner();
}
+ recreateSpinner();
}
- private void removeCurrent() {
+ public void removeCurrent() {
if(currentFragment != null) {
currentFragment.setPrimaryFragment(false);
}
@@ -237,13 +542,48 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte currentFragment.setPrimaryFragment(true);
supportInvalidateOptionsMenu();
- FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
- trans.remove(oldFrag);
- trans.commit();
+ if(secondaryContainer == null) {
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.remove(oldFrag);
+ trans.commit();
+ } else {
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+
+ // Remove old right fragment
+ trans.remove(oldFrag);
+
+ // Only switch places if there is a backstack, otherwise primary container is correct
+ if(backStack.size() > 0) {
+ // Add current left fragment to right side
+ trans.remove(currentFragment);
+
+ // Make sure remove is finished before adding
+ trans.commit();
+ getSupportFragmentManager().executePendingTransactions();
+
+ trans = getSupportFragmentManager().beginTransaction();
+ trans.add(R.id.fragment_second_container, currentFragment, currentFragment.getSupportTag() + "");
+ } else {
+ secondaryContainer.setVisibility(View.GONE);
+ }
+
+ trans.commit();
+ }
recreateSpinner();
}
+
+ public void invalidate() {
+ if(currentFragment != null) {
+ while(backStack.size() > 0) {
+ removeCurrent();
+ }
+
+ currentFragment.invalidate();
+ populateDrawer();
+ }
+ }
- private void recreateSpinner() {
+ protected void recreateSpinner() {
if(backStack.size() > 0) {
spinnerAdapter.clear();
for(int i = 0; i < backStack.size(); i++) {
@@ -257,13 +597,6 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte getSupportActionBar().setDisplayShowCustomEnabled(false);
}
}
-
- protected void addTab(int titleRes, Class fragmentClass, Bundle args) {
- pagerAdapter.addTab(getString(titleRes), fragmentClass, args);
- }
- protected void addTab(CharSequence title, Class fragmentClass, Bundle args) {
- pagerAdapter.addTab(title, fragmentClass, args);
- }
protected void restart() {
Intent intent = new Intent(this, this.getClass());
@@ -313,6 +646,10 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte }
public DownloadService getDownloadService() {
+ if(finished) {
+ return null;
+ }
+
// If service is not available, request it to start and wait for it.
for (int i = 0; i < 5; i++) {
DownloadService downloadService = DownloadServiceImpl.getInstance();
@@ -326,13 +663,6 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte return DownloadServiceImpl.getInstance();
}
- public ViewPager getViewPager() {
- return viewPager;
- }
- public TabPagerAdapter getPagerAdapter() {
- return pagerAdapter;
- }
-
public static String getThemeName() {
return theme;
}
@@ -383,258 +713,4 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte }
}
}
-
- public class TabPagerAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
- private ActionBarActivity activity;
- private ViewPager pager;
- private ActionBar actionBar;
- private SubsonicFragment currentFragment;
- private List<TabInfo> tabs = new ArrayList<TabInfo>();
- private List<List<SubsonicFragment>> frags = new ArrayList<List<SubsonicFragment>>();
- private List<QueuedFragment> queue = new ArrayList<QueuedFragment>();
- private int currentPosition;
-
- public TabPagerAdapter(ActionBarActivity activity, ViewPager pager) {
- super(activity.getSupportFragmentManager());
- this.activity = activity;
- this.actionBar = activity.getSupportActionBar();
- this.pager = pager;
- this.currentPosition = 0;
- }
-
- @Override
- public Fragment getItem(int i) {
- final TabInfo tabInfo = tabs.get(i);
- SubsonicFragment frag = (SubsonicFragment) Fragment.instantiate(activity, tabInfo.fragmentClass.getName(), tabInfo.args);
- List<SubsonicFragment> fragStack = new ArrayList<SubsonicFragment>();
- fragStack.add(frag);
- while(i > frags.size()) {
- frags.add(null);
- }
- if(i == frags.size()) {
- frags.add(i, fragStack);
- } else {
- frags.set(i, fragStack);
- }
- if(currentFragment == null || currentPosition == i) {
- currentFragment = frag;
- currentFragment.setPrimaryFragment(true);
- }
- return frag;
- }
-
- @Override
- public int getCount() {
- return tabs.size();
- }
-
- public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- if(currentFragment != null) {
- currentFragment.onCreateOptionsMenu(menu, menuInflater);
-
- for(QueuedFragment addFragment: queue) {
- replaceFragment(addFragment.fragment, addFragment.id, currentFragment.getSupportTag());
- currentFragment = addFragment.fragment;
- }
- currentFragment.setPrimaryFragment(true);
- queue.clear();
- }
- }
- public boolean onOptionsItemSelected(MenuItem item) {
- if(currentFragment != null) {
- return currentFragment.onOptionsItemSelected(item);
- } else {
- return false;
- }
- }
-
- public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
- TabInfo tabInfo = (TabInfo) tab.getTag();
- for (int i = 0; i < tabs.size(); i++) {
- if ( tabs.get(i) == tabInfo ) {
- pager.setCurrentItem(i);
- break;
- }
- }
- }
-
- public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {}
-
- public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {}
-
- public void onPageScrollStateChanged(int arg0) {}
-
- public void onPageScrolled(int arg0, float arg1, int arg2) {}
-
- public void onPageSelected(int position) {
- currentPosition = position;
- actionBar.setSelectedNavigationItem(position);
- if(currentFragment != null) {
- currentFragment.setPrimaryFragment(false);
- }
- if(position <= frags.size()) {
- List<SubsonicFragment> fragStack = frags.get(position);
- currentFragment = fragStack.get(fragStack.size() - 1);
- if(currentFragment != null) {
- currentFragment.setPrimaryFragment(true);
- }
- activity.supportInvalidateOptionsMenu();
- recreateSpinner();
- }
- }
-
- public void addTab(CharSequence title, Class fragmentClass, Bundle args) {
- final TabInfo tabInfo = new TabInfo(fragmentClass, args);
-
- ActionBar.Tab tab = actionBar.newTab();
- tab.setText(title);
- tab.setTabListener(this);
- tab.setTag(tabInfo);
-
- tabs.add(tabInfo);
-
- actionBar.addTab(tab);
- notifyDataSetChanged();
- }
- public void queueFragment(SubsonicFragment fragment, int id) {
- QueuedFragment frag = new QueuedFragment();
- frag.fragment = fragment;
- frag.id = id;
- queue.add(frag);
- }
- public void replaceCurrent(SubsonicFragment fragment, int id, int tag) {
- if(currentFragment != null) {
- currentFragment.setPrimaryFragment(false);
- }
- List<SubsonicFragment> fragStack = frags.get(currentPosition);
- fragStack.add(fragment);
-
- currentFragment = fragment;
- currentFragment.setPrimaryFragment(true);
- activity.supportInvalidateOptionsMenu();
-
- FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
- trans.add(id, fragment, tag + "");
- trans.commit();
- recreateSpinner();
- }
-
- public void removeCurrent() {
- if(currentFragment != null) {
- currentFragment.setPrimaryFragment(false);
- }
- List<SubsonicFragment> fragStack = frags.get(currentPosition);
- Fragment oldFrag = (Fragment)fragStack.remove(fragStack.size() - 1);
-
- currentFragment = fragStack.get(fragStack.size() - 1);
- currentFragment.setPrimaryFragment(true);
- activity.supportInvalidateOptionsMenu();
-
- FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
- trans.remove(oldFrag);
- trans.commit();
- }
-
- public boolean onBackPressed() {
- List<SubsonicFragment> fragStack = frags.get(currentPosition);
- if(fragStack.size() > 1) {
- removeCurrent();
- recreateSpinner();
- return false;
- } else {
- if(currentPosition == 0) {
- return true;
- } else {
- viewPager.setCurrentItem(0);
- return false;
- }
- }
- }
-
- private void recreateSpinner() {
- if(frags.isEmpty()) {
- return;
- }
-
- List<SubsonicFragment> fragStack = frags.get(currentPosition);
- if(fragStack.size() > 1) {
- spinnerAdapter.clear();
- for(int i = 0; i < fragStack.size(); i++) {
- SubsonicFragment frag = fragStack.get(i);
- spinnerAdapter.add(frag.getTitle());
- }
- spinnerAdapter.notifyDataSetChanged();
- actionBarSpinner.setSelection(spinnerAdapter.getCount() - 1);
- actionBar.setDisplayShowCustomEnabled(true);
- } else {
- actionBar.setDisplayShowCustomEnabled(false);
- }
- }
-
- public void invalidate() {
- FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
- for (int i = 0; i < frags.size(); i++) {
- List<SubsonicFragment> fragStack = frags.get(i);
-
- for(int j = fragStack.size() - 1; j > 0; j--) {
- SubsonicFragment oldFrag = fragStack.remove(j);
- trans.remove((Fragment)oldFrag);
- }
-
- SubsonicFragment frag = (SubsonicFragment)fragStack.get(0);
- frag.invalidate();
- }
- trans.commit();
- }
-
- public void onSaveInstanceState(Bundle savedInstanceState) {
- for(int i = 0; i < frags.size(); i++) {
- List<SubsonicFragment> fragStack = frags.get(i);
- String[] ids = new String[fragStack.size()];
-
- for(int j = 0; j < fragStack.size(); j++) {
- ids[j] = fragStack.get(j).getTag();
- }
- savedInstanceState.putStringArray(Constants.MAIN_BACK_STACK + i, ids);
- savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE + i, fragStack.size());
- }
- savedInstanceState.putInt(Constants.MAIN_BACK_STACK_TABS, frags.size());
- savedInstanceState.putInt(Constants.MAIN_BACK_STACK_POSITION, currentPosition);
- }
-
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- int tabCount = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_TABS);
- FragmentManager fm = activity.getSupportFragmentManager();
- for(int i = 0; i < tabCount; i++) {
- int stackSize = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE + i);
- String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK + i);
- List<SubsonicFragment> fragStack = new ArrayList<SubsonicFragment>();
-
- for(int j = 0; j < stackSize; j++) {
- SubsonicFragment frag = (SubsonicFragment)fm.findFragmentByTag(ids[j]);
- fragStack.add(frag);
- }
-
- frags.add(i, fragStack);
- }
- currentPosition = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_POSITION);
- List<SubsonicFragment> fragStack = frags.get(currentPosition);
- currentFragment = fragStack.get(fragStack.size() - 1);
- currentFragment.setPrimaryFragment(true);
- activity.supportInvalidateOptionsMenu();
- }
-
- private class TabInfo {
- public final Class fragmentClass;
- public final Bundle args;
- public TabInfo(Class fragmentClass, Bundle args) {
- this.fragmentClass = fragmentClass;
- this.args = args;
- }
- }
- private class QueuedFragment {
- public SubsonicFragment fragment;
- public int id;
- }
- }
}
diff --git a/src/github/daneren2005/dsub/activity/MainActivity.java b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java index da46df71..29d192e7 100644 --- a/src/github/daneren2005/dsub/activity/MainActivity.java +++ b/src/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java @@ -1,339 +1,436 @@ -package github.daneren2005.dsub.activity; - -import android.accounts.Account; -import android.accounts.AccountManager; -import android.app.AlertDialog; -import android.content.ContentResolver; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.preference.PreferenceManager; -import android.support.v4.view.ViewPager; -import android.support.v7.app.ActionBar; -import android.util.Log; -import android.view.View; -import android.widget.ImageButton; -import android.widget.TextView; -import github.daneren2005.dsub.R; -import github.daneren2005.dsub.domain.MusicDirectory; -import github.daneren2005.dsub.domain.PlayerState; -import github.daneren2005.dsub.fragments.ChatFragment; -import github.daneren2005.dsub.fragments.MainFragment; -import github.daneren2005.dsub.fragments.SelectArtistFragment; -import github.daneren2005.dsub.fragments.SelectDirectoryFragment; -import github.daneren2005.dsub.fragments.SelectPlaylistFragment; -import github.daneren2005.dsub.fragments.SelectPodcastsFragment; -import github.daneren2005.dsub.fragments.SubsonicFragment; -import github.daneren2005.dsub.service.DownloadFile; -import github.daneren2005.dsub.service.DownloadServiceImpl; -import github.daneren2005.dsub.updates.Updater; -import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.FileUtil; -import github.daneren2005.dsub.util.SilentBackgroundTask; -import github.daneren2005.dsub.util.Util; -import github.daneren2005.dsub.view.ChangeLog; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -public class MainActivity extends SubsonicActivity { - private static final String TAG = MainActivity.class.getSimpleName(); - private static boolean infoDialogDisplayed; - private ScheduledExecutorService executorService; - private View bottomBar; - private View coverArtView; - private TextView trackView; - private TextView artistView; - private ImageButton startButton; - private long lastBackPressTime = 0; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) { - stopService(new Intent(this, DownloadServiceImpl.class)); - finish(); - } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) { - getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD); - Intent intent = new Intent(); - intent.setClass(this, DownloadActivity.class); - startActivity(intent); - } - setContentView(R.layout.main); - loadSettings(); - createAccount(); - - bottomBar = findViewById(R.id.bottom_bar); - bottomBar.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(); - intent.setClass(v.getContext(), DownloadActivity.class); - startActivity(intent); - } - }); - coverArtView = bottomBar.findViewById(R.id.album_art); - trackView = (TextView) bottomBar.findViewById(R.id.track_name); - artistView = (TextView) bottomBar.findViewById(R.id.artist_name); - - ImageButton previousButton = (ImageButton) findViewById(R.id.download_previous); - previousButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - new SilentBackgroundTask<Void>(MainActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if(getDownloadService() == null) { - return null; - } - - getDownloadService().previous(); - return null; - } - - @Override - protected void done(Void result) { - update(); - } - }.execute(); - } - }); - - startButton = (ImageButton) findViewById(R.id.download_start); - startButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - new SilentBackgroundTask<Void>(MainActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - PlayerState state = getDownloadService().getPlayerState(); - if(state == PlayerState.STARTED) { - getDownloadService().pause(); - } else { - getDownloadService().start(); - } - - return null; - } - - @Override - protected void done(Void result) { - update(); - } - }.execute(); - } - }); - - ImageButton nextButton = (ImageButton) findViewById(R.id.download_next); - nextButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - new SilentBackgroundTask<Void>(MainActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if(getDownloadService() == null) { - return null; - } - - if (getDownloadService().getCurrentPlayingIndex() < getDownloadService().size() - 1) { - getDownloadService().next(); - } - return null; - } - - @Override - protected void done(Void result) { - update(); - } - }.execute(); - } - }); - - viewPager = (ViewPager) findViewById(R.id.pager); - viewPager.setOffscreenPageLimit(4); - pagerAdapter = new TabPagerAdapter(this, viewPager); - viewPager.setAdapter(pagerAdapter); - viewPager.setOnPageChangeListener(pagerAdapter); - - addTab(R.string.button_bar_home, MainFragment.class, null); - addTab(R.string.button_bar_browse, SelectArtistFragment.class, null); - addTab(R.string.button_bar_playlists, SelectPlaylistFragment.class, null); - addTab(R.string.button_bar_podcasts, SelectPodcastsFragment.class, null); - SharedPreferences prefs = Util.getPreferences(this); - if(prefs.getBoolean(Constants.PREFERENCES_KEY_CHAT_ENABLED, true)) { - addTab(R.string.button_bar_chat, ChatFragment.class, null); - } - - getSupportActionBar().setDisplayHomeAsUpEnabled(false); - getSupportActionBar().setHomeButtonEnabled(false); - getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - } - - @Override - protected void onPostCreate(Bundle bundle) { - super.onPostCreate(bundle); - - showInfoDialog(); - checkUpdates(); - - ChangeLog changeLog = new ChangeLog(this, Util.getPreferences(this)); - if(changeLog.isFirstRun()) { - changeLog.getLogDialog().show(); - } - } - - @Override - public void onResume() { - super.onResume(); - - final Handler handler = new Handler(); - Runnable runnable = new Runnable() { - @Override - public void run() { - handler.post(new Runnable() { - @Override - public void run() { - update(); - } - }); - } - }; - - if(getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) { - viewPager.setCurrentItem(1); - - int fragmentID = R.id.select_artist_layout; - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_PARENT_ID)) { - SubsonicFragment fragment = new SelectDirectoryFragment(); - Bundle args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PARENT_ID)); - args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PARENT_NAME)); - fragment.setArguments(args); - - pagerAdapter.queueFragment(fragment, R.id.select_artist_layout); - fragmentID = fragment.getRootId(); - } - - SubsonicFragment fragment = new SelectDirectoryFragment(); - Bundle args = new Bundle(); - args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID)); - args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME)); - fragment.setArguments(args); - - pagerAdapter.queueFragment(fragment, fragmentID); - getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM); - } - - executorService = Executors.newSingleThreadScheduledExecutor(); - executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS); - } - - @Override - public void onPause() { - super.onPause(); - executorService.shutdown(); - } - - @Override - public void onBackPressed() { - if(onBackPressedSupport()) { - if(lastBackPressTime < (System.currentTimeMillis() - 4000)) { - lastBackPressTime = System.currentTimeMillis(); - Util.toast(this, R.string.main_back_confirm); - } else { - finish(); - } - } - } - - private void update() { - if (getDownloadService() == null) { - return; - } - - DownloadFile current = getDownloadService().getCurrentPlaying(); - if(current == null) { - trackView.setText("Title"); - artistView.setText("Artist"); - getImageLoader().loadImage(coverArtView, null, false, false); - return; - } - - MusicDirectory.Entry song = current.getSong(); - trackView.setText(song.getTitle()); - artistView.setText(song.getArtist()); - getImageLoader().loadImage(coverArtView, song, false, false); - int[] attrs = new int[] {(getDownloadService().getPlayerState() == PlayerState.STARTED) ? R.attr.media_button_pause : R.attr.media_button_start}; - TypedArray typedArray = this.obtainStyledAttributes(attrs); - Drawable drawable = typedArray.getDrawable(0); - startButton.setImageDrawable(drawable); - typedArray.recycle(); - } - - public void checkUpdates() { - try { - String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; - int ver = Integer.parseInt(version.replace(".", "")); - Updater updater = new Updater(ver); - updater.checkUpdates(this); - } - catch(Exception e) { - - } - } - - private void loadSettings() { - PreferenceManager.setDefaultValues(this, R.xml.settings, false); - SharedPreferences prefs = Util.getPreferences(this); - if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath()); - editor.commit(); - } - - if (!prefs.contains(Constants.PREFERENCES_KEY_OFFLINE)) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(Constants.PREFERENCES_KEY_OFFLINE, false); - - editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + 1, "Demo Server"); - editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + 1, "http://demo.subsonic.org"); - editor.putString(Constants.PREFERENCES_KEY_USERNAME + 1, "android-guest"); - editor.putString(Constants.PREFERENCES_KEY_PASSWORD + 1, "guest"); - editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); - editor.commit(); - } - if(!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 3); - editor.commit(); - } - } - - private void createAccount() { - AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE); - Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE); - accountManager.addAccountExplicitly(account, null, null); - - SharedPreferences prefs = Util.getPreferences(this); - boolean syncEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SYNC_ENABLED, true); - int syncInterval = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_SYNC_INTERVAL, "60")); - - // Make sync run every hour - ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled); - ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval); - ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PODCAST_AUTHORITY, syncEnabled); - ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PODCAST_AUTHORITY, new Bundle(), 60L * syncInterval); - } - - private void showInfoDialog() { - if (!infoDialogDisplayed) { - infoDialogDisplayed = true; - Log.i(TAG, Util.getRestUrl(this, null)); - if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) { - Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text); - } - } - } -} +/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package github.daneren2005.dsub.activity;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.PlayerState;
+import github.daneren2005.dsub.fragments.ChatFragment;
+import github.daneren2005.dsub.fragments.MainFragment;
+import github.daneren2005.dsub.fragments.SearchFragment;
+import github.daneren2005.dsub.fragments.SelectArtistFragment;
+import github.daneren2005.dsub.fragments.SelectBookmarkFragment;
+import github.daneren2005.dsub.fragments.SelectDirectoryFragment;
+import github.daneren2005.dsub.fragments.SelectPlaylistFragment;
+import github.daneren2005.dsub.fragments.SelectPodcastsFragment;
+import github.daneren2005.dsub.fragments.SubsonicFragment;
+import github.daneren2005.dsub.service.DownloadFile;
+import github.daneren2005.dsub.service.DownloadServiceImpl;
+import github.daneren2005.dsub.updates.Updater;
+import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.SilentBackgroundTask;
+import github.daneren2005.dsub.util.Util;
+import github.daneren2005.dsub.view.ChangeLog;
+
+/**
+ * Created by Scott on 10/14/13.
+ */
+public class SubsonicFragmentActivity extends SubsonicActivity {
+ private static String TAG = SubsonicFragmentActivity.class.getSimpleName();
+ private static boolean infoDialogDisplayed;
+ private ScheduledExecutorService executorService;
+ private View bottomBar;
+ private View coverArtView;
+ private TextView trackView;
+ private TextView artistView;
+ private ImageButton startButton;
+ private long lastBackPressTime = 0;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
+ stopService(new Intent(this, DownloadServiceImpl.class));
+ finish();
+ } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
+ getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD);
+ Intent intent = new Intent();
+ intent.setClass(this, DownloadActivity.class);
+ if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true);
+ }
+ startActivity(intent);
+ }
+ setContentView(R.layout.abstract_fragment_activity);
+
+ if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
+ String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
+ currentFragment = getNewFragment(fragmentType);
+
+ if("".equals(fragmentType) || fragmentType == null) {
+ // Initial startup stuff
+ loadSettings();
+ createAccount();
+ }
+
+ currentFragment.setPrimaryFragment(true);
+ getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
+
+ if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
+ SearchFragment fragment = new SearchFragment();
+ replaceFragment(fragment, R.id.home_layout, fragment.getSupportTag());
+ }
+ }
+
+ bottomBar = findViewById(R.id.bottom_bar);
+ bottomBar.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent();
+ intent.setClass(v.getContext(), DownloadActivity.class);
+ startActivity(intent);
+ }
+ });
+ coverArtView = bottomBar.findViewById(R.id.album_art);
+ trackView = (TextView) bottomBar.findViewById(R.id.track_name);
+ artistView = (TextView) bottomBar.findViewById(R.id.artist_name);
+
+ ImageButton previousButton = (ImageButton) findViewById(R.id.download_previous);
+ previousButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ if(getDownloadService() == null) {
+ return null;
+ }
+
+ getDownloadService().previous();
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ update();
+ }
+ }.execute();
+ }
+ });
+
+ startButton = (ImageButton) findViewById(R.id.download_start);
+ startButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ PlayerState state = getDownloadService().getPlayerState();
+ if(state == PlayerState.STARTED) {
+ getDownloadService().pause();
+ } else {
+ getDownloadService().start();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ update();
+ }
+ }.execute();
+ }
+ });
+
+ ImageButton nextButton = (ImageButton) findViewById(R.id.download_next);
+ nextButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ if(getDownloadService() == null) {
+ return null;
+ }
+
+ if (getDownloadService().getCurrentPlayingIndex() < getDownloadService().size() - 1) {
+ getDownloadService().next();
+ }
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ update();
+ }
+ }.execute();
+ }
+ });
+ }
+
+ @Override
+ protected void onPostCreate(Bundle bundle) {
+ super.onPostCreate(bundle);
+
+ showInfoDialog();
+ checkUpdates();
+
+ ChangeLog changeLog = new ChangeLog(this, Util.getPreferences(this));
+ if(changeLog.isFirstRun()) {
+ changeLog.getLogDialog().show();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ final Handler handler = new Handler();
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ update();
+ }
+ });
+ }
+ };
+
+ if(getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) {
+ int fragmentID = R.id.fragment_list_layout;
+ if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_PARENT_ID)) {
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PARENT_ID));
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_PARENT_NAME));
+ fragment.setArguments(args);
+
+ replaceFragment(fragment, R.id.fragment_list_layout, currentFragment.getSupportTag());
+ fragmentID = fragment.getRootId();
+ }
+
+ SubsonicFragment fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME));
+ fragment.setArguments(args);
+
+ replaceFragment(fragment, fragmentID, currentFragment.getSupportTag());
+ getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM);
+ }
+
+ executorService = Executors.newSingleThreadScheduledExecutor();
+ executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ executorService.shutdown();
+ }
+
+ @Override
+ public void setContentView(int viewId) {
+ super.setContentView(viewId);
+ drawerToggle.setDrawerIndicatorEnabled(true);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if(super.onOptionsItemSelected(item)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if(onBackPressedSupport()) {
+ if(lastBackPressTime < (System.currentTimeMillis() - 4000)) {
+ lastBackPressTime = System.currentTimeMillis();
+ Util.toast(this, R.string.main_back_confirm);
+ } else {
+ finish();
+ }
+ }
+ }
+
+ @Override
+ public void replaceFragment(SubsonicFragment fragment, int id, int tag, boolean replaceCurrent) {
+ super.replaceFragment(fragment, id, tag, replaceCurrent);
+ drawerToggle.setDrawerIndicatorEnabled(false);
+ }
+ @Override
+ public void removeCurrent() {
+ super.removeCurrent();
+ if(backStack.isEmpty()) {
+ drawerToggle.setDrawerIndicatorEnabled(true);
+ }
+ }
+
+ @Override
+ public void startFragmentActivity(String fragmentType) {
+ // Create a transaction that does all of this
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+
+ // Clear existing stack
+ for(int i = backStack.size() - 1; i >= 0; i--) {
+ trans.remove(backStack.get(i));
+ }
+ trans.remove(currentFragment);
+ backStack.clear();
+
+ // Create new stack
+ currentFragment = getNewFragment(fragmentType);
+ currentFragment.setPrimaryFragment(true);
+ trans.add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "");
+
+ // Done, cleanup
+ trans.commit();
+ supportInvalidateOptionsMenu();
+ recreateSpinner();
+ drawer.closeDrawers();
+
+ if(secondaryContainer != null) {
+ secondaryContainer.setVisibility(View.GONE);
+ }
+ drawerToggle.setDrawerIndicatorEnabled(true);
+ }
+
+ private SubsonicFragment getNewFragment(String fragmentType) {
+ if("Artist".equals(fragmentType)) {
+ return new SelectArtistFragment();
+ } else if("Playlist".equals(fragmentType)) {
+ return new SelectPlaylistFragment();
+ } else if("Chat".equals(fragmentType)) {
+ return new ChatFragment();
+ } else if("Podcast".equals(fragmentType)) {
+ return new SelectPodcastsFragment();
+ } else if("Bookmark".equals(fragmentType)) {
+ return new SelectBookmarkFragment();
+ } else {
+ return new MainFragment();
+ }
+ }
+
+ private void update() {
+ if (getDownloadService() == null) {
+ return;
+ }
+
+ DownloadFile current = getDownloadService().getCurrentPlaying();
+ if(current == null) {
+ trackView.setText("Title");
+ artistView.setText("Artist");
+ getImageLoader().loadImage(coverArtView, null, false, false);
+ return;
+ }
+
+ MusicDirectory.Entry song = current.getSong();
+ trackView.setText(song.getTitle());
+ artistView.setText(song.getArtist());
+ getImageLoader().loadImage(coverArtView, song, false, false);
+ int[] attrs = new int[] {(getDownloadService().getPlayerState() == PlayerState.STARTED) ? R.attr.media_button_pause : R.attr.media_button_start};
+ TypedArray typedArray = this.obtainStyledAttributes(attrs);
+ startButton.setImageResource(typedArray.getResourceId(0, 0));
+ typedArray.recycle();
+ }
+
+ public void checkUpdates() {
+ try {
+ String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
+ int ver = Integer.parseInt(version.replace(".", ""));
+ Updater updater = new Updater(ver);
+ updater.checkUpdates(this);
+ }
+ catch(Exception e) {
+
+ }
+ }
+
+ private void loadSettings() {
+ PreferenceManager.setDefaultValues(this, R.xml.settings, false);
+ SharedPreferences prefs = Util.getPreferences(this);
+ if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
+ editor.commit();
+ }
+
+ if (!prefs.contains(Constants.PREFERENCES_KEY_OFFLINE)) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(Constants.PREFERENCES_KEY_OFFLINE, false);
+
+ editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + 1, "Demo Server");
+ editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + 1, "http://demo.subsonic.org");
+ editor.putString(Constants.PREFERENCES_KEY_USERNAME + 1, "android-guest");
+ editor.putString(Constants.PREFERENCES_KEY_PASSWORD + 1, "guest");
+ editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
+ editor.commit();
+ }
+ if(!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 3);
+ editor.commit();
+ }
+ }
+
+ private void createAccount() {
+ AccountManager accountManager = (AccountManager) this.getSystemService(ACCOUNT_SERVICE);
+ Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
+ accountManager.addAccountExplicitly(account, null, null);
+
+ SharedPreferences prefs = Util.getPreferences(this);
+ boolean syncEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SYNC_ENABLED, true);
+ int syncInterval = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_SYNC_INTERVAL, "60"));
+
+ // Make sync run every hour
+ ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled);
+ ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval);
+ ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PODCAST_AUTHORITY, syncEnabled);
+ ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PODCAST_AUTHORITY, new Bundle(), 60L * syncInterval);
+ }
+
+ private void showInfoDialog() {
+ if (!infoDialogDisplayed) {
+ infoDialogDisplayed = true;
+ Log.i(TAG, Util.getRestUrl(this, null));
+ if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) {
+ Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
+ }
+ }
+ }
+}
diff --git a/src/github/daneren2005/dsub/activity/VoiceQueryReceiverActivity.java b/src/github/daneren2005/dsub/activity/VoiceQueryReceiverActivity.java index 5cda9ee5..e37696d5 100644 --- a/src/github/daneren2005/dsub/activity/VoiceQueryReceiverActivity.java +++ b/src/github/daneren2005/dsub/activity/VoiceQueryReceiverActivity.java @@ -24,12 +24,14 @@ import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.provider.SearchRecentSuggestions; + +import github.daneren2005.dsub.fragments.SubsonicFragment; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.provider.DSubSearchProvider; /** - * Receives voice search queries and forwards to the SearchActivity. + * Receives voice search queries and forwards to the SearchFragment. * * http://android-developers.blogspot.com/2010/09/supporting-new-music-voice-action.html * @@ -48,9 +50,10 @@ public class VoiceQueryReceiverActivity extends Activity { DSubSearchProvider.MODE); suggestions.saveRecentQuery(query, null); - Intent intent = new Intent(VoiceQueryReceiverActivity.this, SearchActivity.class); + Intent intent = new Intent(VoiceQueryReceiverActivity.this, SubsonicFragmentActivity.class); intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query); intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent); } finish(); diff --git a/src/github/daneren2005/dsub/audiofx/EqualizerController.java b/src/github/daneren2005/dsub/audiofx/EqualizerController.java index 0dcee863..0e1c49b5 100644 --- a/src/github/daneren2005/dsub/audiofx/EqualizerController.java +++ b/src/github/daneren2005/dsub/audiofx/EqualizerController.java @@ -80,7 +80,7 @@ public class EqualizerController { public void loadSettings() { try { if (isAvailable()) { - EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat"); + EqualizerSettings settings = FileUtil.deserialize(context, "equalizer.dat", EqualizerSettings.class); if (settings != null) { settings.apply(equalizer); } @@ -95,7 +95,11 @@ public class EqualizerController { } public boolean isEnabled() { - return isAvailable() && equalizer.getEnabled(); + try { + return isAvailable() && equalizer.getEnabled(); + } catch(Exception e) { + return false; + } } public void release() { @@ -120,10 +124,13 @@ public class EqualizerController { private static class EqualizerSettings implements Serializable { - private final short[] bandLevels; + private short[] bandLevels; private short preset; - private final boolean enabled; + private boolean enabled; + public EqualizerSettings() { + + } public EqualizerSettings(Equalizer equalizer) { enabled = equalizer.getEnabled(); bandLevels = new short[equalizer.getNumberOfBands()]; diff --git a/src/github/daneren2005/dsub/domain/Bookmark.java b/src/github/daneren2005/dsub/domain/Bookmark.java new file mode 100644 index 00000000..d1f470ce --- /dev/null +++ b/src/github/daneren2005/dsub/domain/Bookmark.java @@ -0,0 +1,102 @@ +/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2013 (C) Scott Jackson
+ */
+package github.daneren2005.dsub.domain;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Created by Scott on 11/4/13.
+ */
+public class Bookmark implements Serializable {
+ private int position;
+ private String username;
+ private String comment;
+ private Date created;
+ private Date changed;
+ private MusicDirectory.Entry entry;
+
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(int position) {
+ this.position = position;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public Date getCreated() {
+ return created;
+ }
+
+ public void setCreated(String created) {
+ if (created != null) {
+ try {
+ this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
+ } catch (ParseException e) {
+ this.created = null;
+ }
+ } else {
+ this.created = null;
+ }
+ }
+
+ public Date getChanged() {
+ return changed;
+ }
+
+ public void setChanged(String changed) {
+ if (changed != null) {
+ try {
+ this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
+ } catch (ParseException e) {
+ this.changed = null;
+ }
+ } else {
+ this.changed = null;
+ }
+ }
+
+ public MusicDirectory.Entry getEntry() {
+ return this.entry;
+ }
+
+ public void setEntry(MusicDirectory.Entry entry) {
+ this.entry = entry;
+ }
+}
diff --git a/src/github/daneren2005/dsub/domain/Indexes.java b/src/github/daneren2005/dsub/domain/Indexes.java index 0bc44158..67eb33bc 100644 --- a/src/github/daneren2005/dsub/domain/Indexes.java +++ b/src/github/daneren2005/dsub/domain/Indexes.java @@ -18,6 +18,7 @@ */ package github.daneren2005.dsub.domain; +import java.util.ArrayList; import java.util.List; import java.io.Serializable; @@ -26,15 +27,33 @@ import java.io.Serializable; */ public class Indexes implements Serializable { - private final long lastModified; - private final List<Artist> shortcuts; - private final List<Artist> artists; + private long lastModified; + private List<Artist> shortcuts; + private List<Artist> artists; + private List<MusicDirectory.Entry> entries; + public Indexes() { + + } public Indexes(long lastModified, List<Artist> shortcuts, List<Artist> artists) { this.lastModified = lastModified; this.shortcuts = shortcuts; this.artists = artists; + this.entries = new ArrayList<MusicDirectory.Entry>(); } + public Indexes(long lastModified, List<Artist> shortcuts, List<Artist> artists, List<MusicDirectory.Entry> entries) { + this.lastModified = lastModified; + this.shortcuts = shortcuts; + this.artists = artists; + this.entries = entries; + if(!entries.isEmpty()) { + Artist root = new Artist(); + root.setId("root"); + root.setName("Root"); + root.setIndex("#"); + artists.add(root); + } + } public long getLastModified() { return lastModified; @@ -47,4 +66,8 @@ public class Indexes implements Serializable { public List<Artist> getArtists() { return artists; } + + public List<MusicDirectory.Entry> getEntries() { + return entries; + } }
\ No newline at end of file diff --git a/src/github/daneren2005/dsub/domain/MusicDirectory.java b/src/github/daneren2005/dsub/domain/MusicDirectory.java index c05d1631..0b9be5fb 100644 --- a/src/github/daneren2005/dsub/domain/MusicDirectory.java +++ b/src/github/daneren2005/dsub/domain/MusicDirectory.java @@ -18,9 +18,11 @@ */ package github.daneren2005.dsub.domain; +import android.media.MediaMetadataRetriever; import android.util.Log; import java.util.ArrayList; import java.util.List; +import java.io.File; import java.io.Serializable; import java.util.Collections; import java.util.Comparator; @@ -28,7 +30,7 @@ import java.util.Comparator; /** * @author Sindre Mehus */ -public class MusicDirectory { +public class MusicDirectory implements Serializable { private static final String TAG = MusicDirectory.class.getSimpleName(); private String name; @@ -121,6 +123,37 @@ public class MusicDirectory { private Integer discNumber; private boolean starred; private int closeness; + + public void loadMetadata(File file) { + try { + MediaMetadataRetriever metadata = new MediaMetadataRetriever(); + metadata.setDataSource(file.getAbsolutePath()); + String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER); + if(discNumber == null) { + discNumber = "1/1"; + } + int slashIndex = discNumber.indexOf("/"); + if(slashIndex > 0) { + discNumber = discNumber.substring(0, slashIndex); + } + setDiscNumber(Integer.parseInt(discNumber)); + String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); + setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000); + String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); + setDuration(Integer.parseInt(length) / 1000); + String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); + if(artist != null) { + setArtist(artist); + } + String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM); + if(album != null) { + setAlbum(album); + } + metadata.release(); + } catch(Exception e) { + Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver"); + } + } public String getId() { return id; diff --git a/src/github/daneren2005/dsub/domain/MusicFolder.java b/src/github/daneren2005/dsub/domain/MusicFolder.java index 68a22bcc..99e86e23 100644 --- a/src/github/daneren2005/dsub/domain/MusicFolder.java +++ b/src/github/daneren2005/dsub/domain/MusicFolder.java @@ -28,9 +28,12 @@ import java.io.Serializable; */ public class MusicFolder implements Serializable { - private final String id; - private final String name; + private String id; + private String name; + public MusicFolder() { + + } public MusicFolder(String id, String name) { this.id = id; this.name = name; diff --git a/src/github/daneren2005/dsub/domain/Playlist.java b/src/github/daneren2005/dsub/domain/Playlist.java index c97659c7..663fa2b0 100644 --- a/src/github/daneren2005/dsub/domain/Playlist.java +++ b/src/github/daneren2005/dsub/domain/Playlist.java @@ -33,6 +33,9 @@ public class Playlist implements Serializable { private String created; private Boolean pub; + public Playlist() { + + } public Playlist(String id, String name) { this.id = id; this.name = name; diff --git a/src/github/daneren2005/dsub/fragments/ChatFragment.java b/src/github/daneren2005/dsub/fragments/ChatFragment.java index 198b93a4..ca3a4f76 100644 --- a/src/github/daneren2005/dsub/fragments/ChatFragment.java +++ b/src/github/daneren2005/dsub/fragments/ChatFragment.java @@ -170,7 +170,7 @@ public class ChatFragment extends SubsonicFragment { @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- menuInflater.inflate(R.menu.chat, menu);
+ menuInflater.inflate(R.menu.abstract_top_menu, menu);
}
@Override
diff --git a/src/github/daneren2005/dsub/fragments/DownloadFragment.java b/src/github/daneren2005/dsub/fragments/DownloadFragment.java index f1f4b7c0..d46fbec6 100644 --- a/src/github/daneren2005/dsub/fragments/DownloadFragment.java +++ b/src/github/daneren2005/dsub/fragments/DownloadFragment.java @@ -40,12 +40,15 @@ import android.widget.SeekBar; import android.widget.TextView;
import android.widget.ViewFlipper;
import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.PlayerState;
import github.daneren2005.dsub.domain.RemoteControlState;
import github.daneren2005.dsub.domain.RepeatMode;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
+import github.daneren2005.dsub.service.MusicService;
+import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.view.FadeOutAnimation;
@@ -59,8 +62,6 @@ import github.daneren2005.dsub.view.AutoRepeatButton; import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture;
import com.mobeta.android.dslv.*;
-import github.daneren2005.dsub.activity.EqualizerActivity;
-import github.daneren2005.dsub.activity.MainActivity;
import github.daneren2005.dsub.activity.SubsonicActivity;
public class DownloadFragment extends SubsonicFragment implements OnGestureListener {
@@ -92,11 +93,11 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe private Button jukeboxButton;
private View toggleListButton;
private ImageButton starButton;
+ private ImageButton bookmarkButton;
private View mainLayout;
private ScheduledExecutorService executorService;
private DownloadFile currentPlaying;
private long currentRevision;
- private GestureDetector gestureScanner;
private int swipeDistance;
private int swipeVelocity;
private VisualizerView visualizerView;
@@ -104,6 +105,8 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe private ScheduledFuture<?> hideControlsFuture;
private SongListAdapter songListAdapter;
private SilentBackgroundTask<Void> onProgressChangedTask;
+ private SilentBackgroundTask<Void> onCurrentChangedTask;
+ private SilentBackgroundTask<Void> onDownloadListChangedTask;
private boolean seekInProgress = false;
private boolean startFlipped = false;
@@ -119,6 +122,13 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe startFlipped = true;
}
}
+ Bundle args = getArguments();
+ if(args != null) {
+ if(args.getBoolean(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
+ startFlipped = true;
+ nowPlaying = false;
+ }
+ }
}
@Override
@@ -161,6 +171,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe equalizerButton = (Button)rootView.findViewById(R.id.download_equalizer);
visualizerButton = (Button)rootView.findViewById(R.id.download_visualizer);
jukeboxButton = (Button)rootView.findViewById(R.id.download_jukebox);
+ bookmarkButton = (ImageButton) rootView.findViewById(R.id.download_bookmark);
LinearLayout visualizerViewLayout = (LinearLayout)rootView.findViewById(R.id.download_visualizer_view_layout);
toggleListButton =rootView.findViewById(R.id.download_toggle_list);
@@ -189,6 +200,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe equalizerButton.setOnTouchListener(touchListener);
visualizerButton.setOnTouchListener(touchListener);
jukeboxButton.setOnTouchListener(touchListener);
+ bookmarkButton.setOnTouchListener(touchListener);
emptyTextView.setOnTouchListener(touchListener);
albumArtImageView.setOnTouchListener(touchListener);
@@ -225,12 +237,8 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe new SilentBackgroundTask<Boolean>(context) {
@Override
protected Boolean doInBackground() throws Throwable {
- if (getDownloadService().getCurrentPlayingIndex() < getDownloadService().size() - 1) {
- getDownloadService().next();
- return true;
- } else {
- return false;
- }
+ getDownloadService().next();
+ return true;
}
@Override
@@ -337,7 +345,8 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe DownloadService downloadService = getDownloadService();
if(downloadService != null && downloadService.getEqualizerController() != null
&& downloadService.getEqualizerController().getEqualizer() != null) {
- context.startActivity(new Intent(context, EqualizerActivity.class));
+ SubsonicFragment fragment = new EqualizerFragment();
+ replaceFragment(fragment, R.id.download_layout_container);
setControlsVisible(true);
} else {
Util.toast(context, "Failed to start equalizer. Try restarting.");
@@ -373,6 +382,13 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe }
});
+ bookmarkButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ createBookmark();
+ }
+ });
+
toggleListButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -470,17 +486,12 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe visualizerViewLayout.addView(visualizerView, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
}
- // TODO: Extract to utility method and cache.
- Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Storopia.ttf");
- equalizerButton.setTypeface(typeface);
- visualizerButton.setTypeface(typeface);
- jukeboxButton.setTypeface(typeface);
-
return rootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ DownloadService downloadService = getDownloadService();
if(Util.isOffline(context)) {
menuInflater.inflate(R.menu.nowplaying_offline, menu);
} else {
@@ -491,11 +502,11 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe menuInflater.inflate(R.menu.nowplaying_downloading, menu);
}
- if(getDownloadService() != null && getDownloadService().getSleepTimer()) {
+ if(downloadService != null && downloadService.getSleepTimer()) {
menu.findItem(R.id.menu_toggle_timer).setTitle(R.string.download_stop_timer);
}
}
- if(getDownloadService() != null && getDownloadService().getKeepScreenOn()) {
+ if(downloadService != null && downloadService.getKeepScreenOn()) {
menu.findItem(R.id.menu_screen_on_off).setTitle(R.string.download_menu_screen_off);
}
}
@@ -512,6 +523,10 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe @Override
public void onCreateContextMenu(android.view.ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
+
if (view == playlistView) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
DownloadFile downloadFile = (DownloadFile) playlistView.getItemAtPosition(info.position);
@@ -546,10 +561,11 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe case R.id.menu_show_album:
MusicDirectory.Entry entry = song.getSong();
- Intent intent = new Intent(context, MainActivity.class);
+ Intent intent = new Intent(context, SubsonicFragmentActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, entry.getParent());
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getAlbum());
+ intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Artist");
if(entry.getGrandParent() != null) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_PARENT_ID, entry.getGrandParent());
@@ -604,24 +620,29 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe getDownloadService().delete(songs);
return true;
case R.id.menu_remove_all:
- new SilentBackgroundTask<Void>(context) {
+ Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() {
@Override
- protected Void doInBackground() throws Throwable {
- getDownloadService().setShufflePlayEnabled(false);
- if(nowPlaying) {
- getDownloadService().clear();
- }
- else {
- getDownloadService().clearBackground();
- }
- return null;
- }
+ public void onClick(DialogInterface dialog, int which) {
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ getDownloadService().setShufflePlayEnabled(false);
+ if(nowPlaying) {
+ getDownloadService().clear();
+ }
+ else {
+ getDownloadService().clearBackground();
+ }
+ return null;
+ }
- @Override
- protected void done(Void result) {
- onDownloadListChanged();
+ @Override
+ protected void done(Void result) {
+ onDownloadListChanged();
+ }
+ }.execute();
}
- }.execute();
+ });
return true;
case R.id.menu_screen_on_off:
if (getDownloadService().getKeepScreenOn()) {
@@ -736,6 +757,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe if(rootView != null) {
if(primary) {
mainLayout.setVisibility(View.VISIBLE);
+ updateButtons();
} else {
mainLayout.setVisibility(View.GONE);
}
@@ -776,6 +798,10 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe }
private void updateButtons() {
+ if(context == null) {
+ return;
+ }
+
SharedPreferences prefs = Util.getPreferences(context);
boolean equalizerOn = prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false);
if(equalizerOn && getDownloadService() != null && getDownloadService().getEqualizerController() != null &&
@@ -791,6 +817,12 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe boolean jukeboxEnabled = getDownloadService() != null && getDownloadService().isRemoteEnabled();
jukeboxButton.setTextColor(jukeboxEnabled ? COLOR_BUTTON_ENABLED : COLOR_BUTTON_DISABLED);
+
+ if(Util.isOffline(context)) {
+ bookmarkButton.setVisibility(View.GONE);
+ } else {
+ bookmarkButton.setVisibility(View.VISIBLE);
+ }
}
// Scroll to current playing/downloading.
@@ -896,74 +928,119 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe private void onDownloadListChanged() {
onDownloadListChanged(false);
}
- private void onDownloadListChanged(boolean refresh) {
- DownloadService downloadService = getDownloadService();
- if (downloadService == null) {
+ private void onDownloadListChanged(final boolean refresh) {
+ final DownloadService downloadService = getDownloadService();
+ if (downloadService == null || onDownloadListChangedTask != null) {
return;
}
- List<DownloadFile> list;
- if(nowPlaying) {
- list = downloadService.getSongs();
- }
- else {
- list = downloadService.getBackgroundDownloads();
- }
+ onDownloadListChangedTask = new SilentBackgroundTask<Void>(context) {
+ int currentPlayingIndex;
+ int size;
- if(downloadService.isShufflePlayEnabled()) {
- emptyTextView.setText(R.string.download_shuffle_loading);
- }
- else {
- emptyTextView.setText(R.string.download_empty);
- }
+ @Override
+ protected Void doInBackground() throws Throwable {
+ currentPlayingIndex = downloadService.getCurrentPlayingIndex() + 1;
+ size = downloadService.size();
+ return null;
+ }
- if(songListAdapter == null || refresh) {
- playlistView.setAdapter(songListAdapter = new SongListAdapter(list));
- } else {
- songListAdapter.notifyDataSetChanged();
- }
- emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
- currentRevision = downloadService.getDownloadListUpdateRevision();
+ @Override
+ protected void done(Void result) {
+ List<DownloadFile> list;
+ if(nowPlaying) {
+ list = downloadService.getSongs();
+ }
+ else {
+ list = downloadService.getBackgroundDownloads();
+ }
- switch (downloadService.getRepeatMode()) {
- case OFF:
- if("light".equals(SubsonicActivity.getThemeName()) | "light_fullscreen".equals(SubsonicActivity.getThemeName())) {
- repeatButton.setImageResource(R.drawable.media_repeat_off_light);
+ if(downloadService.isShufflePlayEnabled()) {
+ emptyTextView.setText(R.string.download_shuffle_loading);
+ }
+ else {
+ emptyTextView.setText(R.string.download_empty);
+ }
+
+ if(songListAdapter == null || refresh) {
+ playlistView.setAdapter(songListAdapter = new SongListAdapter(list));
} else {
- repeatButton.setImageResource(R.drawable.media_repeat_off);
+ songListAdapter.notifyDataSetChanged();
}
- break;
- case ALL:
- repeatButton.setImageResource(R.drawable.media_repeat_all);
- break;
- case SINGLE:
- repeatButton.setImageResource(R.drawable.media_repeat_single);
- break;
- default:
- break;
- }
-
- setSubtitle(context.getResources().getString(R.string.download_playing_out_of, downloadService.getCurrentPlayingIndex() + 1, downloadService.size()));
+ emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
+ currentRevision = downloadService.getDownloadListUpdateRevision();
+
+ switch (downloadService.getRepeatMode()) {
+ case OFF:
+ if("light".equals(SubsonicActivity.getThemeName()) | "light_fullscreen".equals(SubsonicActivity.getThemeName())) {
+ repeatButton.setImageResource(R.drawable.media_repeat_off_light);
+ } else {
+ repeatButton.setImageResource(R.drawable.media_repeat_off);
+ }
+ break;
+ case ALL:
+ repeatButton.setImageResource(R.drawable.media_repeat_all);
+ break;
+ case SINGLE:
+ repeatButton.setImageResource(R.drawable.media_repeat_single);
+ break;
+ default:
+ break;
+ }
+
+ setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex, size));
+ onDownloadListChangedTask = null;
+ if(onCurrentChangedTask != null) {
+ onCurrentChangedTask.execute();
+ } else if(onProgressChangedTask != null) {
+ onProgressChangedTask.execute();
+ }
+ }
+ };
+ onDownloadListChangedTask.execute();
}
private void onCurrentChanged() {
- DownloadService downloadService = getDownloadService();
- if (downloadService == null) {
+ final DownloadService downloadService = getDownloadService();
+ if (downloadService == null || onCurrentChangedTask != null) {
return;
}
+
+ onCurrentChangedTask = new SilentBackgroundTask<Void>(context) {
+ int currentPlayingIndex;
+ int currentPlayingSize;
- currentPlaying = downloadService.getCurrentPlaying();
- if (currentPlaying != null) {
- MusicDirectory.Entry song = currentPlaying.getSong();
- songTitleTextView.setText(song.getTitle());
- getImageLoader().loadImage(albumArtImageView, song, true, true);
- starButton.setImageResource(song.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off);
- setSubtitle(context.getResources().getString(R.string.download_playing_out_of, downloadService.getCurrentPlayingIndex() + 1, downloadService.size()));
- } else {
- songTitleTextView.setText(null);
- getImageLoader().loadImage(albumArtImageView, null, true, false);
- starButton.setImageResource(android.R.drawable.btn_star_big_off);
- setSubtitle(null);
+ @Override
+ protected Void doInBackground() throws Throwable {
+ currentPlaying = downloadService.getCurrentPlaying();
+ currentPlayingIndex = downloadService.getCurrentPlayingIndex() + 1;
+ currentPlayingSize = downloadService.size();
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ if (currentPlaying != null) {
+ MusicDirectory.Entry song = currentPlaying.getSong();
+ songTitleTextView.setText(song.getTitle());
+ getImageLoader().loadImage(albumArtImageView, song, true, true);
+ starButton.setImageResource(song.isStarred() ? android.R.drawable.btn_star_big_on : android.R.drawable.btn_star_big_off);
+ setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex, currentPlayingSize));
+ } else {
+ songTitleTextView.setText(null);
+ getImageLoader().loadImage(albumArtImageView, null, true, false);
+ starButton.setImageResource(android.R.drawable.btn_star_big_off);
+ setSubtitle(null);
+ }
+ onCurrentChangedTask = null;
+ if(onProgressChangedTask != null) {
+ onProgressChangedTask.execute();
+ }
+ }
+ };
+
+ if(onDownloadListChangedTask == null) {
+ onCurrentChangedTask.execute();
}
}
@@ -1057,7 +1134,9 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe onProgressChangedTask = null;
}
};
- onProgressChangedTask.execute();
+ if(onDownloadListChangedTask == null && onCurrentChangedTask == null) {
+ onProgressChangedTask.execute();
+ }
}
private void changeProgress(final int ms) {
@@ -1094,6 +1173,54 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe }
}.execute();
}
+
+ private void createBookmark() {
+ DownloadService downloadService = getDownloadService();
+ if(downloadService == null) {
+ return;
+ }
+
+ final DownloadFile currentDownload = downloadService.getCurrentPlaying();
+ if(currentDownload == null) {
+ return;
+ }
+
+ View dialogView = context.getLayoutInflater().inflate(R.layout.create_bookmark, null);
+ final EditText commentBox = (EditText)dialogView.findViewById(R.id.comment_text);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.download_save_bookmark_title)
+ .setView(dialogView)
+ .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ String comment = commentBox.getText().toString();
+
+ createBookmark(currentDownload, comment);
+ }
+ })
+ .setNegativeButton(R.string.common_cancel, null);
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ }
+ private void createBookmark(final DownloadFile currentDownload, final String comment) {
+ new SilentBackgroundTask<Void>(context) {
+ @Override
+ protected Void doInBackground() throws Throwable {
+ MusicDirectory.Entry currentSong = currentDownload.getSong();
+ MusicService musicService = MusicServiceFactory.getMusicService(context);
+ musicService.createBookmark(currentSong.getId(), getDownloadService().getPlayerPosition(), comment, context, null);
+
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
+ Util.toast(context, R.string.download_save_bookmark);
+ setControlsVisible(true);
+ }
+ }.execute();
+ }
private class SongListAdapter extends ArrayAdapter<DownloadFile> {
public SongListAdapter(List<DownloadFile> entries) {
@@ -1120,10 +1247,6 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe return false;
}
- public GestureDetector getGestureDetector() {
- return gestureScanner;
- }
-
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
DownloadService downloadService = getDownloadService();
diff --git a/src/github/daneren2005/dsub/fragments/EqualizerFragment.java b/src/github/daneren2005/dsub/fragments/EqualizerFragment.java new file mode 100644 index 00000000..8b2c5313 --- /dev/null +++ b/src/github/daneren2005/dsub/fragments/EqualizerFragment.java @@ -0,0 +1,286 @@ +/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2010 (C) Sindre Mehus
+ */
+package github.daneren2005.dsub.fragments;
+
+import android.content.SharedPreferences;
+import android.media.audiofx.Equalizer;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import github.daneren2005.dsub.R;
+import github.daneren2005.dsub.audiofx.EqualizerController;
+import github.daneren2005.dsub.service.DownloadServiceImpl;
+import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.Util;
+
+/**
+ * Created by Scott on 10/27/13.
+ */
+public class EqualizerFragment extends SubsonicFragment {
+ private static final String TAG = EqualizerFragment.class.getSimpleName();
+
+ private static final int MENU_GROUP_PRESET = 100;
+
+ private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
+ private EqualizerController equalizerController;
+ private Equalizer equalizer;
+ private short masterLevel = 0;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
+ rootView = inflater.inflate(R.layout.equalizer, container, false);
+
+ equalizerController = DownloadServiceImpl.getInstance().getEqualizerController();
+ equalizer = equalizerController.getEqualizer();
+
+ initEqualizer();
+
+ final View presetButton = rootView.findViewById(R.id.equalizer_preset);
+ registerForContextMenu(presetButton);
+ presetButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ presetButton.showContextMenu();
+ }
+ });
+
+ CheckBox enabledCheckBox = (CheckBox) rootView.findViewById(R.id.equalizer_enabled);
+ enabledCheckBox.setChecked(equalizer.getEnabled());
+ enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ setEqualizerEnabled(b);
+ }
+ });
+
+ setTitle(R.string.equalizer_label);
+
+ return rootView;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ equalizerController.saveSettings();
+
+ if(!equalizer.getEnabled()) {
+ equalizerController.release();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ equalizerController = DownloadServiceImpl.getInstance().getEqualizerController();
+ equalizer = equalizerController.getEqualizer();
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
+
+ short currentPreset;
+ try {
+ currentPreset = equalizer.getCurrentPreset();
+ } catch (Exception x) {
+ currentPreset = -1;
+ }
+
+ for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++) {
+ MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
+ if (preset == currentPreset) {
+ menuItem.setChecked(true);
+ }
+ }
+ menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ short preset = (short) menuItem.getItemId();
+ equalizer.usePreset(preset);
+ updateBars(false);
+ return true;
+ }
+
+ private void setEqualizerEnabled(boolean enabled) {
+ SharedPreferences prefs = Util.getPreferences(context);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled);
+ editor.commit();
+ equalizer.setEnabled(enabled);
+ updateBars(true);
+ }
+
+ private void updateBars(boolean changedEnabled) {
+ boolean isEnabled = equalizer.getEnabled();
+ short minEQLevel = equalizer.getBandLevelRange()[0];
+ short maxEQLevel = equalizer.getBandLevelRange()[1];
+ for (Map.Entry<Short, SeekBar> entry : bars.entrySet()) {
+ short band = entry.getKey();
+ SeekBar bar = entry.getValue();
+ bar.setEnabled(isEnabled);
+ if(band >= (short)0) {
+ short setLevel;
+ if(changedEnabled) {
+ setLevel = (short)(equalizer.getBandLevel(band) - masterLevel);
+ if(isEnabled) {
+ bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
+ } else {
+ bar.setProgress(-minEQLevel);
+ }
+ } else {
+ bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
+ setLevel = (short)(equalizer.getBandLevel(band) + masterLevel);
+ }
+ if(setLevel < minEQLevel) {
+ setLevel = minEQLevel;
+ } else if(setLevel > maxEQLevel) {
+ setLevel = maxEQLevel;
+ }
+ equalizer.setBandLevel(band, setLevel);
+ } else if(!isEnabled) {
+ bar.setProgress(-minEQLevel);
+ }
+ }
+
+ if(!isEnabled) {
+ masterLevel = 0;
+ SharedPreferences prefs = Util.getPreferences(context);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
+ editor.commit();
+ }
+ }
+
+ private void initEqualizer() {
+ LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.equalizer_layout);
+
+ final short minEQLevel = equalizer.getBandLevelRange()[0];
+ final short maxEQLevel = equalizer.getBandLevelRange()[1];
+
+ // Setup Pregain
+ SharedPreferences prefs = Util.getPreferences(context);
+ masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0);
+ initPregain(layout, minEQLevel, maxEQLevel);
+
+ for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
+ final short band = i;
+
+ View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
+ TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
+ final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
+ SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
+
+ freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
+
+ bars.put(band, bar);
+ bar.setMax(maxEQLevel - minEQLevel);
+ short level = equalizer.getBandLevel(band);
+ if(equalizer.getEnabled()) {
+ level = (short) (level - masterLevel);
+ }
+ bar.setProgress(level - minEQLevel);
+ bar.setEnabled(equalizer.getEnabled());
+ updateLevelText(levelTextView, level);
+
+ bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ short level = (short) (progress + minEQLevel);
+ if (fromUser) {
+ equalizer.setBandLevel(band, (short)(level + masterLevel));
+ }
+ updateLevelText(levelTextView, level);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ layout.addView(bandBar);
+ }
+ }
+
+ private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
+ View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
+ TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
+ final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
+ SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
+
+ freqTextView.setText("Master");
+
+ bars.put((short)-1, bar);
+ bar.setMax(maxEQLevel - minEQLevel);
+ bar.setProgress(masterLevel - minEQLevel);
+ bar.setEnabled(equalizer.getEnabled());
+ updateLevelText(levelTextView, masterLevel);
+
+ bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ masterLevel = (short) (progress + minEQLevel);
+ if (fromUser) {
+ SharedPreferences prefs = Util.getPreferences(context);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
+ editor.commit();
+ for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
+ short level = (short) ((bars.get(i).getProgress() + minEQLevel) + masterLevel);
+ equalizer.setBandLevel(i, level);
+ }
+ }
+ updateLevelText(levelTextView, masterLevel);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ layout.addView(bandBar);
+ }
+
+ private void updateLevelText(TextView levelTextView, short level) {
+ levelTextView.setText((level > 0 ? "+" : "") + level / 100 + " dB");
+ }
+}
diff --git a/src/github/daneren2005/dsub/fragments/MainFragment.java b/src/github/daneren2005/dsub/fragments/MainFragment.java index 05726483..0d865fe8 100644 --- a/src/github/daneren2005/dsub/fragments/MainFragment.java +++ b/src/github/daneren2005/dsub/fragments/MainFragment.java @@ -95,6 +95,9 @@ public class MainFragment extends SubsonicFragment { @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
int serverCount = Util.getServerCount(context);
int activeServer = Util.getActiveServer(context);
@@ -116,7 +119,6 @@ public class MainFragment extends SubsonicFragment { int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE;
setActiveServer(activeServer);
- context.getPagerAdapter().invalidate();
return true;
}
@@ -186,6 +188,7 @@ public class MainFragment extends SubsonicFragment { }
}
});
+ setTitle(R.string.common_appname);
}
private void setActiveServer(int instance) {
@@ -195,13 +198,14 @@ public class MainFragment extends SubsonicFragment { service.clearIncomplete();
}
Util.setActiveServer(context, instance);
+ context.invalidate();
}
}
private void toggleOffline() {
boolean isOffline = Util.isOffline(context);
Util.setOffline(context, !isOffline);
- context.getPagerAdapter().invalidate();
+ context.invalidate();
if(isOffline) {
int scrobblesCount = Util.offlineScrobblesCount(context);
diff --git a/src/github/daneren2005/dsub/fragments/SearchFragment.java b/src/github/daneren2005/dsub/fragments/SearchFragment.java index 6fa86737..900872da 100644 --- a/src/github/daneren2005/dsub/fragments/SearchFragment.java +++ b/src/github/daneren2005/dsub/fragments/SearchFragment.java @@ -18,11 +18,9 @@ import android.view.MenuItem; import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
-import android.widget.TextView;
import android.net.Uri;
import android.view.ViewGroup;
import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.activity.SearchActivity;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.SearchCritera;
@@ -53,7 +51,6 @@ public class SearchFragment extends SubsonicFragment { private View artistsHeading;
private View albumsHeading;
private View songsHeading;
- private TextView searchButton;
private View moreArtistsButton;
private View moreAlbumsButton;
private View moreSongsButton;
@@ -84,7 +81,7 @@ public class SearchFragment extends SubsonicFragment { @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.search, container, false);
+ rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
setTitle(R.string.search_title);
View buttons = inflater.inflate(R.layout.search_buttons, null);
@@ -93,19 +90,16 @@ public class SearchFragment extends SubsonicFragment { albumsHeading = buttons.findViewById(R.id.search_albums);
songsHeading = buttons.findViewById(R.id.search_songs);
- searchButton = (TextView) buttons.findViewById(R.id.search_search);
moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
moreSongsButton = buttons.findViewById(R.id.search_more_songs);
- list = (ListView) rootView.findViewById(R.id.search_list);
+ list = (ListView) rootView.findViewById(R.id.fragment_list);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (view == searchButton) {
- context.onSearchRequested();
- } else if (view == moreArtistsButton) {
+ if (view == moreArtistsButton) {
expandArtists();
} else if (view == moreAlbumsButton) {
expandAlbums();
@@ -130,7 +124,7 @@ public class SearchFragment extends SubsonicFragment { }
});
registerForContextMenu(list);
- ((SearchActivity)context).onSupportNewIntent(context.getIntent());
+ context.onNewIntent(context.getIntent());
if(searchResult != null) {
skipSearch = true;
@@ -157,6 +151,9 @@ public class SearchFragment extends SubsonicFragment { @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
Object selectedItem = list.getItemAtPosition(info.position);
@@ -186,7 +183,7 @@ public class SearchFragment extends SubsonicFragment { public void setPrimaryFragment(boolean primary) {
super.setPrimaryFragment(primary);
if(rootView != null && primary) {
- ((SearchActivity)context).onSupportNewIntent(context.getIntent());
+ context.onNewIntent(context.getIntent());
}
}
@@ -221,7 +218,6 @@ public class SearchFragment extends SubsonicFragment { public void populateList() {
mergeAdapter = new MergeAdapter();
- mergeAdapter.addView(searchButton, true);
if (searchResult != null) {
List<Artist> artists = searchResult.getArtists();
@@ -258,7 +254,6 @@ public class SearchFragment extends SubsonicFragment { }
boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
- searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
}
list.setAdapter(mergeAdapter);
@@ -301,11 +296,11 @@ public class SearchFragment extends SubsonicFragment { args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
fragment.setArguments(args);
- replaceFragment(fragment, R.id.search_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
}
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
- int id = R.id.search_layout;
+ int id = R.id.fragment_list_layout;
Bundle args;
if(album.getParent() != null) {
SubsonicFragment parentFragment = new SelectDirectoryFragment();
@@ -314,7 +309,7 @@ public class SearchFragment extends SubsonicFragment { args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getArtist());
parentFragment.setArguments(args);
- replaceFragment(parentFragment, R.id.search_layout);
+ replaceFragment(parentFragment, R.id.fragment_list_layout);
id = parentFragment.getRootId();
}
diff --git a/src/github/daneren2005/dsub/fragments/SelectArtistFragment.java b/src/github/daneren2005/dsub/fragments/SelectArtistFragment.java index b11f6fe7..ed629a15 100644 --- a/src/github/daneren2005/dsub/fragments/SelectArtistFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectArtistFragment.java @@ -17,6 +17,7 @@ import android.widget.TextView; import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.Indexes;
+import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.MusicFolder;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
@@ -40,6 +41,7 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie private View folderButton;
private TextView folderName;
private List<MusicFolder> musicFolders = null;
+ private List<MusicDirectory.Entry> entries;
private List<Artist> artists;
@Override
@@ -61,9 +63,9 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.select_artist, container, false);
+ rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
- artistList = (ListView) rootView.findViewById(R.id.select_artist_list);
+ artistList = (ListView) rootView.findViewById(R.id.fragment_list);
artistList.setOnItemClickListener(this);
folderButtonParent = inflater.inflate(R.layout.select_artist_header, artistList, false);
@@ -103,6 +105,9 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
Object entry = artistList.getItemAtPosition(info.position);
@@ -146,7 +151,7 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie : selectedFolder.getName();
Util.setSelectedMusicFolderId(context, musicFolderId);
folderName.setText(musicFolderName);
- refresh();
+ context.invalidate();
}
return true;
@@ -162,9 +167,13 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ if("root".equals(artist.getId())) {
+ Log.d(TAG, "root");
+ args.putSerializable(Constants.FRAGMENT_LIST, (Serializable) entries);
+ }
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_artist_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
}
}
@@ -174,7 +183,7 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie }
private void load(final boolean refresh) {
- setTitle(R.string.search_artists);
+ setTitle(R.string.button_bar_browse);
if (Util.isOffline(context)) {
folderButton.setVisibility(View.GONE);
@@ -199,7 +208,10 @@ public class SelectArtistFragment extends SubsonicFragment implements AdapterVie artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
artists.addAll(result.getShortcuts());
artists.addAll(result.getArtists());
+ artistList.setFastScrollEnabled(false);
artistList.setAdapter(new ArtistAdapter(context, artists));
+ artistList.setFastScrollEnabled(true);
+ entries = result.getEntries();
setMusicFolders();
artistList.setVisibility(View.VISIBLE);
diff --git a/src/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java b/src/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java new file mode 100644 index 00000000..dc892634 --- /dev/null +++ b/src/github/daneren2005/dsub/fragments/SelectBookmarkFragment.java @@ -0,0 +1,238 @@ +/* + This file is part of Subsonic. + + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2010 (C) Sindre Mehus +*/ +package github.daneren2005.dsub.fragments; + +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ListView; +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.activity.DownloadActivity; +import github.daneren2005.dsub.domain.Bookmark; +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.service.DownloadService; +import github.daneren2005.dsub.service.MusicService; +import github.daneren2005.dsub.service.MusicServiceFactory; +import github.daneren2005.dsub.service.OfflineException; +import github.daneren2005.dsub.service.ServerTooOldException; +import github.daneren2005.dsub.util.BackgroundTask; +import github.daneren2005.dsub.util.Constants; +import github.daneren2005.dsub.util.LoadingTask; +import github.daneren2005.dsub.util.TabBackgroundTask; +import github.daneren2005.dsub.util.Util; +import github.daneren2005.dsub.view.BookmarkAdapter; +import java.io.Serializable; +import java.text.Format; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +public class SelectBookmarkFragment extends SubsonicFragment implements AdapterView.OnItemClickListener { + private static final String TAG = SelectBookmarkFragment.class.getSimpleName(); + private ListView bookmarkListView; + private View emptyView; + private List<Bookmark> bookmarks; + private BookmarkAdapter bookmarkAdapter; + + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + + if(bundle != null) { + bookmarks = (List<Bookmark>) bundle.getSerializable(Constants.FRAGMENT_LIST); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) bookmarks); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { + rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false); + + bookmarkListView = (ListView)rootView.findViewById(R.id.fragment_list); + bookmarkListView.setOnItemClickListener(this); + registerForContextMenu(bookmarkListView); + emptyView = rootView.findViewById(R.id.fragment_list_empty); + + if(bookmarks == null) { + refresh(); + } else { + bookmarkListView.setAdapter(new BookmarkAdapter(context, bookmarks)); + } + + return rootView; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { + menuInflater.inflate(R.menu.abstract_top_menu, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(super.onOptionsItemSelected(item)) { + return true; + } + + return false; + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, view, menuInfo); + if(!primaryFragment) { + return; + } + + MenuInflater inflater = context.getMenuInflater(); + inflater.inflate(R.menu.select_bookmark_context, menu); + } + + @Override + public boolean onContextItemSelected(MenuItem menuItem) { + if(!primaryFragment) { + return false; + } + + AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); + Bookmark bookmark = bookmarks.get(info.position); + + switch(menuItem.getItemId()) { + case R.id.bookmark_menu_info: + displayBookmarkInfo(bookmark); + break; + case R.id.bookmark_menu_delete: + deleteBookmark(bookmark); + break; + } + + if(onContextItemSelected(menuItem, bookmark.getEntry())) { + return true; + } + + return true; + } + + @Override + protected void refresh(final boolean refresh) { + setTitle(R.string.button_bar_bookmarks); + bookmarkListView.setVisibility(View.INVISIBLE); + + BackgroundTask<List<Bookmark>> task = new TabBackgroundTask<List<Bookmark>>(this) { + @Override + protected List<Bookmark> doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + + bookmarks = new ArrayList<Bookmark>(); + + try { + bookmarks = musicService.getBookmarks(refresh, context, this); + } catch (Exception x) { + Log.e(TAG, "Failed to load bookmarks", x); + } + + return bookmarks; + } + + @Override + protected void done(List<Bookmark> result) { + emptyView.setVisibility(result == null || result.isEmpty() ? View.VISIBLE : View.GONE); + + if (result != null) { + bookmarkListView.setAdapter(bookmarkAdapter = new BookmarkAdapter(context, result)); + bookmarkListView.setVisibility(View.VISIBLE); + } + } + }; + task.execute(); + } + + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + DownloadService downloadService = getDownloadService(); + if(downloadService == null) { + return; + } + + Bookmark bookmark = (Bookmark) parent.getItemAtPosition(position); + downloadService.download(bookmark); + Util.startActivityWithoutTransition(context, DownloadActivity.class); + } + + private void displayBookmarkInfo(final Bookmark bookmark) { + Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String comment = bookmark.getComment(); + if(comment == null) { + comment = ""; + } + + String msg = context.getResources().getString(R.string.bookmark_details, + bookmark.getEntry().getTitle(), Util.formatDuration(bookmark.getPosition() / 1000), + formatter.format(bookmark.getCreated()), formatter.format(bookmark.getChanged()), comment); + + Util.info(context, R.string.bookmark_details_title, msg, false); + } + private void deleteBookmark(final Bookmark bookmark) { + final MusicDirectory.Entry entry = bookmark.getEntry(); + Util.confirmDialog(context, R.string.bookmark_delete_title, entry.getTitle(), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + new LoadingTask<Void>(context, false) { + @Override + protected Void doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + musicService.deleteBookmark(entry.getId(), context, null); + return null; + } + + @Override + protected void done(Void result) { + bookmarkAdapter.remove(bookmark); + bookmarkAdapter.notifyDataSetChanged(); + Util.toast(context, context.getResources().getString(R.string.bookmark_deleted, entry.getTitle())); + } + + @Override + protected void error(Throwable error) { + String msg; + if (error instanceof OfflineException || error instanceof ServerTooOldException) { + msg = getErrorMessage(error); + } else { + msg = context.getResources().getString(R.string.bookmark_deleted_error, entry.getTitle()) + " " + getErrorMessage(error); + } + + Util.toast(context, msg, false); + } + }.execute(); + } + }); + } +} diff --git a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index c5489c6c..0081f881 100644 --- a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -14,18 +14,17 @@ import android.view.MenuItem; import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.view.EntryAdapter;
import java.io.Serializable;
import java.util.List;
import com.mobeta.android.dslv.*;
import github.daneren2005.dsub.activity.DownloadActivity;
-import github.daneren2005.dsub.activity.SearchActivity;
import github.daneren2005.dsub.domain.PodcastEpisode;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
@@ -47,7 +46,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter private DragSortListView entryList;
int rootId;
- private View footer;
private View emptyView;
private boolean hideButtons = false;
private Boolean licenseValid;
@@ -65,6 +63,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter String albumListType;
String albumListExtra;
int albumListSize;
+ boolean refreshListing = false;
public SelectDirectoryFragment() {
@@ -97,7 +96,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter rootView.setId(rootId);
entryList = (DragSortListView) rootView.findViewById(R.id.select_album_entries);
- footer = LayoutInflater.from(context).inflate(R.layout.select_album_footer, entryList, false);
entryList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
entryList.setOnItemClickListener(this);
entryList.setDropListener(new DragSortListView.DropListener() {
@@ -131,10 +129,14 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter albumListType = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
albumListExtra = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA);
albumListSize = args.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0);
+ refreshListing = args.getBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS);
+ if(entries == null) {
+ entries = (List<MusicDirectory.Entry>) args.getSerializable(Constants.FRAGMENT_LIST);
+ }
}
if(entries == null) {
- if(primaryFragment) {
+ if(primaryFragment || secondaryFragment) {
load(false);
} else {
invalidated = true;
@@ -233,6 +235,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
+
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
MusicDirectory.Entry entry = (MusicDirectory.Entry) entryList.getItemAtPosition(info.position);
@@ -287,6 +293,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getParent());
args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist());
+ if("recent".equals(albumListType)) {
+ args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true);
+ }
parentFragment.setArguments(args);
replaceFragment(parentFragment, fragId);
@@ -299,7 +308,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getTitle());
fragment.setArguments(args);
- replaceFragment(fragment, fragId);
+ replaceFragment(fragment, fragId, fragId == rootId);
} else if (entry.isVideo()) {
playVideo(entry);
} else if(entry instanceof PodcastEpisode) {
@@ -323,7 +332,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter @Override
protected void refresh(boolean refresh) {
- load(refresh);
+ if(!"root".equals(id)) {
+ load(refresh);
+ }
}
@Override
@@ -332,12 +343,16 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
private void load(boolean refresh) {
+ if(refreshListing) {
+ refresh = true;
+ }
+
entryList.setVisibility(View.INVISIBLE);
emptyView.setVisibility(View.INVISIBLE);
if (playlistId != null) {
- getPlaylist(playlistId, playlistName);
+ getPlaylist(playlistId, playlistName, refresh);
} else if(podcastId != null) {
- getPodcast(podcastId, podcastName);
+ getPodcast(podcastId, podcastName, refresh);
} else if (albumListType != null) {
getAlbumList(albumListType, albumListSize);
} else {
@@ -356,24 +371,24 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }.execute();
}
- private void getPlaylist(final String playlistId, final String playlistName) {
+ private void getPlaylist(final String playlistId, final String playlistName, final boolean refresh) {
setTitle(playlistName);
new LoadTask() {
@Override
protected MusicDirectory load(MusicService service) throws Exception {
- return service.getPlaylist(playlistId, playlistName, context, this);
+ return service.getPlaylist(refresh, playlistId, playlistName, context, this);
}
}.execute();
}
- private void getPodcast(final String podcastId, final String podcastName) {
+ private void getPodcast(final String podcastId, final String podcastName, final boolean refresh) {
setTitle(podcastName);
new LoadTask() {
@Override
protected MusicDirectory load(MusicService service) throws Exception {
- return service.getPodcastEpisodes(podcastId, context, this);
+ return service.getPodcastEpisodes(refresh, podcastId, context, this);
}
}.execute();
}
@@ -445,7 +460,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
}
- if (songCount > 0) {
+ if (songCount > 0 && !"root".equals(id)) {
if(showHeader) {
View header = createHeader(entries);
if(header != null) {
@@ -454,7 +469,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
} else {
showHeader = false;
- hideButtons = true;
+ if(!"root".equals(id)) {
+ hideButtons = true;
+ }
}
emptyView.setVisibility(entries.isEmpty() ? View.VISIBLE : View.GONE);
@@ -563,31 +580,33 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter }
final List<MusicDirectory.Entry> songs = getSelectedSongs();
- Runnable onValid = new Runnable() {
+ warnIfNetworkOrStorageUnavailable();
+ LoadingTask<Void> onValid = new LoadingTask<Void>(context) {
@Override
- public void run() {
+ protected Void doInBackground() throws Throwable {
if (!append) {
getDownloadService().clear();
}
- warnIfNetworkOrStorageUnavailable();
getDownloadService().download(songs, save, autoplay, playNext, shuffle);
if (playlistName != null) {
getDownloadService().setSuggestedPlaylistName(playlistName, playlistId);
} else {
getDownloadService().setSuggestedPlaylistName(null, null);
}
+ return null;
+ }
+
+ @Override
+ protected void done(Void result) {
if (autoplay) {
Util.startActivityWithoutTransition(context, DownloadActivity.class);
- if(context instanceof SearchActivity) {
- context.finish();
- }
} else if (save) {
Util.toast(context,
- context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size()));
+ context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size()));
} else if (append) {
Util.toast(context,
- context.getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size()));
+ context.getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size()));
}
}
};
@@ -607,14 +626,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter return;
}
- Runnable onValid = new Runnable() {
+ warnIfNetworkOrStorageUnavailable();
+ LoadingTask<Void> onValid = new LoadingTask<Void>(context) {
@Override
- public void run() {
- warnIfNetworkOrStorageUnavailable();
+ protected Void doInBackground() throws Throwable {
getDownloadService().downloadBackground(songs, save);
+ return null;
+ }
- Util.toast(context,
- context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size()));
+ @Override
+ protected void done(Void result) {
+ Util.toast(context, context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size()));
}
};
@@ -722,6 +744,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.deletePodcastEpisode(episode.getEpisodeId(), context, null);
+ if (getDownloadService() != null) {
+ List<MusicDirectory.Entry> episodeList = new ArrayList<MusicDirectory.Entry>(1);
+ episodeList.add(episode);
+ getDownloadService().delete(episodeList);
+ }
return null;
}
@@ -740,9 +767,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter });
}
- private void checkLicenseAndTrialPeriod(Runnable onValid) {
+ private void checkLicenseAndTrialPeriod(LoadingTask onValid) {
if (licenseValid) {
- onValid.run();
+ onValid.execute();
return;
}
@@ -755,11 +782,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter showDonationDialog(trialDaysLeft, onValid);
} else {
Util.toast(context, context.getResources().getString(R.string.select_album_not_licensed, trialDaysLeft));
- onValid.run();
+ onValid.execute();
}
}
- private void showDonationDialog(int trialDaysLeft, final Runnable onValid) {
+ private void showDonationDialog(int trialDaysLeft, final LoadingTask onValid) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(android.R.drawable.ic_dialog_info);
@@ -786,7 +813,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
if (onValid != null) {
- onValid.run();
+ onValid.execute();
}
}
});
diff --git a/src/github/daneren2005/dsub/fragments/SelectGenreFragment.java b/src/github/daneren2005/dsub/fragments/SelectGenreFragment.java index 2a6693ca..4f0b8a03 100644 --- a/src/github/daneren2005/dsub/fragments/SelectGenreFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectGenreFragment.java @@ -64,11 +64,11 @@ public class SelectGenreFragment extends SubsonicFragment implements AdapterView @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.select_genres, container, false);
+ rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
- genreListView = (ListView)rootView.findViewById(R.id.select_genre_list);
+ genreListView = (ListView)rootView.findViewById(R.id.fragment_list);
genreListView.setOnItemClickListener(this);
- emptyView = rootView.findViewById(R.id.select_genre_empty);
+ emptyView = rootView.findViewById(R.id.fragment_list_empty);
if(genres == null) {
refresh();
@@ -81,6 +81,10 @@ public class SelectGenreFragment extends SubsonicFragment implements AdapterView @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
+ if(!primaryFragment) {
+ return;
+ }
+
menuInflater.inflate(R.menu.select_genres, menu);
}
@@ -92,18 +96,6 @@ public class SelectGenreFragment extends SubsonicFragment implements AdapterView return false;
}
-
- @Override
- public void setPrimaryFragment(boolean primary) {
- super.setPrimaryFragment(primary);
- if(rootView != null) {
- if(primary) {
- ((ViewGroup)rootView).getChildAt(0).setVisibility(View.VISIBLE);
- } else {
- ((ViewGroup)rootView).getChildAt(0).setVisibility(View.GONE);
- }
- }
- }
@Override
protected void refresh(boolean refresh) {
@@ -155,6 +147,6 @@ public class SelectGenreFragment extends SubsonicFragment implements AdapterView args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, genre.getName());
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_genre_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
}
}
diff --git a/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java b/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java index 48338b3d..01c9d938 100644 --- a/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectPlaylistFragment.java @@ -59,10 +59,10 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.select_playlist, container, false);
+ rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
- list = (ListView) rootView.findViewById(R.id.select_playlist_list);
- emptyTextView = rootView.findViewById(R.id.select_playlist_empty);
+ list = (ListView) rootView.findViewById(R.id.fragment_list);
+ emptyTextView = rootView.findViewById(R.id.fragment_list_empty);
list.setOnItemClickListener(this);
registerForContextMenu(list);
@@ -81,7 +81,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
- menuInflater.inflate(R.menu.select_playlist, menu);
+ menuInflater.inflate(R.menu.abstract_top_menu, menu);
}
@Override
@@ -96,6 +96,9 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
MenuInflater inflater = context.getMenuInflater();
if (Util.isOffline(context)) {
@@ -133,7 +136,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_playlist_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
break;
case R.id.playlist_menu_play_shuffled:
fragment = new SelectDirectoryFragment();
@@ -144,7 +147,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_playlist_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
break;
case R.id.playlist_menu_delete:
deletePlaylist(playlist);
@@ -171,7 +174,7 @@ public class SelectPlaylistFragment extends SubsonicFragment implements AdapterV args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_playlist_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
}
@Override
diff --git a/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java b/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java index e9a06076..143ff229 100644 --- a/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java +++ b/src/github/daneren2005/dsub/fragments/SelectPodcastsFragment.java @@ -81,12 +81,12 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
- rootView = inflater.inflate(R.layout.select_podcasts, container, false);
+ rootView = inflater.inflate(R.layout.abstract_list_fragment, container, false);
- podcastListView = (ListView)rootView.findViewById(R.id.select_podcasts_list);
+ podcastListView = (ListView)rootView.findViewById(R.id.fragment_list);
podcastListView.setOnItemClickListener(this);
registerForContextMenu(podcastListView);
- emptyView = rootView.findViewById(R.id.select_podcasts_empty);
+ emptyView = rootView.findViewById(R.id.fragment_list_empty);
if(channels == null) {
if(!primaryFragment) {
@@ -127,6 +127,10 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
+ if(!primaryFragment) {
+ return;
+ }
+
if(!Util.isOffline(context)) {
android.view.MenuInflater inflater = context.getMenuInflater();
inflater.inflate(R.menu.select_podcasts_context, menu);
@@ -205,7 +209,7 @@ public class SelectPodcastsFragment extends SubsonicFragment implements AdapterV args.putString(Constants.INTENT_EXTRA_NAME_PODCAST_DESCRIPTION, channel.getDescription());
fragment.setArguments(args);
- replaceFragment(fragment, R.id.select_podcasts_layout);
+ replaceFragment(fragment, R.id.fragment_list_layout);
}
}
diff --git a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java index 0d79ceda..d33c1b96 100644 --- a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java +++ b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.ContextMenu;
+import android.view.GestureDetector;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
@@ -41,11 +42,9 @@ import android.widget.EditText; import android.widget.TextView;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.activity.DownloadActivity;
-import github.daneren2005.dsub.activity.HelpActivity;
-import github.daneren2005.dsub.activity.MainActivity;
-import github.daneren2005.dsub.activity.SearchActivity;
import github.daneren2005.dsub.activity.SettingsActivity;
import github.daneren2005.dsub.activity.SubsonicActivity;
+import github.daneren2005.dsub.activity.SubsonicFragmentActivity;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.Genre;
import github.daneren2005.dsub.domain.MusicDirectory;
@@ -65,6 +64,7 @@ import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.util.Util;
import java.io.File;
+import java.io.Serializable;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -85,8 +85,10 @@ public class SubsonicFragment extends Fragment { protected CharSequence subtitle = null;
protected View rootView;
protected boolean primaryFragment = false;
+ protected boolean secondaryFragment = false;
protected boolean invalidated = false;
protected static Random random = new Random();
+ protected GestureDetector gestureScanner;
public SubsonicFragment() {
super();
@@ -96,6 +98,19 @@ public class SubsonicFragment extends Fragment { @Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
+
+ if(bundle != null) {
+ String name = bundle.getString(Constants.FRAGMENT_NAME);
+ if(name != null) {
+ title = name;
+ }
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(Constants.FRAGMENT_NAME, title.toString());
}
@Override
@@ -129,12 +144,6 @@ public class SubsonicFragment extends Fragment { case R.id.menu_exit:
exit();
return true;
- case R.id.menu_settings:
- startActivity(new Intent(context, SettingsActivity.class));
- return true;
- case R.id.menu_help:
- startActivity(new Intent(context, HelpActivity.class));
- return true;
}
return false;
@@ -237,9 +246,6 @@ public class SubsonicFragment extends Fragment { getDownloadService().clear();
getDownloadService().download(songs, false, true, true, false);
Util.startActivityWithoutTransition(context, DownloadActivity.class);
- if(context instanceof SearchActivity) {
- context.finish();
- }
break;
case R.id.song_menu_play_next:
getDownloadService().download(songs, false, false, true, false);
@@ -279,7 +285,10 @@ public class SubsonicFragment extends Fragment { }
public void replaceFragment(SubsonicFragment fragment, int id) {
- context.replaceFragment(fragment, id, fragment.getSupportTag());
+ replaceFragment(fragment, id, true);
+ }
+ public void replaceFragment(SubsonicFragment fragment, int id, boolean replaceCurrent) {
+ context.replaceFragment(fragment, id, fragment.getSupportTag(), secondaryFragment && replaceCurrent);
}
protected int getNewId() {
@@ -296,7 +305,9 @@ public class SubsonicFragment extends Fragment { public int getRootId() {
return rootView.getId();
}
-
+
+ public void setSupportTag(int tag) { this.tag = tag; }
+ public void setSupportTag(String tag) { this.tag = Integer.parseInt(tag); }
public int getSupportTag() {
return tag;
}
@@ -314,10 +325,14 @@ public class SubsonicFragment extends Fragment { }
}
}
-
+ public void setPrimaryFragment(boolean primary, boolean secondary) {
+ setPrimaryFragment(primary);
+ secondaryFragment = secondary;
+ }
+
public void invalidate() {
if(primaryFragment) {
- refresh(false);
+ refresh(true);
} else {
invalidated = true;
}
@@ -335,8 +350,8 @@ public class SubsonicFragment extends Fragment { }
protected void exit() {
- if(context.getClass() != MainActivity.class) {
- Intent intent = new Intent(context, MainActivity.class);
+ if(context.getClass() != SubsonicFragmentActivity.class) {
+ Intent intent = new Intent(context, SubsonicFragmentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
Util.startActivityWithoutTransition(context, intent);
@@ -512,6 +527,12 @@ public class SubsonicFragment extends Fragment { protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.setStarred(entry.getId(), starred, context, null);
+
+ // Make sure to clear parent cache
+ String s = Util.getRestUrl(context, null) + entry.getParent();
+ String parentCache = "directory-" + s.hashCode() + ".ser";
+ File file = new File(context.getCacheDir(), parentCache);
+ file.delete();
return null;
}
@@ -587,7 +608,7 @@ public class SubsonicFragment extends Fragment { if(isDirectory)
root = musicService.getMusicDirectory(id, name, false, context, this);
else
- root = musicService.getPlaylist(id, name, context, this);
+ root = musicService.getPlaylist(true, id, name, context, this);
List<MusicDirectory.Entry> songs = new LinkedList<MusicDirectory.Entry>();
getSongsRecursively(root, songs);
return songs;
@@ -621,9 +642,6 @@ public class SubsonicFragment extends Fragment { downloadService.download(songs, save, autoplay, false, shuffle);
if(!append) {
Util.startActivityWithoutTransition(context, DownloadActivity.class);
- if(context instanceof SearchActivity) {
- context.finish();
- }
}
}
else {
@@ -792,7 +810,7 @@ public class SubsonicFragment extends Fragment { @Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
- MusicDirectory playlist = musicService.getPlaylist(id, name, context, null);
+ MusicDirectory playlist = musicService.getPlaylist(true, id, name, context, null);
List<MusicDirectory.Entry> toDelete = playlist.getChildren();
musicService.overwritePlaylist(id, name, toDelete.size(), songs, context, null);
return null;
@@ -960,6 +978,8 @@ public class SubsonicFragment extends Fragment { public void deleteRecursively(Artist artist) {
File dir = FileUtil.getArtistDirectory(context, artist);
+ if(dir == null) return;
+
Util.recursiveDelete(dir);
if(Util.isOffline(context)) {
refresh();
@@ -968,9 +988,15 @@ public class SubsonicFragment extends Fragment { public void deleteRecursively(MusicDirectory.Entry album) {
File dir = FileUtil.getAlbumDirectory(context, album);
+ if(dir == null) return;
+
Util.recursiveDelete(dir);
if(Util.isOffline(context)) {
refresh();
}
}
+
+ public GestureDetector getGestureDetector() {
+ return gestureScanner;
+ }
}
diff --git a/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java b/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java index 7215040c..3b4e545f 100644 --- a/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java +++ b/src/github/daneren2005/dsub/provider/DSubWidgetProvider.java @@ -25,6 +25,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; @@ -36,16 +37,17 @@ import android.graphics.RectF; import android.os.Environment; import android.util.Log; import android.view.KeyEvent; +import android.view.View; import android.widget.RemoteViews; import github.daneren2005.dsub.R; import github.daneren2005.dsub.activity.DownloadActivity; -import github.daneren2005.dsub.activity.MainActivity; +import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.DownloadServiceImpl; import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.FileUtil; -import java.util.HashMap; +import github.daneren2005.dsub.util.Util; /** * Simple widget to show currently playing album art along @@ -143,6 +145,16 @@ public class DSubWidgetProvider extends AppWidgetProvider { final Resources res = context.getResources(); final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout()); + if(playing) { + views.setViewVisibility(R.id.widget_root, View.VISIBLE); + } else { + // Hide widget + SharedPreferences prefs = Util.getPreferences(context); + if(prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) { + views.setViewVisibility(R.id.widget_root, View.GONE); + } + } + MusicDirectory.Entry currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong(); String title = currentPlaying == null ? null : currentPlaying.getTitle(); CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist(); @@ -243,10 +255,10 @@ public class DSubWidgetProvider extends AppWidgetProvider { * * @param playerActive True if player is active in background, which means * widget click will launch {@link DownloadActivity}, - * otherwise we launch {@link MainActivity}. + * otherwise we launch {@link github.daneren2005.dsub.activity.SubsonicFragmentActivity}. */ private void linkButtons(Context context, RemoteViews views, boolean playerActive) { - Intent intent = new Intent(context, MainActivity.class); + Intent intent = new Intent(context, SubsonicFragmentActivity.class); if(playerActive) { intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); diff --git a/src/github/daneren2005/dsub/receiver/BluetoothIntentReceiver.java b/src/github/daneren2005/dsub/receiver/BluetoothIntentReceiver.java index 567cf8f4..ab46c784 100644 --- a/src/github/daneren2005/dsub/receiver/BluetoothIntentReceiver.java +++ b/src/github/daneren2005/dsub/receiver/BluetoothIntentReceiver.java @@ -22,8 +22,10 @@ import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.util.Log; import github.daneren2005.dsub.service.DownloadServiceImpl; +import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.Util; /** @@ -44,7 +46,11 @@ public class BluetoothIntentReceiver extends BroadcastReceiver { Util.registerMediaButtonEventReceiver(context); } else if (isDisconnected(intent)) { Log.i(TAG, "Disconnected from Bluetooth A2DP, requesting pause."); - context.sendBroadcast(new Intent(DownloadServiceImpl.CMD_PAUSE)); + SharedPreferences prefs = Util.getPreferences(context); + int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0")); + if(pausePref == 0 || pausePref == 2) { + context.sendBroadcast(new Intent(DownloadServiceImpl.CMD_PAUSE)); + } } } private boolean isConnected(Intent intent) { @@ -75,4 +81,4 @@ public class BluetoothIntentReceiver extends BroadcastReceiver { } return false; } -}
\ No newline at end of file +} diff --git a/src/github/daneren2005/dsub/service/CachedMusicService.java b/src/github/daneren2005/dsub/service/CachedMusicService.java index cc8d2dbd..5a7737de 100644 --- a/src/github/daneren2005/dsub/service/CachedMusicService.java +++ b/src/github/daneren2005/dsub/service/CachedMusicService.java @@ -18,6 +18,8 @@ */ package github.daneren2005.dsub.service; +import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -26,6 +28,8 @@ import org.apache.http.HttpResponse; import android.content.Context; import android.graphics.Bitmap; import android.support.v4.util.LruCache; + +import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.ChatMessage; import github.daneren2005.dsub.domain.Genre; import github.daneren2005.dsub.domain.Indexes; @@ -42,6 +46,7 @@ import github.daneren2005.dsub.domain.Version; import github.daneren2005.dsub.util.CancellableTask; import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.TimeLimitedCache; +import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Util; /** @@ -92,7 +97,14 @@ public class CachedMusicService implements MusicService { } List<MusicFolder> result = cachedMusicFolders.get(); if (result == null) { - result = musicService.getMusicFolders(refresh, context, progressListener); + if(!refresh) { + result = FileUtil.deserialize(context, getCacheName(context, "musicFolders"), ArrayList.class); + } + + if(result == null) { + result = musicService.getMusicFolders(refresh, context, progressListener); + FileUtil.serialize(context, new ArrayList<MusicFolder>(result), getCacheName(context, "musicFolders")); + } cachedMusicFolders.set(result); } return result; @@ -120,7 +132,14 @@ public class CachedMusicService implements MusicService { TimeLimitedCache<MusicDirectory> cache = refresh ? null : cachedMusicDirectories.get(id); MusicDirectory dir = cache == null ? null : cache.get(); if (dir == null) { - dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener); + if(!refresh) { + dir = FileUtil.deserialize(context, getCacheName(context, "directory", id), MusicDirectory.class); + } + + if(dir == null) { + dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener); + FileUtil.serialize(context, dir, getCacheName(context, "directory", id)); + } cache = new TimeLimitedCache<MusicDirectory>(TTL_MUSIC_DIR, TimeUnit.SECONDS); cache.set(dir); cachedMusicDirectories.put(id, cache); @@ -134,8 +153,16 @@ public class CachedMusicService implements MusicService { } @Override - public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception { - return musicService.getPlaylist(id, name, context, progressListener); + public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception { + MusicDirectory dir = null; + if(!refresh) { + dir = FileUtil.deserialize(context, getCacheName(context, "playlist", id), MusicDirectory.class); + } + if(dir == null) { + dir = musicService.getPlaylist(refresh, id, name, context, progressListener); + FileUtil.serialize(context, dir, getCacheName(context, "playlist", id)); + } + return dir; } @Override @@ -143,7 +170,14 @@ public class CachedMusicService implements MusicService { checkSettingsChanged(context); List<Playlist> result = refresh ? null : cachedPlaylists.get(); if (result == null) { - result = musicService.getPlaylists(refresh, context, progressListener); + if(!refresh) { + result = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class); + } + + if(result == null) { + result = musicService.getPlaylists(refresh, context, progressListener); + FileUtil.serialize(context, new ArrayList<Playlist>(result), getCacheName(context, "playlist")); + } cachedPlaylists.set(result); } return result; @@ -152,11 +186,13 @@ public class CachedMusicService implements MusicService { @Override public void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception { cachedPlaylists.clear(); + Util.delete(new File(context.getCacheDir(), getCacheName(context, "playlist"))); musicService.createPlaylist(id, name, entries, context, progressListener); } @Override public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception { + Util.delete(new File(context.getCacheDir(), getCacheName(context, "playlist"))); musicService.deletePlaylist(id, context, progressListener); } @@ -296,7 +332,14 @@ public class CachedMusicService implements MusicService { List<Genre> result = refresh ? null : cachedGenres.get(); if (result == null) { - result = musicService.getGenres(refresh, context, progressListener); + if(!refresh) { + result = FileUtil.deserialize(context, getCacheName(context, "genre"), ArrayList.class); + } + + if(result == null) { + result = musicService.getGenres(refresh, context, progressListener); + FileUtil.serialize(context, new ArrayList<Genre>(result), getCacheName(context, "genre")); + } cachedGenres.set(result); } @@ -314,7 +357,14 @@ public class CachedMusicService implements MusicService { List<PodcastChannel> result = refresh ? null : cachedPodcastChannels.get(); if (result == null) { - result = musicService.getPodcastChannels(refresh, context, progressListener); + if(!refresh) { + result = FileUtil.deserialize(context, getCacheName(context, "podcast"), ArrayList.class); + } + + if(result == null) { + result = musicService.getPodcastChannels(refresh, context, progressListener); + FileUtil.serialize(context, new ArrayList<PodcastChannel>(result), getCacheName(context, "podcast")); + } cachedPodcastChannels.set(result); } @@ -322,8 +372,8 @@ public class CachedMusicService implements MusicService { } @Override - public MusicDirectory getPodcastEpisodes(String id, Context context, ProgressListener progressListener) throws Exception { - return musicService.getPodcastEpisodes(id, context, progressListener); + public MusicDirectory getPodcastEpisodes(boolean refresh, String id, Context context, ProgressListener progressListener) throws Exception { + return musicService.getPodcastEpisodes(refresh, id, context, progressListener); } @Override @@ -333,11 +383,15 @@ public class CachedMusicService implements MusicService { @Override public void createPodcastChannel(String url, Context context, ProgressListener progressListener) throws Exception{ + Util.delete(new File(context.getCacheDir(), getCacheName(context, "podcast"))); + cachedPodcastChannels.clear(); musicService.createPodcastChannel(url, context, progressListener); } @Override public void deletePodcastChannel(String id, Context context, ProgressListener progressListener) throws Exception{ + Util.delete(new File(context.getCacheDir(), getCacheName(context, "podcast"))); + cachedPodcastChannels.clear(); musicService.deletePodcastChannel(id, context, progressListener); } @@ -350,13 +404,40 @@ public class CachedMusicService implements MusicService { public void deletePodcastEpisode(String id, Context context, ProgressListener progressListener) throws Exception{ musicService.deletePodcastEpisode(id, context, progressListener); } - + + @Override + public void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception { + musicService.setRating(id, rating, context, progressListener); + } + + @Override + public List<Bookmark> getBookmarks(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + return musicService.getBookmarks(refresh, context, progressListener); + } + + @Override + public void createBookmark(String id, int position, String comment, Context context, ProgressListener progressListener) throws Exception { + musicService.createBookmark(id, position, comment, context, progressListener); + } + + @Override + public void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception { + musicService.deleteBookmark(id, context, progressListener); + } + @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ return musicService.processOfflineSyncs(context, progressListener); } - + private String getCacheName(Context context, String name, String id) { + String s = Util.getRestUrl(context, null) + id; + return name + "-" + s.hashCode() + ".ser"; + } + private String getCacheName(Context context, String name) { + String s = Util.getRestUrl(context, null); + return name + "-" + s.hashCode() + ".ser"; + } private void checkSettingsChanged(Context context) { String newUrl = Util.getRestUrl(context, null); diff --git a/src/github/daneren2005/dsub/service/DownloadFile.java b/src/github/daneren2005/dsub/service/DownloadFile.java index 5ab7ad70..c2cffdef 100644 --- a/src/github/daneren2005/dsub/service/DownloadFile.java +++ b/src/github/daneren2005/dsub/service/DownloadFile.java @@ -30,6 +30,7 @@ import android.os.PowerManager; import android.util.DisplayMetrics; import android.util.Log; import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.service.parser.SubsonicRESTException; import github.daneren2005.dsub.util.CancellableTask; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Util; @@ -44,8 +45,8 @@ import org.apache.http.HttpStatus; * @version $Id$ */ public class DownloadFile { - private static final String TAG = DownloadFile.class.getSimpleName(); + private static final int MAX_FAILURES = 5; private final Context context; private final MusicDirectory.Entry song; private final File partialFile; @@ -55,7 +56,8 @@ public class DownloadFile { private final MediaStoreService mediaStoreService; private CancellableTask downloadTask; private boolean save; - private boolean failed; + private boolean failedDownload = false; + private int failed = 0; private int bitRate; private boolean isPlaying = false; private boolean saveWhenDone = false; @@ -98,7 +100,7 @@ public class DownloadFile { public synchronized void download() { FileUtil.createDirectoryForParent(saveFile); - failed = false; + failedDownload = false; if(!partialFile.exists()) { bitRate = Util.getMaxBitrate(context); } @@ -153,7 +155,10 @@ public class DownloadFile { } public boolean isFailed() { - return failed; + return failedDownload; + } + public boolean isFailedMax() { + return failed > MAX_FAILURES; } public void delete() { @@ -212,11 +217,18 @@ public class DownloadFile { completeWhenDone = false; } } catch(IOException ex) { - Log.w(TAG, "Failed to rename file " + completeFile + " to " + saveFile); + Log.w(TAG, "Failed to rename file " + completeFile + " to " + saveFile, ex); } this.isPlaying = isPlaying; } + public void renamePartial() { + try { + Util.renameFile(partialFile, completeFile); + } catch(IOException ex) { + Log.w(TAG, "Failed to rename file " + partialFile + " to " + completeFile, ex); + } + } public boolean getPlaying() { return isPlaying; } @@ -314,12 +326,21 @@ public class DownloadFile { } } + } catch(SubsonicRESTException x) { + Util.close(out); + Util.delete(completeFile); + Util.delete(saveFile); + if (!isCancelled()) { + failed++; + failedDownload = true; + Log.w(TAG, "Failed to download '" + song + "'.", x); + } } catch (Exception x) { Util.close(out); Util.delete(completeFile); Util.delete(saveFile); if (!isCancelled()) { - failed = true; + failedDownload = true; Log.w(TAG, "Failed to download '" + song + "'.", x); } diff --git a/src/github/daneren2005/dsub/service/DownloadService.java b/src/github/daneren2005/dsub/service/DownloadService.java index 7e8c8c81..1a254c73 100644 --- a/src/github/daneren2005/dsub/service/DownloadService.java +++ b/src/github/daneren2005/dsub/service/DownloadService.java @@ -22,6 +22,7 @@ import java.util.List; import github.daneren2005.dsub.audiofx.EqualizerController; import github.daneren2005.dsub.audiofx.VisualizerController; +import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.RemoteControlState; @@ -33,6 +34,7 @@ import github.daneren2005.dsub.domain.RepeatMode; */ public interface DownloadService { + void download(Bookmark bookmark); void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle); void downloadBackground(List<MusicDirectory.Entry> songs, boolean save); diff --git a/src/github/daneren2005/dsub/service/DownloadServiceImpl.java b/src/github/daneren2005/dsub/service/DownloadServiceImpl.java index 66d31a0f..e379291f 100644 --- a/src/github/daneren2005/dsub/service/DownloadServiceImpl.java +++ b/src/github/daneren2005/dsub/service/DownloadServiceImpl.java @@ -28,6 +28,7 @@ import static github.daneren2005.dsub.domain.PlayerState.STARTED; import static github.daneren2005.dsub.domain.PlayerState.STOPPED; import github.daneren2005.dsub.audiofx.EqualizerController; import github.daneren2005.dsub.audiofx.VisualizerController; +import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.RemoteControlState; @@ -115,6 +116,8 @@ public class DownloadServiceImpl extends Service implements DownloadService { private PowerManager.WakeLock wakeLock; private boolean keepScreenOn; private int cachedPosition = 0; + private long downloadRevision; + private boolean downloadOngoing = false; private static boolean equalizerAvailable; private static boolean visualizerAvailable; @@ -268,6 +271,17 @@ public class DownloadServiceImpl extends Service implements DownloadService { return binder; } + @Override + public synchronized void download(Bookmark bookmark) { + clear(); + DownloadFile downloadFile = new DownloadFile(this, bookmark.getEntry(), false); + downloadList.add(downloadFile); + revision++; + updateJukeboxPlaylist(); + play(0, true, bookmark.getPosition()); + lifecycleSupport.serializeDownloadQueue(); + } + @Override public synchronized void download(List<MusicDirectory.Entry> songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { setShufflePlayEnabled(false); @@ -318,7 +332,10 @@ public class DownloadServiceImpl extends Service implements DownloadService { public synchronized void downloadBackground(List<MusicDirectory.Entry> songs, boolean save) { for (MusicDirectory.Entry song : songs) { DownloadFile downloadFile = new DownloadFile(this, song, save); - backgroundDownloadList.add(downloadFile); + if(!downloadFile.isWorkDone() || (downloadFile.shouldSave() && !downloadFile.isSaved())) { + // Only add to list if there is work to be done + backgroundDownloadList.add(downloadFile); + } } revision++; @@ -578,21 +595,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { return; } - int index = getCurrentPlayingIndex(); - if (index != -1) { - switch (getRepeatMode()) { - case OFF: - index = index + 1; - break; - case ALL: - index = (index + 1) % size(); - break; - case SINGLE: - break; - default: - break; - } - } + int index = getNextPlayingIndex(); nextSetup = false; if(nextPlayingTask != null) { @@ -613,6 +616,24 @@ public class DownloadServiceImpl extends Service implements DownloadService { public synchronized int getCurrentPlayingIndex() { return downloadList.indexOf(currentPlaying); } + private int getNextPlayingIndex() { + int index = getCurrentPlayingIndex(); + if (index != -1) { + switch (getRepeatMode()) { + case OFF: + index = index + 1; + break; + case ALL: + index = (index + 1) % size(); + break; + case SINGLE: + break; + default: + break; + } + } + return index; + } @Override public DownloadFile getCurrentPlaying() { @@ -657,8 +678,10 @@ public class DownloadServiceImpl extends Service implements DownloadService { public synchronized void play(int index) { play(index, true); } - - private synchronized void play(int index, boolean start) { + private synchronized void play(int index, boolean start) { + play(index, start, 0); + } + private synchronized void play(int index, boolean start, int position) { if (index < 0 || index >= size()) { reset(); setCurrentPlaying(null, false); @@ -674,7 +697,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { remoteController.changeTrack(index, downloadList.get(index)); setPlayerState(STARTED); } else { - bufferAndPlay(); + bufferAndPlay(position); } } if (remoteState == RemoteControlState.LOCAL) { @@ -761,28 +784,18 @@ public class DownloadServiceImpl extends Service implements DownloadService { @Override public synchronized void next() { int index = getCurrentPlayingIndex(); - if (index != -1) { - play(index + 1); + int nextPlayingIndex = getNextPlayingIndex(); + // Make sure to actually go to next when repeat song is on + if(index == nextPlayingIndex) { + nextPlayingIndex++; + } + if (index != -1 && nextPlayingIndex < size()) { + play(nextPlayingIndex); } } private void onSongCompleted() { - int index = getCurrentPlayingIndex(); - if (index != -1) { - switch (getRepeatMode()) { - case OFF: - play(index + 1); - break; - case ALL: - play((index + 1) % size()); - break; - case SINGLE: - play(index); - break; - default: - break; - } - } + play(getNextPlayingIndex()); } @Override @@ -1072,14 +1085,17 @@ public class DownloadServiceImpl extends Service implements DownloadService { remoteController.setVolume(up); } - private synchronized void bufferAndPlay() { + private synchronized void bufferAndPlay() { + bufferAndPlay(0); + } + private synchronized void bufferAndPlay(int position) { if(playerState != PREPARED) { reset(); - bufferTask = new BufferTask(currentPlaying, 0); + bufferTask = new BufferTask(currentPlaying, position); bufferTask.start(); } else { - doPlay(currentPlaying, 0, true); + doPlay(currentPlaying, position, true); } } @@ -1138,7 +1154,10 @@ public class DownloadServiceImpl extends Service implements DownloadService { } } - lifecycleSupport.serializeDownloadQueue(); + // Only call when starting, setPlayerState(PAUSED) already calls this + if(start) { + lifecycleSupport.serializeDownloadQueue(); + } } catch (Exception x) { handleError(x); } @@ -1158,6 +1177,8 @@ public class DownloadServiceImpl extends Service implements DownloadService { final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); if(nextMediaPlayer != null) { nextMediaPlayer.setOnCompletionListener(null); + nextMediaPlayer.setOnErrorListener(null); + nextMediaPlayer.reset(); nextMediaPlayer.release(); nextMediaPlayer = null; } @@ -1345,7 +1366,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { checkShufflePlay(); } - if (remoteState != RemoteControlState.LOCAL || !Util.isNetworkConnected(this)) { + if (remoteState != RemoteControlState.LOCAL || !Util.isNetworkConnected(this) || Util.isOffline(this)) { return; } @@ -1380,7 +1401,7 @@ public class DownloadServiceImpl extends Service implements DownloadService { int i = start; do { DownloadFile downloadFile = downloadList.get(i); - if (!downloadFile.isWorkDone()) { + if (!downloadFile.isWorkDone() && !downloadFile.isFailedMax()) { if (downloadFile.shouldSave() || preloaded < Util.getPreloadCount(this)) { currentDownloading = downloadFile; currentDownloading.download(); @@ -1407,15 +1428,26 @@ public class DownloadServiceImpl extends Service implements DownloadService { revision++; i--; } else { - currentDownloading = downloadFile; - currentDownloading.download(); - cleanupCandidates.add(currentDownloading); - break; + if(!downloadFile.isFailedMax()) { + currentDownloading = downloadFile; + currentDownloading.download(); + cleanupCandidates.add(currentDownloading); + break; + } } } } } + if(!backgroundDownloadList.isEmpty() && downloadRevision != revision) { + Util.showDownloadingNotification(this, currentDownloading, backgroundDownloadList.size()); + downloadRevision = revision; + downloadOngoing = true; + } else if(backgroundDownloadList.isEmpty() && downloadOngoing) { + Util.hideDownloadingNotification(this); + downloadOngoing = false; + } + // Delete obsolete .partial and .complete files. cleanup(); } diff --git a/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java b/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java index 4e3ec29c..563565b2 100644 --- a/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java +++ b/src/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java @@ -31,6 +31,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.media.RemoteControlClient; import android.os.AsyncTask; import android.os.Build; @@ -43,6 +44,7 @@ import android.view.KeyEvent; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.util.CacheCleaner; +import github.daneren2005.dsub.util.Constants; import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Util; @@ -52,7 +54,7 @@ import github.daneren2005.dsub.util.Util; public class DownloadServiceLifecycleSupport { private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName(); - private static final String FILENAME_DOWNLOADS_SER = "downloadstate.ser"; + private static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser"; private final DownloadServiceImpl downloadService; private Looper eventLooper; @@ -141,7 +143,11 @@ public class DownloadServiceLifecycleSupport { @Override public void run() { if(!downloadService.isRemoteEnabled()) { - downloadService.pause(); + SharedPreferences prefs = Util.getPreferences(downloadService); + int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0")); + if(pausePref == 0 || pausePref == 1) { + downloadService.pause(); + } } } }); @@ -252,20 +258,29 @@ public class DownloadServiceLifecycleSupport { state.currentPlayingIndex = downloadService.getCurrentPlayingIndex(); state.currentPlayingPosition = downloadService.getPlayerPosition(); + DownloadFile currentPlaying = downloadService.getCurrentPlaying(); + if(currentPlaying != null) { + state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable(); + } + Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition); FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER); } private void deserializeDownloadQueueNow() { - State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER); + State state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER, State.class); if (state == null) { return; } Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition); - downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition); - // Work-around: Serialize again, as the restore() method creates a serialization without current playing info. - serializeDownloadQueue(); + // Rename first thing before anything else starts + if(state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) { + DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false); + currentPlaying.renamePartial(); + } + + downloadService.restore(state.songs, state.currentPlayingIndex, state.currentPlayingPosition); } private void handleKeyEvent(KeyEvent event) { @@ -363,5 +378,6 @@ public class DownloadServiceLifecycleSupport { private List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>(); private int currentPlayingIndex; private int currentPlayingPosition; + private boolean renameCurrent = false; } } diff --git a/src/github/daneren2005/dsub/service/JukeboxController.java b/src/github/daneren2005/dsub/service/JukeboxController.java index fcd58e01..faace3ae 100644 --- a/src/github/daneren2005/dsub/service/JukeboxController.java +++ b/src/github/daneren2005/dsub/service/JukeboxController.java @@ -104,7 +104,7 @@ public class JukeboxController extends RemoteController { if (jukeboxStatus != null) { jukeboxStatus.setPositionSeconds(seconds); } - tasks.add(new Skip(-1, seconds)); + tasks.add(new Skip(downloadService.getCurrentPlayingIndex(), seconds)); downloadService.setPlayerState(PlayerState.STARTED); } @Override diff --git a/src/github/daneren2005/dsub/service/MusicService.java b/src/github/daneren2005/dsub/service/MusicService.java index cae307cb..8d204530 100644 --- a/src/github/daneren2005/dsub/service/MusicService.java +++ b/src/github/daneren2005/dsub/service/MusicService.java @@ -24,6 +24,8 @@ import org.apache.http.HttpResponse; import android.content.Context; import android.graphics.Bitmap; + +import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.ChatMessage; import github.daneren2005.dsub.domain.Genre; import github.daneren2005.dsub.domain.Indexes; @@ -59,7 +61,7 @@ public interface MusicService { MusicDirectory getStarredList(Context context, ProgressListener progressListener) throws Exception; - MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception; + MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception; List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception; @@ -123,7 +125,7 @@ public interface MusicService { List<PodcastChannel> getPodcastChannels(boolean refresh, Context context, ProgressListener progressListener) throws Exception; - MusicDirectory getPodcastEpisodes(String id, Context context, ProgressListener progressListener) throws Exception; + MusicDirectory getPodcastEpisodes(boolean refresh, String id, Context context, ProgressListener progressListener) throws Exception; void refreshPodcasts(Context context, ProgressListener progressListener) throws Exception; @@ -134,6 +136,14 @@ public interface MusicService { void downloadPodcastEpisode(String id, Context context, ProgressListener progressListener) throws Exception; void deletePodcastEpisode(String id, Context context, ProgressListener progressListener) throws Exception; + + void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception; + + List<Bookmark> getBookmarks(boolean refresh, Context context, ProgressListener progressListener) throws Exception; + + void createBookmark(String id, int position, String comment, Context context, ProgressListener progressListener) throws Exception; + + void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception; int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception; }
\ No newline at end of file diff --git a/src/github/daneren2005/dsub/service/OfflineMusicService.java b/src/github/daneren2005/dsub/service/OfflineMusicService.java index 1221df5c..ba798c09 100644 --- a/src/github/daneren2005/dsub/service/OfflineMusicService.java +++ b/src/github/daneren2005/dsub/service/OfflineMusicService.java @@ -32,9 +32,9 @@ import java.util.Set; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.media.MediaMetadataRetriever; import android.util.Log; import github.daneren2005.dsub.domain.Artist; +import github.daneren2005.dsub.domain.Bookmark; import github.daneren2005.dsub.domain.Genre; import github.daneren2005.dsub.domain.Indexes; import github.daneren2005.dsub.domain.RemoteStatus; @@ -147,7 +147,10 @@ public class OfflineMusicService extends RESTMusicService { return FileUtil.getBaseName(name); } - private MusicDirectory.Entry createEntry(Context context, File file, String name) { + private MusicDirectory.Entry createEntry(Context context, File file, String name) { + return createEntry(context, file, name, true); + } + private MusicDirectory.Entry createEntry(Context context, File file, String name, boolean load) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); entry.setDirectory(file.isDirectory()); entry.setId(file.getPath()); @@ -179,33 +182,8 @@ public class OfflineMusicService extends RESTMusicService { } } - try { - MediaMetadataRetriever metadata = new MediaMetadataRetriever(); - metadata.setDataSource(file.getAbsolutePath()); - String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER); - if(discNumber == null) { - discNumber = "1/1"; - } - int slashIndex = discNumber.indexOf("/"); - if(slashIndex > 0) { - discNumber = discNumber.substring(0, slashIndex); - } - entry.setDiscNumber(Integer.parseInt(discNumber)); - String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); - entry.setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000); - String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); - entry.setDuration(Integer.parseInt(length) / 1000); - String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); - if(artist != null) { - entry.setArtist(artist); - } - String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM); - if(album != null) { - entry.setAlbum(album); - } - metadata.release(); - } catch(Exception e) { - Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver"); + if(load) { + entry.loadMetadata(file); } } @@ -401,7 +379,7 @@ public class OfflineMusicService extends RESTMusicService { } @Override - public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception { + public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception { DownloadService downloadService = DownloadServiceImpl.getInstance(); if (downloadService == null) { return new MusicDirectory(); @@ -427,7 +405,7 @@ public class OfflineMusicService extends RESTMusicService { File entryFile = new File(line); String entryName = getName(entryFile); if(entryFile.exists() && entryName != null){ - playlist.addChild(createEntry(context, entryFile, entryName)); + playlist.addChild(createEntry(context, entryFile, entryName, false)); } } @@ -629,7 +607,7 @@ public class OfflineMusicService extends RESTMusicService { } @Override - public MusicDirectory getPodcastEpisodes(String id, Context context, ProgressListener progressListener) throws Exception { + public MusicDirectory getPodcastEpisodes(boolean refresh, String id, Context context, ProgressListener progressListener) throws Exception { return getMusicDirectory(FileUtil.getPodcastDirectory(context, id).getPath(), null, false, context, progressListener); } @@ -657,6 +635,26 @@ public class OfflineMusicService extends RESTMusicService { public void deletePodcastEpisode(String id, Context context, ProgressListener progressListener) throws Exception{ throw new OfflineException("Getting Podcasts not available in offline mode"); } + + @Override + public void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception { + throw new OfflineException("Setting ratings not available in offline mode"); + } + + @Override + public List<Bookmark> getBookmarks(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + throw new OfflineException("Getting bookmarks not available in offline mode"); + } + + @Override + public void createBookmark(String id, int position, String comment, Context context, ProgressListener progressListener) throws Exception { + throw new OfflineException("Creating bookmarks not available in offline mode"); + } + + @Override + public void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception { + throw new OfflineException("Deleting bookmarks not available in offline mode"); + } @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ diff --git a/src/github/daneren2005/dsub/service/RESTMusicService.java b/src/github/daneren2005/dsub/service/RESTMusicService.java index 82148dc0..22abacb1 100644 --- a/src/github/daneren2005/dsub/service/RESTMusicService.java +++ b/src/github/daneren2005/dsub/service/RESTMusicService.java @@ -70,6 +70,7 @@ import android.util.Log; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.*; import github.daneren2005.dsub.service.parser.AlbumListParser; +import github.daneren2005.dsub.service.parser.BookmarkParser; import github.daneren2005.dsub.service.parser.ChatMessageParser; import github.daneren2005.dsub.service.parser.ErrorParser; import github.daneren2005.dsub.service.parser.GenreParser; @@ -186,17 +187,9 @@ public class RESTMusicService implements MusicService { } public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - - List<MusicFolder> cachedMusicFolders = readCachedMusicFolders(context); - if (cachedMusicFolders != null && !refresh) { - return cachedMusicFolders; - } - Reader reader = getReader(context, progressListener, "getMusicFolders", null); try { - List<MusicFolder> musicFolders = new MusicFoldersParser(context).parse(reader, progressListener); - writeCachedMusicFolders(context, musicFolders); - return musicFolders; + return new MusicFoldersParser(context).parse(reader, progressListener); } finally { Util.close(reader); } @@ -243,7 +236,7 @@ public class RESTMusicService implements MusicService { private Indexes readCachedIndexes(Context context, String musicFolderId) { String filename = getCachedIndexesFilename(context, musicFolderId); - return FileUtil.deserialize(context, filename); + return FileUtil.deserialize(context, filename, Indexes.class); } private void writeCachedIndexes(Context context, Indexes indexes, String musicFolderId) { @@ -256,21 +249,6 @@ public class RESTMusicService implements MusicService { return "indexes-" + Math.abs(s.hashCode()) + ".ser"; } - private ArrayList<MusicFolder> readCachedMusicFolders(Context context) { - String filename = getCachedMusicFoldersFilename(context); - return FileUtil.deserialize(context, filename); - } - - private void writeCachedMusicFolders(Context context, List<MusicFolder> musicFolders) { - String filename = getCachedMusicFoldersFilename(context); - FileUtil.serialize(context, new ArrayList<MusicFolder>(musicFolders), filename); - } - - private String getCachedMusicFoldersFilename(Context context) { - String s = Util.getRestUrl(context, null); - return "musicFolders-" + Math.abs(s.hashCode()) + ".ser"; - } - @Override public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { SharedPreferences prefs = Util.getPreferences(context); @@ -336,7 +314,7 @@ public class RESTMusicService implements MusicService { } @Override - public MusicDirectory getPlaylist(String id, String name, Context context, ProgressListener progressListener) throws Exception { + public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception { HttpParams params = new BasicHttpParams(); HttpConnectionParams.setSoTimeout(params, SOCKET_READ_TIMEOUT_GET_PLAYLIST); @@ -755,10 +733,6 @@ public class RESTMusicService implements MusicService { public RemoteStatus skipJukebox(int index, int offsetSeconds, Context context, ProgressListener progressListener) throws Exception { List<String> parameterNames = Arrays.asList("action", "index", "offset"); List<Object> parameterValues = Arrays.<Object>asList("skip", index, offsetSeconds); - if(index < 0) { - parameterNames.remove(1); - parameterValues.remove(1); - } return executeJukeboxCommand(context, progressListener, parameterNames, parameterValues); } @@ -927,7 +901,7 @@ public class RESTMusicService implements MusicService { } @Override - public MusicDirectory getPodcastEpisodes(String id, Context context, ProgressListener progressListener) throws Exception { + public MusicDirectory getPodcastEpisodes(boolean refresh, String id, Context context, ProgressListener progressListener) throws Exception { Reader reader = getReader(context, progressListener, "getPodcasts", null, Arrays.asList("id"), Arrays.<Object>asList(id)); try { return new PodcastEntryParser(context).parse(id, reader, progressListener); @@ -995,7 +969,55 @@ public class RESTMusicService implements MusicService { Util.close(reader); } } - + + @Override + public void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.6", "Setting ratings not supported."); + + Reader reader = getReader(context, progressListener, "setRating", null, Arrays.asList("id", "rating"), Arrays.<Object>asList(id, rating)); + try { + new ErrorParser(context).parse(reader); + } finally { + Util.close(reader); + } + } + + @Override + public List<Bookmark> getBookmarks(boolean refresh, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.9", "Bookmarks not supported."); + + Reader reader = getReader(context, progressListener, "getBookmarks", null); + try { + return new BookmarkParser(context).parse(reader, progressListener); + } finally { + Util.close(reader); + } + } + + @Override + public void createBookmark(String id, int position, String comment, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.9", "Creating bookmarks not supported."); + + Reader reader = getReader(context, progressListener, "createBookmark", null, Arrays.asList("id", "position", "comment"), Arrays.<Object>asList(id, position, comment)); + try { + new ErrorParser(context).parse(reader); + } finally { + Util.close(reader); + } + } + + @Override + public void deleteBookmark(String id, Context context, ProgressListener progressListener) throws Exception { + checkServerVersion(context, "1.9", "Deleting bookmarks not supported."); + + Reader reader = getReader(context, progressListener, "deleteBookmark", null, Arrays.asList("id"), Arrays.<Object>asList(id)); + try { + new ErrorParser(context).parse(reader); + } finally { + Util.close(reader); + } + } + @Override public int processOfflineSyncs(final Context context, final ProgressListener progressListener) throws Exception{ return processOfflineScrobbles(context, progressListener) + processOfflineStars(context, progressListener); diff --git a/src/github/daneren2005/dsub/service/StreamProxy.java b/src/github/daneren2005/dsub/service/StreamProxy.java index 24c1b201..900a0c92 100644 --- a/src/github/daneren2005/dsub/service/StreamProxy.java +++ b/src/github/daneren2005/dsub/service/StreamProxy.java @@ -18,6 +18,7 @@ import java.net.URLDecoder; import java.net.UnknownHostException;
import java.util.StringTokenizer;
+import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.message.BasicHttpRequest;
@@ -90,10 +91,10 @@ public class StreamProxy implements Runnable { }
private class StreamToMediaPlayerTask implements Runnable {
-
- String localPath;
+ DownloadFile downloadFile;
+ File file;
Socket client;
- int cbSkip;
+ int cbSkip = 0;
public StreamToMediaPlayerTask(Socket client) {
this.client = client;
@@ -103,9 +104,10 @@ public class StreamProxy implements Runnable { HttpRequest request = null;
InputStream is;
String firstLine;
+ BufferedReader reader = null;
try {
is = client.getInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(is), 8192);
+ reader = new BufferedReader(new InputStreamReader(is), 8192);
firstLine = reader.readLine();
} catch (IOException e) {
Log.e(TAG, "Error parsing request", e);
@@ -123,6 +125,19 @@ public class StreamProxy implements Runnable { String realUri = uri.substring(1);
Log.i(TAG, realUri);
request = new BasicHttpRequest(method, realUri);
+
+ // Get all of the headers
+ try {
+ String line;
+ while((line = reader.readLine()) != null && !"".equals(line)) {
+ String headerName = line.substring(0, line.indexOf(':'));
+ String headerValue = line.substring(line.indexOf(": ") + 2);
+ request.addHeader(headerName, headerValue);
+ }
+ } catch(IOException e) {
+ // Don't really care once past first line
+ }
+
return request;
}
@@ -135,6 +150,7 @@ public class StreamProxy implements Runnable { // Read HTTP headers
Log.i(TAG, "Processing request");
+ String localPath;
try {
localPath = URLDecoder.decode(request.getRequestLine().getUri(), Constants.UTF_8);
} catch (UnsupportedEncodingException e) {
@@ -143,11 +159,38 @@ public class StreamProxy implements Runnable { }
Log.i(TAG, "Processing request for file " + localPath);
- File file = new File(localPath);
- if (!file.exists()) {
+ downloadFile = downloadService.getCurrentPlaying();
+ File partialFile = new File(localPath);
+ if (!partialFile.equals(downloadFile.getPartialFile())) {
Log.e(TAG, "File " + localPath + " does not exist");
return false;
}
+
+ // Use either partial or complete if downloading finished while StreamProxy was idle
+ file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile();
+
+ // Try to get range requested
+ Header rangeHeader = request.getFirstHeader("Range");
+
+ if(rangeHeader != null) {
+ String range = rangeHeader.getValue();
+ int index = range.indexOf("=");
+ if(index >= 0) {
+ range = range.substring(index + 1);
+
+ index = range.indexOf("-");
+ if(index > 0) {
+ range = range.substring(0, index);
+ }
+
+ cbSkip = Integer.parseInt(range);
+
+ // Make sure to not try to read past where the file is downloaded
+ if(cbSkip >= file.length()) {
+ return false;
+ }
+ }
+ }
return true;
}
@@ -155,14 +198,30 @@ public class StreamProxy implements Runnable { @Override
public void run() {
Log.i(TAG, "Streaming song in background");
- DownloadFile downloadFile = downloadService.getCurrentPlaying();
MusicDirectory.Entry song = downloadFile.getSong();
+
+ Integer contentLength = downloadFile.getContentLength();
+ if(contentLength == null && downloadFile.isWorkDone()) {
+ contentLength = (int)file.length();
+ }
// Create HTTP header
- String headers = "HTTP/1.0 200 OK\r\n";
+ String headers;
+ if(cbSkip == 0) {
+ headers = "HTTP/1.0 200 OK\r\n";
+ } else {
+ headers = "HTTP/1.0 206 OK\r\n;";
+ headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/";
+ if(contentLength == null) {
+ headers += "*";
+ } else {
+ headers += contentLength;
+ }
+
+ Log.i(TAG, "Streaming starts from: " + cbSkip);
+ }
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
- Integer contentLength = downloadFile.getContentLength();
long fileSize;
if(contentLength == null) {
fileSize = downloadFile.getBitRate() * ((song.getDuration() != null) ? song.getDuration() : 0) * 1000 / 8;
@@ -182,50 +241,54 @@ public class StreamProxy implements Runnable { output = new BufferedOutputStream(client.getOutputStream(), 32*1024);
output.write(headers.getBytes());
- if(!downloadFile.isWorkDone()) {
- // Loop as long as there's stuff to send
- while (isRunning && !client.isClosed()) {
-
- // See if there's more to send
- File file = new File(localPath);
- int cbSentThisBatch = 0;
- if (file.exists()) {
- FileInputStream input = new FileInputStream(file);
- input.skip(cbSkip);
- int cbToSendThisBatch = input.available();
- while (cbToSendThisBatch > 0) {
- int cbToRead = Math.min(cbToSendThisBatch, buff.length);
- int cbRead = input.read(buff, 0, cbToRead);
- if (cbRead == -1) {
- break;
- }
- cbToSendThisBatch -= cbRead;
- cbToSend -= cbRead;
- output.write(buff, 0, cbRead);
- output.flush();
- cbSkip += cbRead;
- cbSentThisBatch += cbRead;
+ // Make sure to have file lock
+ downloadFile.setPlaying(true);
+
+ // Loop as long as there's stuff to send
+ while (isRunning && !client.isClosed()) {
+
+ // See if there's more to send
+ int cbSentThisBatch = 0;
+ if (file.exists()) {
+ FileInputStream input = new FileInputStream(file);
+ input.skip(cbSkip);
+ int cbToSendThisBatch = input.available();
+ while (cbToSendThisBatch > 0) {
+ int cbToRead = Math.min(cbToSendThisBatch, buff.length);
+ int cbRead = input.read(buff, 0, cbToRead);
+ if (cbRead == -1) {
+ break;
}
- input.close();
+ cbToSendThisBatch -= cbRead;
+ cbToSend -= cbRead;
+ output.write(buff, 0, cbRead);
+ output.flush();
+ cbSkip += cbRead;
+ cbSentThisBatch += cbRead;
}
+ input.close();
+ }
- // Done regardless of whether or not it thinks it is
- if(downloadFile.isWorkDone() && cbSkip >= file.length()) {
- break;
- }
+ // Done regardless of whether or not it thinks it is
+ if(downloadFile.isWorkDone() && cbSkip >= file.length()) {
+ break;
+ }
- // If we did nothing this batch, block for a second
- if (cbSentThisBatch == 0) {
- Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")");
- Thread.sleep(1000);
- }
+ // If we did nothing this batch, block for a second
+ if (cbSentThisBatch == 0) {
+ Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")");
+ Thread.sleep(1000);
}
- } else {
- Log.w(TAG, "Requesting data for completely downloaded file");
}
+
+ // Release file lock, use of stream proxy means nothing else is using it
+ downloadFile.setPlaying(false);
}
catch (SocketException socketException) {
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
+
+ // Release file lock, use of stream proxy means nothing else is using it
+ downloadFile.setPlaying(false);
}
catch (Exception e) {
Log.e(TAG, "Exception thrown from streaming task:");
diff --git a/src/github/daneren2005/dsub/service/parser/BookmarkParser.java b/src/github/daneren2005/dsub/service/parser/BookmarkParser.java new file mode 100644 index 00000000..8af509f0 --- /dev/null +++ b/src/github/daneren2005/dsub/service/parser/BookmarkParser.java @@ -0,0 +1,73 @@ +/* + This file is part of Subsonic. + + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2013 (C) Scott Jackson +*/ +package github.daneren2005.dsub.service.parser; + +import android.content.Context; +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.Bookmark; +import github.daneren2005.dsub.util.ProgressListener; +import org.xmlpull.v1.XmlPullParser; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Scott Jackson + */ +public class BookmarkParser extends MusicDirectoryEntryParser { + public BookmarkParser(Context context) { + super(context); + } + + public List<Bookmark> parse(Reader reader, ProgressListener progressListener) throws Exception { + updateProgress(progressListener, R.string.parser_reading); + init(reader); + + List<Bookmark> bookmarks = new ArrayList<Bookmark>(); + Bookmark bookmark = null; + int eventType; + + do { + eventType = nextParseEvent(); + + if (eventType == XmlPullParser.START_TAG) { + String name = getElementName(); + + if ("bookmark".equals(name)) { + bookmark = new Bookmark(); + bookmark.setChanged(get("changed")); + bookmark.setCreated(get("created")); + bookmark.setComment(get("comment")); + bookmark.setPosition(getInteger("position")); + bookmark.setUsername(get("username")); + } else if ("entry".equals(name)) { + bookmark.setEntry(parseEntry(null)); + bookmarks.add(bookmark); + } else if ("error".equals(name)) { + handleError(); + } + } + } while (eventType != XmlPullParser.END_DOCUMENT); + + validate(); + updateProgress(progressListener, R.string.parser_reading_done); + + return bookmarks; + } +} diff --git a/src/github/daneren2005/dsub/service/parser/IndexesParser.java b/src/github/daneren2005/dsub/service/parser/IndexesParser.java index 6196411d..bf5bd8b1 100644 --- a/src/github/daneren2005/dsub/service/parser/IndexesParser.java +++ b/src/github/daneren2005/dsub/service/parser/IndexesParser.java @@ -29,6 +29,7 @@ import android.content.SharedPreferences; import github.daneren2005.dsub.R; import github.daneren2005.dsub.domain.Artist; import github.daneren2005.dsub.domain.Indexes; +import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.util.ProgressListener; import android.util.Log; import github.daneren2005.dsub.util.Constants; @@ -37,7 +38,7 @@ import github.daneren2005.dsub.util.Util; /** * @author Sindre Mehus */ -public class IndexesParser extends AbstractParser { +public class IndexesParser extends MusicDirectoryEntryParser { private static final String TAG = IndexesParser.class.getSimpleName(); private Context context; @@ -55,6 +56,7 @@ public class IndexesParser extends AbstractParser { List<Artist> artists = new ArrayList<Artist>(); List<Artist> shortcuts = new ArrayList<Artist>(); + List<MusicDirectory.Entry> entries = new ArrayList<MusicDirectory.Entry>(); Long lastModified = null; int eventType; String index = "#"; @@ -91,7 +93,10 @@ public class IndexesParser extends AbstractParser { shortcut.setIndex("*"); shortcut.setStarred(get("starred") != null); shortcuts.add(shortcut); - } else if ("error".equals(name)) { + } else if("child".equals(name)) { + MusicDirectory.Entry entry = parseEntry(""); + entries.add(entry); + } else if ("error".equals(name)) { handleError(); } } @@ -115,6 +120,6 @@ public class IndexesParser extends AbstractParser { String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size()); updateProgress(progressListener, msg); - return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists); + return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists, entries); } }
\ No newline at end of file diff --git a/src/github/daneren2005/dsub/util/Constants.java b/src/github/daneren2005/dsub/util/Constants.java index fccd03cd..9940c3be 100644 --- a/src/github/daneren2005/dsub/util/Constants.java +++ b/src/github/daneren2005/dsub/util/Constants.java @@ -54,14 +54,18 @@ public final class Constants { public static final String INTENT_EXTRA_REQUEST_SEARCH = "subsonic.requestsearch"; public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit" ; public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download"; + public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view"; public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album"; public static final String INTENT_EXTRA_NAME_PODCAST_ID = "subsonic.podcast.id"; public static final String INTENT_EXTRA_NAME_PODCAST_NAME = "subsonic.podcast.name"; public static final String INTENT_EXTRA_NAME_PODCAST_DESCRIPTION = "subsonic.podcast.description"; + public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType"; + public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings"; // Notification IDs. public static final int NOTIFICATION_ID_PLAYING = 100; public static final int NOTIFICATION_ID_ERROR = 101; + public static final int NOTIFICATION_ID_DOWNLOADING = 102; // Preferences keys. public static final String PREFERENCES_KEY_SERVER_KEY = "server"; @@ -117,6 +121,10 @@ public final class Constants { public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled"; public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval"; public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi"; + public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect"; + public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget"; + public static final String PREFERENCES_KEY_PODCASTS_ENABLED = "podcastsEnabled"; + public static final String PREFERENCES_KEY_BOOKMARKS_ENABLED = "bookmarksEnabled"; public static final String OFFLINE_SCROBBLE_COUNT = "scrobbleCount"; public static final String OFFLINE_SCROBBLE_ID = "scrobbleID"; @@ -137,6 +145,8 @@ public final class Constants { public static final String FRAGMENT_LIST = "fragmentList"; public static final String FRAGMENT_LIST2 = "fragmentList2"; public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper"; + public static final String FRAGMENT_NAME = "fragmentName"; + public static final String FRAGMENT_POSITION = "fragmentPosition"; // Name of the preferences file. public static final String PREFERENCES_FILE_NAME = "github.daneren2005.dsub_preferences"; diff --git a/src/github/daneren2005/dsub/util/FileUtil.java b/src/github/daneren2005/dsub/util/FileUtil.java index 34bc82bd..d18bddb8 100644 --- a/src/github/daneren2005/dsub/util/FileUtil.java +++ b/src/github/daneren2005/dsub/util/FileUtil.java @@ -20,9 +20,9 @@ package github.daneren2005.dsub.util; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.RandomAccessFile; import java.io.Serializable; import java.util.Arrays; import java.util.SortedSet; @@ -36,10 +36,19 @@ import android.graphics.BitmapFactory; import android.os.Environment; import android.util.Log; import github.daneren2005.dsub.domain.Artist; +import github.daneren2005.dsub.domain.Genre; +import github.daneren2005.dsub.domain.Indexes; +import github.daneren2005.dsub.domain.Playlist; +import github.daneren2005.dsub.domain.PodcastChannel; import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.domain.MusicFolder; import github.daneren2005.dsub.domain.PodcastChannel; import github.daneren2005.dsub.domain.PodcastEpisode; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + /** * @author Sindre Mehus */ @@ -52,6 +61,17 @@ public class FileUtil { private static final List<String> VIDEO_FILE_EXTENSIONS = Arrays.asList("flv", "mp4", "m4v", "wmv", "avi", "mov", "mpg", "mkv"); private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u"); private static final File DEFAULT_MUSIC_DIR = createDirectory("music"); + private static final Kryo kryo = new Kryo(); + + static { + kryo.register(MusicDirectory.Entry.class); + kryo.register(Indexes.class); + kryo.register(Artist.class); + kryo.register(MusicFolder.class); + kryo.register(PodcastChannel.class); + kryo.register(Playlist.class); + kryo.register(Genre.class); + } public static File getAnySong(Context context) { File dir = getMusicDirectory(context); @@ -359,35 +379,36 @@ public class FileUtil { } public static <T extends Serializable> boolean serialize(Context context, T obj, String fileName) { - File file = new File(context.getCacheDir(), fileName); - ObjectOutputStream out = null; + Output out = null; try { - out = new ObjectOutputStream(new FileOutputStream(file)); - out.writeObject(obj); - Log.i(TAG, "Serialized object to " + file); + RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw"); + out = new Output(new FileOutputStream(file.getFD())); + kryo.writeObject(out, obj); + Log.i(TAG, "Serialized object to " + fileName); return true; } catch (Throwable x) { - Log.w(TAG, "Failed to serialize object to " + file); + Log.w(TAG, "Failed to serialize object to " + fileName); return false; } finally { Util.close(out); } } - public static <T extends Serializable> T deserialize(Context context, String fileName) { - File file = new File(context.getCacheDir(), fileName); - if (!file.exists() || !file.isFile()) { - return null; - } - - ObjectInputStream in = null; + public static <T extends Serializable> T deserialize(Context context, String fileName, Class<T> tClass) { + Input in = null; try { - in = new ObjectInputStream(new FileInputStream(file)); - T result = (T) in.readObject(); - Log.i(TAG, "Deserialized object from " + file); + RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "r"); + + in = new Input(new FileInputStream(file.getFD())); + T result = (T) kryo.readObject(in, tClass); + Log.i(TAG, "Deserialized object from " + fileName); return result; - } catch (Throwable x) { - Log.w(TAG, "Failed to deserialize object from " + file, x); + } catch(FileNotFoundException e) { + // Different error message + Log.w(TAG, "No serialization for object from " + fileName); + return null; + } catch (Throwable x) { + Log.w(TAG, "Failed to deserialize object from " + fileName, x); return null; } finally { Util.close(in); diff --git a/src/github/daneren2005/dsub/util/Util.java b/src/github/daneren2005/dsub/util/Util.java index ae575e89..ce6ba914 100644 --- a/src/github/daneren2005/dsub/util/Util.java +++ b/src/github/daneren2005/dsub/util/Util.java @@ -22,6 +22,7 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; @@ -40,6 +41,7 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.os.Environment; import android.os.Handler; +import android.support.v4.app.NotificationCompat; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; @@ -52,13 +54,14 @@ import android.widget.RemoteViews; import android.widget.TextView; import android.widget.Toast; import github.daneren2005.dsub.R; -import github.daneren2005.dsub.activity.MainActivity; +import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.domain.PlayerState; import github.daneren2005.dsub.domain.RepeatMode; import github.daneren2005.dsub.domain.Version; import github.daneren2005.dsub.provider.DSubWidgetProvider; import github.daneren2005.dsub.receiver.MediaButtonIntentReceiver; +import github.daneren2005.dsub.service.DownloadFile; import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.DownloadServiceImpl; import org.apache.http.HttpEntity; @@ -161,7 +164,7 @@ public final class Util { public static int getActiveServer(Context context) { SharedPreferences prefs = getPreferences(context); - return prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); + return prefs.getBoolean(Constants.PREFERENCES_KEY_OFFLINE, false) ? 0 : prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); } public static boolean checkServerVersion(Context context, String requiredVersion) { @@ -758,8 +761,8 @@ public final class Util { } } - public static boolean isNullOrWhiteSpace(String string) { - return string == null || string.isEmpty() || string.trim().isEmpty(); + public static boolean isNullOrWhiteSpace(String string) { + return string == null || "".equals(string) || "".equals(string.trim()); } public static boolean isNetworkConnected(Context context) { @@ -783,24 +786,44 @@ public final class Util { } public static void info(Context context, int titleId, int messageId) { - showDialog(context, android.R.drawable.ic_dialog_info, titleId, messageId); + info(context, titleId, messageId, true); } public static void info(Context context, int titleId, String message) { - showDialog(context, android.R.drawable.ic_dialog_info, titleId, message); + info(context, titleId, message, true); } public static void info(Context context, String title, String message) { - showDialog(context, android.R.drawable.ic_dialog_info, title, message); + info(context, title, message, true); + } + public static void info(Context context, int titleId, int messageId, boolean linkify) { + showDialog(context, android.R.drawable.ic_dialog_info, titleId, messageId, linkify); + } + public static void info(Context context, int titleId, String message, boolean linkify) { + showDialog(context, android.R.drawable.ic_dialog_info, titleId, message, linkify); + } + public static void info(Context context, String title, String message, boolean linkify) { + showDialog(context, android.R.drawable.ic_dialog_info, title, message, linkify); } private static void showDialog(Context context, int icon, int titleId, int messageId) { - showDialog(context, icon, context.getResources().getString(titleId), context.getResources().getString(messageId)); + showDialog(context, icon, titleId, messageId, true); } private static void showDialog(Context context, int icon, int titleId, String message) { - showDialog(context, icon, context.getResources().getString(titleId), message); + showDialog(context, icon, titleId, message, true); } private static void showDialog(Context context, int icon, String title, String message) { + showDialog(context, icon, title, message, true); + } + private static void showDialog(Context context, int icon, int titleId, int messageId, boolean linkify) { + showDialog(context, icon, context.getResources().getString(titleId), context.getResources().getString(messageId), linkify); + } + private static void showDialog(Context context, int icon, int titleId, String message, boolean linkify) { + showDialog(context, icon, context.getResources().getString(titleId), message, linkify); + } + private static void showDialog(Context context, int icon, String title, String message, boolean linkify) { SpannableString ss = new SpannableString(message); - Linkify.addLinks(ss, Linkify.ALL); + if(linkify) { + Linkify.addLinks(ss, Linkify.ALL); + } AlertDialog dialog = new AlertDialog.Builder(context) .setIcon(icon) @@ -833,10 +856,10 @@ public final class Util { setupViews(smallContentView, context, song, playing); notification.contentView = smallContentView; - Intent notificationIntent = new Intent(context, MainActivity.class); + Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0); + notification.contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); handler.post(new Runnable() { @Override @@ -846,7 +869,7 @@ public final class Util { }); // Update widget - DSubWidgetProvider.notifyInstances(context, downloadService, true); + DSubWidgetProvider.notifyInstances(context, downloadService, playing); } private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean playing){ @@ -883,39 +906,62 @@ public final class Util { if (colors.getSecond() != null) { rv.setTextColor(R.id.notification_artist, colors.getSecond()); } - - if(!playing) { - rv.setImageViewResource(R.id.control_pause, R.drawable.notification_play); - rv.setImageViewResource(R.id.control_previous, R.drawable.notification_stop); + + if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) { + rv.setImageViewResource(R.id.control_previous, playing ? R.drawable.notification_pause : R.drawable.notification_play); + rv.setImageViewResource(R.id.control_pause, R.drawable.notification_next); + rv.setImageViewResource(R.id.control_next, R.drawable.notification_close); } // Create actions for media buttons PendingIntent pendingIntent; - if(playing) { + int previous = 0, pause = 0, next = 0, close = 0; + if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) { + pause = R.id.control_previous; + next = R.id.control_pause; + close = R.id.control_next; + } else { + previous = R.id.control_previous; + pause = R.id.control_pause; + next = R.id.control_next; + } + + if(previous > 0) { Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS"); prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); - rv.setOnClickPendingIntent(R.id.control_previous, pendingIntent); - } else { + rv.setOnClickPendingIntent(previous, pendingIntent); + } + if(pause > 0) { + if(playing) { + Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE"); + pauseIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); + pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0); + rv.setOnClickPendingIntent(pause, pendingIntent); + } else { + Intent prevIntent = new Intent("KEYCODE_MEDIA_START"); + prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY)); + pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); + rv.setOnClickPendingIntent(pause, pendingIntent); + } + } + if(next > 0) { + Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT"); + nextIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); + pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0); + rv.setOnClickPendingIntent(next, pendingIntent); + } + if(close > 0) { Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP"); prevIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP)); pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); - rv.setOnClickPendingIntent(R.id.control_previous, pendingIntent); + rv.setOnClickPendingIntent(close, pendingIntent); } - - Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE"); - pauseIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); - pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); - pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0); - rv.setOnClickPendingIntent(R.id.control_pause, pendingIntent); - - Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT"); - nextIntent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); - nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); - pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0); - rv.setOnClickPendingIntent(R.id.control_next, pendingIntent); } public static void hidePlayingNotification(final Context context, final DownloadServiceImpl downloadService, Handler handler) { @@ -930,6 +976,30 @@ public final class Util { // Update widget DSubWidgetProvider.notifyInstances(context, downloadService, false); } + + public static void showDownloadingNotification(final Context context, DownloadFile file, int size) { + NotificationCompat.Builder builder; + builder = new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.stat_notify_download) + .setContentTitle("Downloading " + size + " songs") + .setContentText("Current: " + (file != null ? file.getSong().getTitle() : "none")) + .setProgress(10, 5, true) + .setOngoing(true); + + Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class); + notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); + notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true); + notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + builder.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)); + + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.notify(Constants.NOTIFICATION_ID_DOWNLOADING, builder.build()); + + } + public static void hideDownloadingNotification(final Context context) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.NOTIFICATION_ID_DOWNLOADING); + } public static void sleepQuietly(long millis) { try { diff --git a/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java b/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java index ddaa9f43..9826851d 100644 --- a/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java +++ b/src/github/daneren2005/dsub/util/compat/RemoteControlClientHelper.java @@ -10,6 +10,8 @@ public abstract class RemoteControlClientHelper { public static RemoteControlClientHelper createInstance() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { return new RemoteControlClientBase(); + } else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + return new RemoteControlClientJB(); } else { return new RemoteControlClientICS(); } diff --git a/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java b/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java index 8707ecb5..a47ecab5 100644 --- a/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java +++ b/src/github/daneren2005/dsub/util/compat/RemoteControlClientICS.java @@ -10,16 +10,14 @@ import android.content.Intent; import android.media.AudioManager; import android.media.MediaMetadataRetriever; import android.media.RemoteControlClient; -import android.os.Build; import github.daneren2005.dsub.activity.SubsonicActivity; import github.daneren2005.dsub.service.DownloadService; @TargetApi(14) public class RemoteControlClientICS extends RemoteControlClientHelper { - - private RemoteControlClient mRemoteControl; - private ImageLoader imageLoader; - private DownloadService downloadService; + protected RemoteControlClient mRemoteControl; + protected ImageLoader imageLoader; + protected DownloadService downloadService; public void register(final Context context, final ComponentName mediaButtonReceiverComponent) { downloadService = (DownloadService) context; @@ -37,21 +35,6 @@ public class RemoteControlClientICS extends RemoteControlClientHelper { mRemoteControl.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED); mRemoteControl.setTransportControlFlags(getTransportFlags()); imageLoader = SubsonicActivity.getStaticImageLoader(context); - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - mRemoteControl.setOnGetPlaybackPositionListener(new RemoteControlClient.OnGetPlaybackPositionListener() { - @Override - public long onGetPlaybackPosition() { - return downloadService.getPlayerPosition(); - } - }); - mRemoteControl.setPlaybackPositionUpdateListener(new RemoteControlClient.OnPlaybackPositionUpdateListener() { - @Override - public void onPlaybackPositionUpdate(long newPosition) { - downloadService.seekTo((int) newPosition); - } - }); - } } public void unregister(final Context context) { @@ -62,15 +45,7 @@ public class RemoteControlClientICS extends RemoteControlClientHelper { } public void setPlaybackState(final int state) { - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - long position = -1; - if(state == RemoteControlClient.PLAYSTATE_PLAYING || state == RemoteControlClient.PLAYSTATE_PAUSED) { - position = downloadService.getPlayerPosition(); - } - mRemoteControl.setPlaybackState(state, position, 1.0f); - } else { - mRemoteControl.setPlaybackState(state); - } + mRemoteControl.setPlaybackState(state); } public void updateMetadata(final Context context, final MusicDirectory.Entry currentSong) { @@ -99,19 +74,13 @@ public class RemoteControlClientICS extends RemoteControlClientHelper { } } - private int getTransportFlags() { - int flags = RemoteControlClient.FLAG_KEY_MEDIA_PLAY | + protected int getTransportFlags() { + return RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT | RemoteControlClient.FLAG_KEY_MEDIA_STOP; - - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - flags = flags | RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE; - } - - return flags; } } diff --git a/src/github/daneren2005/dsub/util/compat/RemoteControlClientJB.java b/src/github/daneren2005/dsub/util/compat/RemoteControlClientJB.java new file mode 100644 index 00000000..c499f6c0 --- /dev/null +++ b/src/github/daneren2005/dsub/util/compat/RemoteControlClientJB.java @@ -0,0 +1,50 @@ +package github.daneren2005.dsub.util.compat; + +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.util.ImageLoader; +import android.annotation.TargetApi; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaMetadataRetriever; +import android.media.RemoteControlClient; +import github.daneren2005.dsub.activity.SubsonicActivity; +import github.daneren2005.dsub.service.DownloadService; + +@TargetApi(18) +public class RemoteControlClientJB extends RemoteControlClientICS { + @Override + public void register(final Context context, final ComponentName mediaButtonReceiverComponent) { + super.register(context, mediaButtonReceiverComponent); + + mRemoteControl.setOnGetPlaybackPositionListener(new RemoteControlClient.OnGetPlaybackPositionListener() { + @Override + public long onGetPlaybackPosition() { + return downloadService.getPlayerPosition(); + } + }); + mRemoteControl.setPlaybackPositionUpdateListener(new RemoteControlClient.OnPlaybackPositionUpdateListener() { + @Override + public void onPlaybackPositionUpdate(long newPosition) { + downloadService.seekTo((int) newPosition); + } + }); + } + + @Override + public void setPlaybackState(final int state) { + long position = -1; + if(state == RemoteControlClient.PLAYSTATE_PLAYING || state == RemoteControlClient.PLAYSTATE_PAUSED) { + position = downloadService.getPlayerPosition(); + } + mRemoteControl.setPlaybackState(state, position, 1.0f); + } + + @Override + protected int getTransportFlags() { + return super.getTransportFlags() | RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE; + } + +} diff --git a/src/github/daneren2005/dsub/view/ArtistAdapter.java b/src/github/daneren2005/dsub/view/ArtistAdapter.java index ff66f396..1998eaed 100644 --- a/src/github/daneren2005/dsub/view/ArtistAdapter.java +++ b/src/github/daneren2005/dsub/view/ArtistAdapter.java @@ -42,7 +42,7 @@ public class ArtistAdapter extends ArrayAdapter<Artist> implements SectionIndexe private final Integer[] positions; public ArtistAdapter(Context activity, List<Artist> artists) { - super(activity, R.layout.artist_list_item, artists); + super(activity, R.layout.basic_list_item, artists); this.activity = activity; Set<String> sectionSet = new LinkedHashSet<String>(30); diff --git a/src/github/daneren2005/dsub/view/ArtistEntryView.java b/src/github/daneren2005/dsub/view/ArtistEntryView.java index 1d3993a0..958b4b87 100644 --- a/src/github/daneren2005/dsub/view/ArtistEntryView.java +++ b/src/github/daneren2005/dsub/view/ArtistEntryView.java @@ -48,12 +48,12 @@ public class ArtistEntryView extends UpdateView { public ArtistEntryView(Context context) {
super(context);
this.context = context;
- LayoutInflater.from(context).inflate(R.layout.artist_list_item, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
- titleView = (TextView) findViewById(R.id.artist_name);
- starButton = (ImageButton) findViewById(R.id.artist_star);
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
starButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.artist_more);
+ moreButton = (ImageView) findViewById(R.id.item_more);
moreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.showContextMenu();
diff --git a/src/github/daneren2005/dsub/view/ArtistView.java b/src/github/daneren2005/dsub/view/ArtistView.java index 2a284905..6f54e800 100644 --- a/src/github/daneren2005/dsub/view/ArtistView.java +++ b/src/github/daneren2005/dsub/view/ArtistView.java @@ -47,12 +47,12 @@ public class ArtistView extends UpdateView { public ArtistView(Context context) {
super(context);
this.context = context;
- LayoutInflater.from(context).inflate(R.layout.artist_list_item, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
- titleView = (TextView) findViewById(R.id.artist_name);
- starButton = (ImageButton) findViewById(R.id.artist_star);
- starButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.artist_more);
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
+ starButton.setFocusable(false);
+ moreButton = (ImageView) findViewById(R.id.item_more);
moreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.showContextMenu();
diff --git a/src/github/daneren2005/dsub/view/BookmarkAdapter.java b/src/github/daneren2005/dsub/view/BookmarkAdapter.java new file mode 100644 index 00000000..bcddc574 --- /dev/null +++ b/src/github/daneren2005/dsub/view/BookmarkAdapter.java @@ -0,0 +1,62 @@ +/* + This file is part of Subsonic. + + Subsonic is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Subsonic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Subsonic. If not, see <http://www.gnu.org/licenses/>. + + Copyright 2010 (C) Sindre Mehus +*/ + +package github.daneren2005.dsub.view; + +import android.content.Context; +import android.util.Log; +import java.util.List; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import github.daneren2005.dsub.R; +import github.daneren2005.dsub.domain.Bookmark; +import github.daneren2005.dsub.domain.MusicDirectory; +import github.daneren2005.dsub.util.Util; + +public class BookmarkAdapter extends ArrayAdapter<Bookmark> { + private final static String TAG = BookmarkAdapter.class.getSimpleName(); + private Context activity; + + public BookmarkAdapter(Context activity, List<Bookmark> bookmarks) { + super(activity, android.R.layout.simple_list_item_1, bookmarks); + this.activity = activity; + } + + public View getView(int position, View convertView, ViewGroup parent) { + Bookmark bookmark = getItem(position); + MusicDirectory.Entry entry = bookmark.getEntry(); + SongView view; + if (convertView != null) { + view = (SongView) convertView; + } else { + view = new SongView(activity); + } + view.setObject(entry, false); + + // Add current position to duration + TextView durationTextView = (TextView) view.findViewById(R.id.song_duration); + String duration = durationTextView.getText().toString(); + durationTextView.setText(Util.formatDuration(bookmark.getPosition() / 1000) + " / " + duration); + + return view; + } +} diff --git a/src/github/daneren2005/dsub/view/DrawerAdapter.java b/src/github/daneren2005/dsub/view/DrawerAdapter.java new file mode 100644 index 00000000..d3639373 --- /dev/null +++ b/src/github/daneren2005/dsub/view/DrawerAdapter.java @@ -0,0 +1,68 @@ +/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+*/
+package github.daneren2005.dsub.view;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+import github.daneren2005.dsub.R;
+
+/**
+ * Created by Scott on 11/8/13.
+ */
+public class DrawerAdapter extends ArrayAdapter<String> {
+ private static String TAG = DrawerAdapter.class.getSimpleName();
+ private Context context;
+ private List<String> items;
+ private List<Integer> icons;
+
+ public DrawerAdapter(Context context, List<String> items, List<Integer> icons) {
+ super(context, R.layout.drawer_list_item, items);
+
+ this.context = context;
+ this.items = items;
+ this.icons = icons;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ String item = items.get(position);
+ Integer icon = icons.get(position);
+
+ if(convertView == null) {
+ convertView = LayoutInflater.from(context).inflate(R.layout.drawer_list_item, null);
+ }
+
+ TextView textView = (TextView) convertView.findViewById(R.id.drawer_name);
+ textView.setText(item);
+ ImageView iconView = (ImageView) convertView.findViewById(R.id.drawer_icon);
+ Log.d(TAG, "icon: " + icon);
+ iconView.setImageResource(icon);
+
+ return convertView;
+ }
+}
diff --git a/src/github/daneren2005/dsub/view/ErrorDialog.java b/src/github/daneren2005/dsub/view/ErrorDialog.java index e9f25a2d..246b3756 100644 --- a/src/github/daneren2005/dsub/view/ErrorDialog.java +++ b/src/github/daneren2005/dsub/view/ErrorDialog.java @@ -22,8 +22,9 @@ import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; -import github.daneren2005.dsub.activity.MainActivity; + import github.daneren2005.dsub.R; +import github.daneren2005.dsub.activity.SubsonicFragmentActivity; import github.daneren2005.dsub.util.Util; /** @@ -59,11 +60,15 @@ public class ErrorDialog { } }); - builder.create().show(); + try { + builder.create().show(); + } catch(Exception e) { + // Don't care, just means no activity to attach to + } } private void restart(Activity context) { - Intent intent = new Intent(context, MainActivity.class); + Intent intent = new Intent(context, SubsonicFragmentActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Util.startActivityWithoutTransition(context, intent); } diff --git a/src/github/daneren2005/dsub/view/GenreView.java b/src/github/daneren2005/dsub/view/GenreView.java index 69456c28..6a8e04ef 100644 --- a/src/github/daneren2005/dsub/view/GenreView.java +++ b/src/github/daneren2005/dsub/view/GenreView.java @@ -34,12 +34,13 @@ public class GenreView extends UpdateView { public GenreView(Context context) {
super(context);
- LayoutInflater.from(context).inflate(R.layout.artist_list_item, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
- titleView = (TextView) findViewById(R.id.artist_name);
- starButton = (ImageButton) findViewById(R.id.artist_star);
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
starButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.artist_more);
+ moreButton = (ImageView) findViewById(R.id.item_more);
+ moreButton.setVisibility(View.GONE);
moreButton.setClickable(false);
}
diff --git a/src/github/daneren2005/dsub/view/PlaylistAdapter.java b/src/github/daneren2005/dsub/view/PlaylistAdapter.java index f25996dd..ff0294b7 100644 --- a/src/github/daneren2005/dsub/view/PlaylistAdapter.java +++ b/src/github/daneren2005/dsub/view/PlaylistAdapter.java @@ -36,7 +36,7 @@ public class PlaylistAdapter extends ArrayAdapter<Playlist> { private final Context activity; public PlaylistAdapter(Context activity, List<Playlist> Playlists) { - super(activity, R.layout.playlist_list_item, Playlists); + super(activity, R.layout.basic_list_item, Playlists); this.activity = activity; } diff --git a/src/github/daneren2005/dsub/view/PlaylistView.java b/src/github/daneren2005/dsub/view/PlaylistView.java index 31332b22..c75f8ad7 100644 --- a/src/github/daneren2005/dsub/view/PlaylistView.java +++ b/src/github/daneren2005/dsub/view/PlaylistView.java @@ -21,6 +21,7 @@ package github.daneren2005.dsub.view; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import github.daneren2005.dsub.R;
@@ -39,17 +40,18 @@ public class PlaylistView extends UpdateView { private Context context;
private Playlist playlist;
- private File file;
private TextView titleView;
public PlaylistView(Context context) {
super(context);
this.context = context;
- LayoutInflater.from(context).inflate(R.layout.playlist_list_item, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
- titleView = (TextView) findViewById(R.id.playlist_name);
- moreButton = (ImageView) findViewById(R.id.playlist_more);
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
+ starButton.setFocusable(false);
+ moreButton = (ImageView) findViewById(R.id.item_more);
moreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.showContextMenu();
@@ -60,11 +62,5 @@ public class PlaylistView extends UpdateView { protected void setObjectImpl(Object obj) {
this.playlist = (Playlist) obj;
titleView.setText(playlist.getName());
- file = FileUtil.getPlaylistFile(Util.getServerName(context), playlist.getName());
- }
-
- @Override
- protected void updateBackground() {
- exists = file.exists();
}
}
diff --git a/src/github/daneren2005/dsub/view/PodcastChannelView.java b/src/github/daneren2005/dsub/view/PodcastChannelView.java index 5b9225d7..9ad78d1c 100644 --- a/src/github/daneren2005/dsub/view/PodcastChannelView.java +++ b/src/github/daneren2005/dsub/view/PodcastChannelView.java @@ -41,12 +41,12 @@ public class PodcastChannelView extends UpdateView { public PodcastChannelView(Context context) {
super(context);
this.context = context;
- LayoutInflater.from(context).inflate(R.layout.artist_list_item, this, true);
+ LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true);
- titleView = (TextView) findViewById(R.id.artist_name);
- starButton = (ImageButton) findViewById(R.id.artist_star);
+ titleView = (TextView) findViewById(R.id.item_name);
+ starButton = (ImageButton) findViewById(R.id.item_star);
starButton.setFocusable(false);
- moreButton = (ImageView) findViewById(R.id.artist_more);
+ moreButton = (ImageView) findViewById(R.id.item_more);
moreButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
v.showContextMenu();
diff --git a/src/github/daneren2005/dsub/view/SongView.java b/src/github/daneren2005/dsub/view/SongView.java index 3106d38c..c256495b 100644 --- a/src/github/daneren2005/dsub/view/SongView.java +++ b/src/github/daneren2005/dsub/view/SongView.java @@ -19,6 +19,7 @@ package github.daneren2005.dsub.view; import android.content.Context; +import android.content.res.TypedArray; import android.media.MediaMetadataRetriever; import android.util.Log; import android.view.LayoutInflater; @@ -42,8 +43,7 @@ import java.text.DateFormat; */ public class SongView extends UpdateView implements Checkable { private static final String TAG = SongView.class.getSimpleName(); - - private Context context; + private MusicDirectory.Entry song; private CheckedTextView checkedTextView; @@ -51,22 +51,23 @@ public class SongView extends UpdateView implements Checkable { private TextView artistTextView; private TextView durationTextView; private TextView statusTextView; + private ImageView statusImageView; private DownloadService downloadService; private long revision = -1; private DownloadFile downloadFile; private boolean playing = false; - private int rightImage = 0; + private boolean rightImage = false; private int moreImage = 0; private boolean isWorkDone = false; private boolean isSaved = false; private File partialFile; private boolean partialFileExists = false; + private boolean loaded = false; public SongView(Context context) { super(context); - this.context = context; LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true); checkedTextView = (CheckedTextView) findViewById(R.id.song_check); @@ -74,6 +75,7 @@ public class SongView extends UpdateView implements Checkable { artistTextView = (TextView) findViewById(R.id.song_artist); durationTextView = (TextView) findViewById(R.id.song_duration); statusTextView = (TextView) findViewById(R.id.song_status); + statusImageView = (ImageView) findViewById(R.id.song_status_icon); starButton = (ImageButton) findViewById(R.id.song_star); starButton.setFocusable(false); moreButton = (ImageView) findViewById(R.id.artist_more); @@ -142,6 +144,7 @@ public class SongView extends UpdateView implements Checkable { checkedTextView.setVisibility(checkable && !song.isVideo() ? View.VISIBLE : View.GONE); revision = -1; + loaded = false; } @Override @@ -164,10 +167,19 @@ public class SongView extends UpdateView implements Checkable { partialFile = downloadFile.getPartialFile(); partialFileExists = partialFile.exists(); isStarred = song.isStarred(); + + // Check if needs to load metadata: check against all fields that we know are null in offline mode + if(song.getBitRate() == null && song.getDuration() == null && song.getDiscNumber() == null && isWorkDone) { + song.loadMetadata(downloadFile.getCompleteFile()); + loaded = true; + } } @Override protected void update() { + if(loaded) { + setObjectImpl(song, checkedTextView.getVisibility() == View.VISIBLE); + } if (downloadService == null) { return; } @@ -184,34 +196,39 @@ public class SongView extends UpdateView implements Checkable { } } - int rightImage = 0; if (isWorkDone) { - int moreImage = isSaved ? R.drawable.list_item_more_saved : R.drawable.list_item_more_shaded; + int moreImage = isSaved ? R.drawable.download_pinned : R.drawable.download_cached; if(moreImage != this.moreImage) { moreButton.setImageResource(moreImage); this.moreImage = moreImage; } - } else if(this.moreImage != R.drawable.list_item_more) { - moreButton.setImageResource(R.drawable.list_item_more); - this.moreImage = R.drawable.list_item_more; + } else if(true) { + int[] attrs = new int[] {R.attr.download_none}; + TypedArray typedArray = context.obtainStyledAttributes(attrs); + moreButton.setImageResource(typedArray.getResourceId(0, 0)); + typedArray.recycle(); + this.moreImage = R.drawable.download_none_light; } if (downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && partialFileExists) { statusTextView.setText(Util.formatLocalizedBytes(partialFile.length(), getContext())); - rightImage = R.drawable.downloading; - } else if(this.rightImage != 0) { + if(!rightImage) { + statusImageView.setVisibility(View.VISIBLE); + rightImage = true; + } + } else if(rightImage) { statusTextView.setText(null); + statusImageView.setVisibility(View.GONE); + rightImage = false; } - if(this.rightImage != rightImage) { - statusTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, rightImage, 0); - this.rightImage = rightImage; - } boolean playing = downloadService.getCurrentPlaying() == downloadFile; if (playing) { if(!this.playing) { this.playing = playing; - titleTextView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.stat_notify_playing, 0, 0, 0); + int[] attrs = new int[] {R.attr.media_button_start}; + TypedArray typedArray = context.obtainStyledAttributes(attrs); + titleTextView.setCompoundDrawablesWithIntrinsicBounds(typedArray.getResourceId(0, 0), 0, 0, 0); } } else { if(this.playing) { diff --git a/src/github/daneren2005/dsub/view/UpdateView.java b/src/github/daneren2005/dsub/view/UpdateView.java index 48d9cf94..05b17417 100644 --- a/src/github/daneren2005/dsub/view/UpdateView.java +++ b/src/github/daneren2005/dsub/view/UpdateView.java @@ -19,6 +19,7 @@ package github.daneren2005.dsub.view;
import android.content.Context;
+import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -41,7 +42,8 @@ public class UpdateView extends LinearLayout { private static Handler backgroundHandler;
private static Handler uiHandler;
private static Runnable updateRunnable;
-
+
+ protected Context context;
protected ImageButton starButton;
protected ImageView moreButton;
@@ -52,6 +54,7 @@ public class UpdateView extends LinearLayout { public UpdateView(Context context) {
super(context);
+ this.context = context;
setLayoutParams(new AbsListView.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
@@ -99,6 +102,8 @@ public class UpdateView extends LinearLayout { }
uiHandler = new Handler();
+ // Needed so handler is never null until thread creates it
+ backgroundHandler = uiHandler;
updateRunnable = new Runnable() {
@Override
public void run() {
@@ -166,12 +171,14 @@ public class UpdateView extends LinearLayout { if(moreButton != null) {
if(exists) {
if(!shaded) {
- moreButton.setImageResource(R.drawable.list_item_more_shaded);
+ moreButton.setImageResource(R.drawable.download_cached);
shaded = true;
}
} else {
if(shaded) {
- moreButton.setImageResource(R.drawable.list_item_more);
+ int[] attrs = new int[] {R.attr.download_none};
+ TypedArray typedArray = context.obtainStyledAttributes(attrs);
+ moreButton.setImageResource(typedArray.getResourceId(0, 0));
shaded = false;
}
}
|