aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml4
-rw-r--r--README17
-rw-r--r--res/drawable-hdpi/download_cached.pngbin1172 -> 982 bytes
-rw-r--r--res/drawable-hdpi/download_pinned.pngbin1112 -> 992 bytes
-rw-r--r--res/drawable-hdpi/ic_drawer.pngbin2829 -> 113 bytes
-rw-r--r--res/drawable-hdpi/ic_stat_star.pngbin3611 -> 826 bytes
-rw-r--r--res/drawable-hdpi/launch.pngbin23597 -> 7496 bytes
-rw-r--r--res/drawable-hdpi/unknown_album_large.pngbin48194 -> 41908 bytes
-rw-r--r--res/drawable-mdpi/download_cached.pngbin824 -> 704 bytes
-rw-r--r--res/drawable-mdpi/download_pinned.pngbin841 -> 673 bytes
-rw-r--r--res/drawable-mdpi/ic_drawer.pngbin2820 -> 104 bytes
-rw-r--r--res/drawable-mdpi/launch.pngbin12053 -> 4077 bytes
-rw-r--r--res/drawable-xhdpi/download_cached.pngbin1721 -> 1300 bytes
-rw-r--r--res/drawable-xhdpi/download_pinned.pngbin1750 -> 1278 bytes
-rw-r--r--res/drawable-xhdpi/ic_drawer.pngbin2836 -> 120 bytes
-rw-r--r--res/drawable-xhdpi/launch.pngbin39749 -> 10916 bytes
-rw-r--r--res/drawable-xxhdpi/download_cached.pngbin0 -> 1906 bytes
-rw-r--r--res/drawable-xxhdpi/download_pinned.pngbin0 -> 1899 bytes
-rw-r--r--res/drawable-xxhdpi/launch.pngbin85882 -> 20218 bytes
-rw-r--r--res/layout-port/download.xml2
-rw-r--r--res/layout/jukebox_volume.xml2
-rw-r--r--res/layout/notification_expanded.xml39
-rw-r--r--res/menu/select_artist_context.xml6
-rw-r--r--res/raw/changelog.xml12
-rw-r--r--res/values-es/strings.xml24
-rw-r--r--res/values/strings.xml4
-rw-r--r--res/xml/appwidget4x4.xml4
-rw-r--r--res/xml/settings.xml6
-rw-r--r--src/github/daneren2005/dsub/activity/SubsonicActivity.java7
-rw-r--r--src/github/daneren2005/dsub/domain/Version.java2
-rw-r--r--src/github/daneren2005/dsub/fragments/DownloadFragment.java28
-rw-r--r--src/github/daneren2005/dsub/fragments/SearchFragment.java14
-rw-r--r--src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java4
-rw-r--r--src/github/daneren2005/dsub/fragments/SubsonicFragment.java13
-rw-r--r--src/github/daneren2005/dsub/service/parser/MusicDirectoryParser.java6
-rw-r--r--src/github/daneren2005/dsub/service/parser/PodcastEntryParser.java2
-rw-r--r--src/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--src/github/daneren2005/dsub/util/ShufflePlayBuffer.java33
38 files changed, 179 insertions, 51 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 207c2afd..58e18fef 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="69"
- android:versionName="4.2.0">
+ android:versionCode="71"
+ android:versionName="4.2.2">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
diff --git a/README b/README
index 4e716c5a..962dc284 100644
--- a/README
+++ b/README
@@ -11,15 +11,20 @@ Replace the file DragSortListView/library/libs/android-support-v4.jar with the o
Roadmap of major planned features in rough order that I plan to work on them in (little features get sprinkled in wherever):
-UI Redesign
- -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
-Mark podcasts as 'offline', download new episodes only
+RemoteControl
+ -Chromecast
+ -DLNA/UpNP Client
+ -DLNA/UpNP Renderer
New Tabs
-Admin functions
-Change your password
- -Create/delete users if admin
+ -Create/delete users if admin
+ -Sharing tab
+ -Internet Radio tab
+HLS Video
+ -Display video where album art is currently (double tap to fullscreen)
+ -Videos can play inline with songs
+
diff --git a/res/drawable-hdpi/download_cached.png b/res/drawable-hdpi/download_cached.png
index d935cb2c..56bfc0e1 100644
--- a/res/drawable-hdpi/download_cached.png
+++ b/res/drawable-hdpi/download_cached.png
Binary files differ
diff --git a/res/drawable-hdpi/download_pinned.png b/res/drawable-hdpi/download_pinned.png
index b5b6dfb1..711c7704 100644
--- a/res/drawable-hdpi/download_pinned.png
+++ b/res/drawable-hdpi/download_pinned.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_drawer.png b/res/drawable-hdpi/ic_drawer.png
index c59f601c..eb90af58 100644
--- a/res/drawable-hdpi/ic_drawer.png
+++ b/res/drawable-hdpi/ic_drawer.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_stat_star.png b/res/drawable-hdpi/ic_stat_star.png
index b16e803c..67ad40f5 100644
--- a/res/drawable-hdpi/ic_stat_star.png
+++ b/res/drawable-hdpi/ic_stat_star.png
Binary files differ
diff --git a/res/drawable-hdpi/launch.png b/res/drawable-hdpi/launch.png
index 9caa6675..0c77b9b4 100644
--- a/res/drawable-hdpi/launch.png
+++ b/res/drawable-hdpi/launch.png
Binary files differ
diff --git a/res/drawable-hdpi/unknown_album_large.png b/res/drawable-hdpi/unknown_album_large.png
index bd9c6cc9..42c28c7d 100644
--- a/res/drawable-hdpi/unknown_album_large.png
+++ b/res/drawable-hdpi/unknown_album_large.png
Binary files differ
diff --git a/res/drawable-mdpi/download_cached.png b/res/drawable-mdpi/download_cached.png
index fa02cc7c..2b5d33d1 100644
--- a/res/drawable-mdpi/download_cached.png
+++ b/res/drawable-mdpi/download_cached.png
Binary files differ
diff --git a/res/drawable-mdpi/download_pinned.png b/res/drawable-mdpi/download_pinned.png
index 8e6e8e7a..ce3fe064 100644
--- a/res/drawable-mdpi/download_pinned.png
+++ b/res/drawable-mdpi/download_pinned.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_drawer.png b/res/drawable-mdpi/ic_drawer.png
index 1ed2c56e..1681d12c 100644
--- a/res/drawable-mdpi/ic_drawer.png
+++ b/res/drawable-mdpi/ic_drawer.png
Binary files differ
diff --git a/res/drawable-mdpi/launch.png b/res/drawable-mdpi/launch.png
index 22e094eb..88887e94 100644
--- a/res/drawable-mdpi/launch.png
+++ b/res/drawable-mdpi/launch.png
Binary files differ
diff --git a/res/drawable-xhdpi/download_cached.png b/res/drawable-xhdpi/download_cached.png
index 1ef7c805..70de6f04 100644
--- a/res/drawable-xhdpi/download_cached.png
+++ b/res/drawable-xhdpi/download_cached.png
Binary files differ
diff --git a/res/drawable-xhdpi/download_pinned.png b/res/drawable-xhdpi/download_pinned.png
index 09eb6ffb..79bf92e3 100644
--- a/res/drawable-xhdpi/download_pinned.png
+++ b/res/drawable-xhdpi/download_pinned.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_drawer.png b/res/drawable-xhdpi/ic_drawer.png
index a5fa74de..daba1451 100644
--- a/res/drawable-xhdpi/ic_drawer.png
+++ b/res/drawable-xhdpi/ic_drawer.png
Binary files differ
diff --git a/res/drawable-xhdpi/launch.png b/res/drawable-xhdpi/launch.png
index f73729d0..0f647dfa 100644
--- a/res/drawable-xhdpi/launch.png
+++ b/res/drawable-xhdpi/launch.png
Binary files differ
diff --git a/res/drawable-xxhdpi/download_cached.png b/res/drawable-xxhdpi/download_cached.png
new file mode 100644
index 00000000..243c570e
--- /dev/null
+++ b/res/drawable-xxhdpi/download_cached.png
Binary files differ
diff --git a/res/drawable-xxhdpi/download_pinned.png b/res/drawable-xxhdpi/download_pinned.png
new file mode 100644
index 00000000..354ac23d
--- /dev/null
+++ b/res/drawable-xxhdpi/download_pinned.png
Binary files differ
diff --git a/res/drawable-xxhdpi/launch.png b/res/drawable-xxhdpi/launch.png
index b067bd9f..cae4f99a 100644
--- a/res/drawable-xxhdpi/launch.png
+++ b/res/drawable-xxhdpi/launch.png
Binary files differ
diff --git a/res/layout-port/download.xml b/res/layout-port/download.xml
index 38ab069f..a70160a1 100644
--- a/res/layout-port/download.xml
+++ b/res/layout-port/download.xml
@@ -35,7 +35,7 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
- android:scaleType="centerCrop"/>
+ android:scaleType="fitCenter"/>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/download_overlay_buttons"
diff --git a/res/layout/jukebox_volume.xml b/res/layout/jukebox_volume.xml
index fd718326..0c49f634 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="?attr/volume"/>
+ android:src="@drawable/ic_action_volume_dark"/>
<SeekBar
android:layout_height="wrap_content"
diff --git a/res/layout/notification_expanded.xml b/res/layout/notification_expanded.xml
index e2246506..3e2c7fcd 100644
--- a/res/layout/notification_expanded.xml
+++ b/res/layout/notification_expanded.xml
@@ -58,40 +58,41 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center|fill"
- android:gravity="center_horizontal"
- android:orientation="horizontal" >
+ android:orientation="horizontal"
+ android:showDividers="middle"
+ android:divider="?android:listDivider">
<ImageButton
android:id="@+id/control_previous"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
android:layout_gravity="center"
- android:layout_weight="0.0"
+ android:layout_weight="1"
+ android:padding="10dip"
android:background="@drawable/btn_bg"
- android:scaleType="fitXY"
+ android:scaleType="fitCenter"
android:src="@drawable/notification_previous" />
<ImageButton
android:id="@+id/control_pause"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:layout_weight="0.0"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="10dip"
android:background="@drawable/btn_bg"
- android:scaleType="fitXY"
+ android:scaleType="fitCenter"
android:src="@drawable/notification_pause" />
<ImageButton
android:id="@+id/control_next"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_weight="0.0"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="10dip"
android:background="@drawable/btn_bg"
- android:scaleType="fitXY"
+ android:scaleType="fitCenter"
android:src="@drawable/notification_next" />
</LinearLayout>
diff --git a/res/menu/select_artist_context.xml b/res/menu/select_artist_context.xml
index d7a5c6ac..e35cae9e 100644
--- a/res/menu/select_artist_context.xml
+++ b/res/menu/select_artist_context.xml
@@ -30,4 +30,10 @@
<item
android:id="@+id/artist_menu_delete"
android:title="@string/common.delete"/>
+
+ <group android:id="@+id/server_1_10">
+ <item
+ android:id="@+id/artist_menu_star"
+ android:title="@string/common.star"/>
+ </group>
</menu>
diff --git a/res/raw/changelog.xml b/res/raw/changelog.xml
index 819263ac..9a080bf1 100644
--- a/res/raw/changelog.xml
+++ b/res/raw/changelog.xml
@@ -1,5 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
+ <release version="4.2.2" versioncode="71" releasedate="11/22/2013">
+ <change>Added starring for artists for 4.9+ Servers</change>
+ <change>Add ability to place large widget on lockscreen for Android 4.2+</change>
+ <change>Option to use app's custom sorting (on by default)</change>
+ <change>Lots of tablet UI enhancements</change>
+ <change>Updated translations</change>
+ <change>Tons of bug fixes</change>
+ </release>
+ <release version="4.2.1" versioncode="70" releasedate="11/15/2013">
+ <change>Fixed crash when going to download list with Screen On = true</change>
+ <change>Fixed crash when changing volume in RC mode</change>
+ </release>
<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>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 594ff0b9..2da129d6 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -22,6 +22,7 @@
<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="common.empty">No se ha encontrado nada</string>
<string name="button_bar.home">Inicio</string>
<string name="button_bar.browse">Biblioteca</string>
@@ -29,6 +30,7 @@
<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.bookmarks">Marcadores</string>
<string name="button_bar.chat">Chat</string>
<string name="main.welcome_title">Bienvenido!</string>
@@ -189,6 +191,8 @@
<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="download.save_bookmark_title">Crear marcador</string>
+ <string name="download.save_bookmark">Marcador creado</string>
<string name="starring_content_starred">Marcado con estrella \"%s\"</string>
<string name="starring_content_unstarred">Sin marca de estrella \"%s\"</string>
@@ -198,6 +202,13 @@
<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="bookmark.delete">Borrar marcador</string>
+ <string name="bookmark.deleted">Borrado marcador para \"%s\"</string>
+ <string name="bookmark.deleted_error">Error al borrar el marcador para \"%s\"</string>
+ <string name="bookmark.details">Canción: %1$s
+ \nComentario: %2$s
+ \nPosición: %3$s</string>
<string name="song_details.all">%1$s %2$s</string>
<string name="song_details.kbps">%d kbps</string>
@@ -311,6 +322,11 @@
<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.disconnect_pause_title">Pausar al desconectar</string>
+ <string name="settings.disconnect_pause_both">Pausar en todos los casos</string>
+ <string name="settings.disconnect_pause_headphone">Pausar sólo con auriculares</string>
+ <string name="settings.disconnect_pause_bluetooth">Pausar sólo en bluetooth</string>
+ <string name="settings.disconnect_pause_neither">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>
@@ -324,6 +340,14 @@
<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="settings.cache_screen_title">Caché/Red</string>
+ <string name="settings.playback_title">Reproducción</string>
+ <string name="settings.hide_widget_title">Ocultar Widget</string>
+ <string name="settings.hide_widget_summary">Ocultar widget tras abandonar la aplicación</string>
+ <string name="settings.podcasts_enabled">Podcasts Habilitados</string>
+ <string name="settings.podcasts_enabled_summary">Mostrar o no mostrar el apartado Podcasts en el menú</string>
+ <string name="settings.bookmarks_enabled">Marcadores Habilitados</string>
+ <string name="settings.bookmarks_enabled_summary">Mostrar o no mostrar el apartado Marcadoresen el menú</string>
<string name="shuffle.title">Iniciar aleatorio por</string>
<string name="shuffle.startYear">Año inicial:</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 52c899e2..1a2068f0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -257,6 +257,8 @@
<string name="settings.theme_holo_fullscreen">Holo Fullscreen</string>
<string name="settings.track_title">Display Track #</string>
<string name="settings.track_summary">Display Track # in front of songs if one exists</string>
+ <string name="settings.custom_sort">Custom Sort</string>
+ <string name="settings.custom_sort_summary">Sort directory listings to properly sort by disc number. Interferes with the servers sort albums by year.</string>
<string name="settings.network_title">Network</string>
<string name="settings.max_bitrate_wifi">Max Audio bitrate - Wi-Fi</string>
<string name="settings.max_bitrate_mobile">Max Audio bitrate - Mobile</string>
@@ -368,7 +370,7 @@
<string name="background_task.no_network">This program requires network access. Please turn on Wi-Fi or mobile network.</string>
<string name="background_task.network_error">A network error occurred. Please check the server address or try again later.</string>
<string name="background_task.not_found">Resource not found. Please check the server address.</string>
- <string name="background_task.parse_error">Didn\'t understand the reply. Please check the server address.</string>
+ <string name="background_task.parse_error">A problem occurred communicating with the server. Please check the server address and verify that you can connect using a regular browser on your device.</string>
<string name="service.connecting">Contacting server, please wait.</string>
diff --git a/res/xml/appwidget4x4.xml b/res/xml/appwidget4x4.xml
index 40956dcf..ca2d1012 100644
--- a/res/xml/appwidget4x4.xml
+++ b/res/xml/appwidget4x4.xml
@@ -4,4 +4,6 @@
android:minHeight="250dp"
android:updatePeriodMillis="0"
android:resizeMode="horizontal|vertical"
- android:initialLayout="@layout/appwidget4x4"/> \ No newline at end of file
+ android:initialLayout="@layout/appwidget4x4"
+ android:initialKeyguardLayout="@layout/appwidget4x4"
+ android:widgetCategory="keyguard|home_screen"/> \ No newline at end of file
diff --git a/res/xml/settings.xml b/res/xml/settings.xml
index 6f7527ab..777509de 100644
--- a/res/xml/settings.xml
+++ b/res/xml/settings.xml
@@ -43,6 +43,12 @@
android:key="hideWidget"
android:defaultValue="false"/>
+ <CheckBoxPreference
+ android:title="@string/settings.custom_sort"
+ android:summary="@string/settings.custom_sort_summary"
+ android:key="customSortEnabled"
+ android:defaultValue="true"/>
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/github/daneren2005/dsub/activity/SubsonicActivity.java b/src/github/daneren2005/dsub/activity/SubsonicActivity.java
index 83baeb6a..c475d321 100644
--- a/src/github/daneren2005/dsub/activity/SubsonicActivity.java
+++ b/src/github/daneren2005/dsub/activity/SubsonicActivity.java
@@ -368,7 +368,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
onSearchRequested();
}
}
- } else if(intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
+ } else if(currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
setIntent(intent);
SearchFragment fragment = new SearchFragment();
@@ -511,6 +511,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
// Only move right to left if replaceCurrent is false
if(!replaceCurrent) {
SubsonicFragment oldLeftFragment = backStack.get(backStack.size() - 2);
+ oldLeftFragment.setSecondaryFragment(false);
int leftId = oldLeftFragment.getRootId();
// Make sure remove is finished before adding
@@ -539,7 +540,7 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
Fragment oldFrag = (Fragment)currentFragment;
currentFragment = (SubsonicFragment) backStack.remove(backStack.size() - 1);
- currentFragment.setPrimaryFragment(true);
+ currentFragment.setPrimaryFragment(true, false);
supportInvalidateOptionsMenu();
if(secondaryContainer == null) {
@@ -563,6 +564,8 @@ public class SubsonicActivity extends ActionBarActivity implements OnItemSelecte
trans = getSupportFragmentManager().beginTransaction();
trans.add(R.id.fragment_second_container, currentFragment, currentFragment.getSupportTag() + "");
+
+ backStack.get(backStack.size() - 1).setSecondaryFragment(true);
} else {
secondaryContainer.setVisibility(View.GONE);
}
diff --git a/src/github/daneren2005/dsub/domain/Version.java b/src/github/daneren2005/dsub/domain/Version.java
index 40edf563..8cf338f1 100644
--- a/src/github/daneren2005/dsub/domain/Version.java
+++ b/src/github/daneren2005/dsub/domain/Version.java
@@ -80,6 +80,8 @@ public class Version implements Comparable<Version> {
return "4.7";
case 9:
return "4.8";
+ case 10:
+ return "4.9";
}
}
return "";
diff --git a/src/github/daneren2005/dsub/fragments/DownloadFragment.java b/src/github/daneren2005/dsub/fragments/DownloadFragment.java
index d46fbec6..fb1979b5 100644
--- a/src/github/daneren2005/dsub/fragments/DownloadFragment.java
+++ b/src/github/daneren2005/dsub/fragments/DownloadFragment.java
@@ -103,12 +103,14 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
private VisualizerView visualizerView;
private boolean nowPlaying = true;
private ScheduledFuture<?> hideControlsFuture;
+ private List<DownloadFile> songList;
private SongListAdapter songListAdapter;
private SilentBackgroundTask<Void> onProgressChangedTask;
private SilentBackgroundTask<Void> onCurrentChangedTask;
private SilentBackgroundTask<Void> onDownloadListChangedTask;
private boolean seekInProgress = false;
private boolean startFlipped = false;
+ private boolean scrollWhenLoaded = false;
/**
* Called when the activity is first created.
@@ -506,7 +508,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
menu.findItem(R.id.menu_toggle_timer).setTitle(R.string.download_stop_timer);
}
}
- if(downloadService != null && downloadService.getKeepScreenOn()) {
+ if(downloadService != null && downloadService.getKeepScreenOn() && nowPlaying) {
menu.findItem(R.id.menu_screen_on_off).setTitle(R.string.download_menu_screen_off);
}
}
@@ -740,6 +742,10 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
}
updateButtons();
+
+ if(currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) {
+ getImageLoader().loadImage(albumArtImageView, null, true, false);
+ }
}
@Override
@@ -828,6 +834,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
// Scroll to current playing/downloading.
private void scrollToCurrent() {
if (getDownloadService() == null || songListAdapter == null) {
+ scrollWhenLoaded = true;
return;
}
@@ -860,8 +867,8 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
}
if(startFlipped) {
- scrollToCurrent();
startFlipped = false;
+ scrollToCurrent();
}
onProgressChanged();
@@ -942,6 +949,7 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
protected Void doInBackground() throws Throwable {
currentPlayingIndex = downloadService.getCurrentPlayingIndex() + 1;
size = downloadService.size();
+
return null;
}
@@ -954,19 +962,24 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
else {
list = downloadService.getBackgroundDownloads();
}
-
+
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));
+ songList = new ArrayList<DownloadFile>();
+ songList.addAll(list);
+ playlistView.setAdapter(songListAdapter = new SongListAdapter(songList));
} else {
+ songList.clear();
+ songList.addAll(list);
songListAdapter.notifyDataSetChanged();
}
+
emptyTextView.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
currentRevision = downloadService.getDownloadListUpdateRevision();
@@ -987,6 +1000,11 @@ public class DownloadFragment extends SubsonicFragment implements OnGestureListe
default:
break;
}
+
+ if(scrollWhenLoaded) {
+ scrollToCurrent();
+ scrollWhenLoaded = false;
+ }
setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex, size));
onDownloadListChangedTask = null;
diff --git a/src/github/daneren2005/dsub/fragments/SearchFragment.java b/src/github/daneren2005/dsub/fragments/SearchFragment.java
index 900872da..81d2f29f 100644
--- a/src/github/daneren2005/dsub/fragments/SearchFragment.java
+++ b/src/github/daneren2005/dsub/fragments/SearchFragment.java
@@ -108,7 +108,7 @@ public class SearchFragment extends SubsonicFragment {
} else {
Object item = parent.getItemAtPosition(position);
if (item instanceof Artist) {
- onArtistSelected((Artist) item);
+ onArtistSelected((Artist) item, false);
} else if (item instanceof MusicDirectory.Entry) {
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
if (entry.isDirectory()) {
@@ -208,7 +208,7 @@ public class SearchFragment extends SubsonicFragment {
searchResult = result;
populateList();
if (autoplay) {
- autoplay();
+ autoplay(query);
}
}
@@ -289,11 +289,14 @@ public class SearchFragment extends SubsonicFragment {
mergeAdapter.notifyDataSetChanged();
}
- private void onArtistSelected(Artist artist) {
+ private void onArtistSelected(Artist artist, boolean autoplay) {
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ if(autoplay) {
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
+ }
fragment.setArguments(args);
replaceFragment(fragment, R.id.fragment_list_layout);
@@ -317,6 +320,9 @@ public class SearchFragment extends SubsonicFragment {
args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
+ if(autoplay) {
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
+ }
fragment.setArguments(args);
replaceFragment(fragment, id);
@@ -345,7 +351,7 @@ public class SearchFragment extends SubsonicFragment {
startActivity(intent);
}
- private void autoplay() {
+ private void autoplay(String query) {
if (!searchResult.getSongs().isEmpty()) {
onSongSelected(searchResult.getSongs().get(0), false, false, true, false);
} else if (!searchResult.getAlbums().isEmpty()) {
diff --git a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
index 0081f881..137564ee 100644
--- a/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/src/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -288,7 +288,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
MusicDirectory.Entry entry = (MusicDirectory.Entry) parent.getItemAtPosition(position);
if (entry.isDirectory()) {
int fragId = rootId;
- if(albumListType != null && entry.getParent() != null) {
+ /*if(albumListType != null && entry.getParent() != null) {
SubsonicFragment parentFragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getParent());
@@ -300,7 +300,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Adapter
replaceFragment(parentFragment, fragId);
fragId = parentFragment.getRootId();
- }
+ }*/
SubsonicFragment fragment = new SelectDirectoryFragment();
Bundle args = new Bundle();
diff --git a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
index d33c1b96..bec0be05 100644
--- a/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -187,13 +187,20 @@ public class SubsonicFragment extends Fragment {
}
}
} else if(selected instanceof Artist) {
+ Artist artist = (Artist) selected;
if(Util.isOffline(context)) {
inflater.inflate(R.menu.select_artist_context_offline, menu);
}
else {
inflater.inflate(R.menu.select_artist_context, menu);
+
+ menu.findItem(R.id.artist_menu_star).setTitle(artist.isStarred() ? R.string.common_unstar : R.string.common_star);
}
}
+
+ if(!Util.checkServerVersion(context, "1.10.1")) {
+ menu.setGroupVisible(R.id.server_1_10, false);
+ }
}
public boolean onContextItemSelected(MenuItem menuItem, Object selectedItem) {
@@ -221,6 +228,9 @@ public class SubsonicFragment extends Fragment {
case R.id.artist_menu_delete:
deleteRecursively(artist);
break;
+ case R.id.artist_menu_star:
+ toggleStarred(artist);
+ break;
case R.id.album_menu_play_now:
downloadRecursively(entry.getId(), false, false, true, false, false);
break;
@@ -329,6 +339,9 @@ public class SubsonicFragment extends Fragment {
setPrimaryFragment(primary);
secondaryFragment = secondary;
}
+ public void setSecondaryFragment(boolean secondary) {
+ secondaryFragment = secondary;
+ }
public void invalidate() {
if(primaryFragment) {
diff --git a/src/github/daneren2005/dsub/service/parser/MusicDirectoryParser.java b/src/github/daneren2005/dsub/service/parser/MusicDirectoryParser.java
index 17b09805..7a49cfa5 100644
--- a/src/github/daneren2005/dsub/service/parser/MusicDirectoryParser.java
+++ b/src/github/daneren2005/dsub/service/parser/MusicDirectoryParser.java
@@ -22,7 +22,7 @@ import android.content.Context;
import android.util.Log;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.MusicDirectory;
-import github.daneren2005.dsub.domain.Version;
+import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.ProgressListener;
import github.daneren2005.dsub.util.Util;
import org.xmlpull.v1.XmlPullParser;
@@ -71,7 +71,7 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser {
updateProgress(progressListener, R.string.parser_reading_done);
// Only apply sorting on server version 4.7 and greater, where disc is supported
- if(Util.checkServerVersion(context, "1.8.0")) {
+ if(Util.checkServerVersion(context, "1.8.0") && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true)) {
dir.sortChildren();
}
@@ -80,4 +80,4 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser {
return dir;
}
-} \ No newline at end of file
+}
diff --git a/src/github/daneren2005/dsub/service/parser/PodcastEntryParser.java b/src/github/daneren2005/dsub/service/parser/PodcastEntryParser.java
index 585b3057..58b1432b 100644
--- a/src/github/daneren2005/dsub/service/parser/PodcastEntryParser.java
+++ b/src/github/daneren2005/dsub/service/parser/PodcastEntryParser.java
@@ -88,7 +88,7 @@ public class PodcastEntryParser extends AbstractParser {
episode.setPath(episode.getPath().substring("Podcasts/".length()));
}
- if("error".equals(episode.getStatus()) || "skipped".equals(episode.getStatus())) {
+ if(episode.getId() == null) {
episode.setId(String.valueOf(bogusId));
bogusId--;
}
diff --git a/src/github/daneren2005/dsub/util/Constants.java b/src/github/daneren2005/dsub/util/Constants.java
index 9940c3be..16fe51e5 100644
--- a/src/github/daneren2005/dsub/util/Constants.java
+++ b/src/github/daneren2005/dsub/util/Constants.java
@@ -125,6 +125,7 @@ public final class Constants {
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 PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled";
public static final String OFFLINE_SCROBBLE_COUNT = "scrobbleCount";
public static final String OFFLINE_SCROBBLE_ID = "scrobbleID";
diff --git a/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java b/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
index 195fe913..b92945c4 100644
--- a/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
+++ b/src/github/daneren2005/dsub/util/ShufflePlayBuffer.java
@@ -18,6 +18,7 @@
*/
package github.daneren2005.dsub.util;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
@@ -30,6 +31,7 @@ import android.util.Log;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
+import github.daneren2005.dsub.util.FileUtil;
/**
* @author Sindre Mehus
@@ -38,11 +40,13 @@ import github.daneren2005.dsub.service.MusicServiceFactory;
public class ShufflePlayBuffer {
private static final String TAG = ShufflePlayBuffer.class.getSimpleName();
+ private static final String CACHE_FILENAME = "shuffleBuffer.ser";
private static final int CAPACITY = 50;
private static final int REFILL_THRESHOLD = 40;
private final ScheduledExecutorService executorService;
- private final List<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
+ private boolean firstRun = true;
+ private final ArrayList<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
private int lastCount = -1;
private Context context;
private int currentServer;
@@ -53,7 +57,8 @@ public class ShufflePlayBuffer {
private String endYear = "";
public ShufflePlayBuffer(Context context) {
- this.context = context;
+ this.context = context;
+
executorService = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
@Override
@@ -69,8 +74,15 @@ public class ShufflePlayBuffer {
List<MusicDirectory.Entry> result = new ArrayList<MusicDirectory.Entry>(size);
synchronized (buffer) {
+ boolean removed = false;
while (!buffer.isEmpty() && result.size() < size) {
result.add(buffer.remove(buffer.size() - 1));
+ removed = true;
+ }
+
+ // Re-cache if anything is taken out
+ if(removed) {
+ FileUtil.serialize(context, buffer, CACHE_FILENAME);
}
}
Log.i(TAG, "Taking " + result.size() + " songs from shuffle play buffer. " + buffer.size() + " remaining.");
@@ -86,7 +98,7 @@ public class ShufflePlayBuffer {
// Check if active server has changed.
clearBufferIfnecessary();
- if (buffer.size() > REFILL_THRESHOLD || (!Util.isNetworkConnected(context) && !Util.isOffline(context)) || lastCount == 0) {
+ if (buffer != null && (buffer.size() > REFILL_THRESHOLD || (!Util.isNetworkConnected(context) && !Util.isOffline(context)) || lastCount == 0)) {
return;
}
@@ -100,6 +112,9 @@ public class ShufflePlayBuffer {
buffer.addAll(songs.getChildren());
Log.i(TAG, "Refilled shuffle play buffer with " + songs.getChildrenSize() + " songs.");
lastCount = songs.getChildrenSize();
+
+ // Cache buffer
+ FileUtil.serialize(context, buffer, CACHE_FILENAME);
}
} catch (Exception x) {
Log.w(TAG, "Failed to refill shuffle play buffer.", x);
@@ -121,6 +136,18 @@ public class ShufflePlayBuffer {
startYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, "");
endYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, "");
buffer.clear();
+
+ if(firstRun) {
+ ArrayList cacheList = FileUtil.deserialize(context, CACHE_FILENAME, ArrayList.class);
+ if(cacheList != null) {
+ buffer.addAll(cacheList);
+ }
+ firstRun = false;
+ } else {
+ // Clear cache
+ File file = new File(context.getCacheDir(), CACHE_FILENAME);
+ file.delete();
+ }
}
}
}