aboutsummaryrefslogtreecommitdiff
path: root/subsonic-android
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-android')
-rw-r--r--subsonic-android/patches/jukebox-patch.txt1234
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/activity/SettingsActivity.java6
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/fragments/MainFragment.java4
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/fragments/SubsonicFragment.java3
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/LoadingTask.java45
-rw-r--r--subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java150
6 files changed, 38 insertions, 1404 deletions
diff --git a/subsonic-android/patches/jukebox-patch.txt b/subsonic-android/patches/jukebox-patch.txt
deleted file mode 100644
index cbbeb40b..00000000
--- a/subsonic-android/patches/jukebox-patch.txt
+++ /dev/null
@@ -1,1234 +0,0 @@
-Index: AndroidManifest.xml
-===================================================================
---- AndroidManifest.xml (revision 2441)
-+++ AndroidManifest.xml (working copy)
-@@ -114,7 +114,8 @@
- a:authorities="github.daneren2005.dsub.provider.SearchSuggestionProvider"/>
-
- <meta-data a:name="android.app.default_searchable"
-- a:value="github.daneren2005.dsub.activity.QueryReceiverActivity"/>
-+ a:value="github.daneren2005.dsub.activity.QueryReceiverActivity"/>
-+ <activity a:name="github.daneren2005.dsub.activity.JukeboxActivity" a:launchMode="singleTask" a:configChanges="keyboardHidden"></activity>
-
- </application>
-
-Index: res/drawable/menu_jukebox.png
-===================================================================
-Cannot display: file marked as a binary type.
-svn:mime-type = application/octet-stream
-
-Property changes on: res/drawable/menu_jukebox.png
-___________________________________________________________________
-Added: svn:mime-type
- + application/octet-stream
-
-Index: res/drawable-hdpi-v4/menu_jukebox.png
-===================================================================
-Cannot display: file marked as a binary type.
-svn:mime-type = application/octet-stream
-
-Property changes on: res/drawable-hdpi-v4/menu_jukebox.png
-___________________________________________________________________
-Added: svn:mime-type
- + application/octet-stream
-
-Index: res/layout/button_bar.xml
-===================================================================
---- res/layout/button_bar.xml (revision 2441)
-+++ res/layout/button_bar.xml (working copy)
-@@ -47,6 +47,14 @@
- a:layout_weight="1"
- a:layout_width="0dp"
- a:layout_height="wrap_content"/>
-+
-+ <ImageButton a:id="@+id/button_bar_jukebox"
-+ a:src="@drawable/menu_jukebox"
-+ a:contentDescription="@string/button_bar.jukebox"
-+ a:background="@drawable/menubar_button"
-+ a:layout_weight="1"
-+ a:layout_width="0dp"
-+ a:layout_height="wrap_content"/>
-
- <ImageButton a:id="@+id/button_bar_now_playing"
- a:src="@drawable/menu_now_playing"
-Index: res/layout/jukebox.xml
-===================================================================
---- res/layout/jukebox.xml (revision 0)
-+++ res/layout/jukebox.xml (revision 0)
-@@ -0,0 +1,72 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-+ a:layout_width="fill_parent"
-+ a:layout_height="fill_parent"
-+ a:orientation="vertical" >
-+
-+ <include layout="@layout/tab_progress"/>
-+
-+ <ListView
-+ a:id="@+id/jukebox_list"
-+ a:layout_width="match_parent"
-+ a:layout_height="0dp"
-+ a:layout_weight="1" >
-+ </ListView>
-+
-+ <LinearLayout
-+ a:layout_width="fill_parent"
-+ a:layout_height="wrap_content"
-+ a:layout_marginTop="0dip"
-+ a:background="@color/mediaControlBackground"
-+ a:gravity="center"
-+ a:orientation="horizontal"
-+ a:paddingBottom="0dip"
-+ a:paddingTop="0dip" >
-+
-+ <ImageButton
-+ a:id="@+id/jukebox_shuffle"
-+ a:layout_width="wrap_content"
-+ a:layout_height="fill_parent"
-+ a:background="@android:color/transparent"
-+ a:src="@drawable/media_shuffle" />
-+
-+ <ImageButton
-+ a:id="@+id/jukebox_previous"
-+ a:layout_width="wrap_content"
-+ a:layout_height="wrap_content"
-+ a:background="@android:color/transparent"
-+ a:padding="0dip"
-+ a:src="@drawable/media_backward" />
-+
-+ <ImageButton
-+ a:id="@+id/jukebox_stop"
-+ a:layout_width="60dip"
-+ a:layout_height="60dip"
-+ a:padding="0dip"
-+ a:background="@drawable/media_stop" />
-+
-+ <ImageButton
-+ a:id="@+id/jukebox_start"
-+ a:layout_width="60dip"
-+ a:layout_height="60dip"
-+ a:padding="0dip"
-+ a:background="@drawable/media_start" />
-+
-+ <ImageButton
-+ a:id="@+id/jukebox_next"
-+ a:layout_width="wrap_content"
-+ a:layout_height="wrap_content"
-+ a:background="@android:color/transparent"
-+ a:padding="0dip"
-+ a:src="@drawable/media_forward" />
-+ </LinearLayout>
-+
-+ <SeekBar
-+ a:id="@+id/jukebox_seek"
-+ a:background="@color/mediaControlBackground"
-+ a:layout_width="match_parent"
-+ a:layout_height="wrap_content" />
-+
-+ <include layout="@layout/button_bar" />
-+
-+</LinearLayout>
-\ No newline at end of file
-Index: res/menu/jukebox_context.xml
-===================================================================
---- res/menu/jukebox_context.xml (revision 0)
-+++ res/menu/jukebox_context.xml (revision 0)
-@@ -0,0 +1,8 @@
-+<?xml version="1.0" encoding="utf-8"?>
-+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-+ <item android:id="@+id/jukebox_clear" android:title="@string/jukebox_clear"></item>
-+ <item android:id="@+id/jukebox_remove" android:title="@string/jukebox_remove"></item>
-+
-+
-+
-+</menu>
-\ No newline at end of file
-Index: res/menu/select_album_context.xml
-===================================================================
---- res/menu/select_album_context.xml (revision 2441)
-+++ res/menu/select_album_context.xml (working copy)
-@@ -15,5 +15,6 @@
- a:id="@+id/album_menu_pin"
- a:title="@string/common.pin"
- />
-+ <item a:id="@+id/album_menu_jukebox_add" a:title="@string/jukebox_add"></item>
-
- </menu>
-Index: res/menu/select_artist_context.xml
-===================================================================
---- res/menu/select_artist_context.xml (revision 2441)
-+++ res/menu/select_artist_context.xml (working copy)
-@@ -15,5 +15,6 @@
- a:id="@+id/artist_menu_pin"
- a:title="@string/common.pin"
- />
-+ <item a:id="@+id/artist_menu_jukebox_add" a:title="@string/jukebox_add"></item>
-
- </menu>
-Index: res/menu/select_song_context.xml
-===================================================================
---- res/menu/select_song_context.xml (revision 2441)
-+++ res/menu/select_song_context.xml (working copy)
-@@ -15,5 +15,10 @@
- a:id="@+id/song_menu_play_last"
- a:title="@string/common.play_last"
- />
-+
-+ <item
-+ a:id="@+id/song_menu_jukebox_add"
-+ a:title="@string/jukebox_add"
-+ />
-
- </menu>
-Index: res/values/strings.xml
-===================================================================
---- res/values/strings.xml (revision 2441)
-+++ res/values/strings.xml (working copy)
-@@ -226,6 +226,14 @@
- <plurals name="select_album_donate_dialog_n_trial_days_left">
- <item quantity="one">One day left of trial period</item>
- <item quantity="other">%d days left of trial period</item>
-- </plurals>
-+ </plurals>
-+ <string name="button_bar.jukebox">Jukebox</string>
-+ <string name="jukebox_start">Start</string>
-+ <string name="jukebox_stop">Stop</string>
-+ <string name="jukebox_next">Next</string>
-+ <string name="jukebox_previous">Previous</string>
-+ <string name="jukebox_clear">Clear</string>
-+ <string name="jukebox_remove">Remove</string>
-+ <string name="jukebox_add">Add to Jukebox</string>
-
- </resources>
-Index: src/net/sourceforge/subsonic/androidapp/activity/JukeboxActivity.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/activity/JukeboxActivity.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/activity/JukeboxActivity.java (revision 0)
-@@ -0,0 +1,235 @@
-+/*
-+ 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 java.util.List;
-+
-+import github.daneren2005.dsub.R;
-+import github.daneren2005.dsub.domain.Jukebox;
-+import github.daneren2005.dsub.domain.MusicDirectory;
-+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
-+import github.daneren2005.dsub.service.MusicService;
-+import github.daneren2005.dsub.service.MusicServiceFactory;
-+import github.daneren2005.dsub.util.BackgroundTask;
-+import github.daneren2005.dsub.util.JukeboxSongView;
-+import github.daneren2005.dsub.util.ProgressListener;
-+import github.daneren2005.dsub.util.TabActivityBackgroundTask;
-+import github.daneren2005.dsub.util.Util;
-+import android.os.Bundle;
-+import android.view.ContextMenu;
-+import android.view.MenuInflater;
-+import android.view.MenuItem;
-+import android.view.View;
-+import android.view.View.OnClickListener;
-+import android.view.ViewGroup;
-+import android.widget.AdapterView;
-+import android.widget.AdapterView.OnItemClickListener;
-+import android.widget.ArrayAdapter;
-+import android.widget.ImageButton;
-+import android.widget.ListView;
-+import android.widget.SeekBar;
-+import android.widget.SeekBar.OnSeekBarChangeListener;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class JukeboxActivity extends SubsonicTabActivity implements ProgressListener, OnClickListener, OnSeekBarChangeListener, OnItemClickListener{
-+
-+ private ImageButton play, stop, next, prev, shuffle;
-+ private ListView entryList;
-+ private SeekBar gain;
-+ private Jukebox jukebox;
-+
-+ @Override
-+ public void onCreate(Bundle savedInstanceState){
-+ super.onCreate(savedInstanceState);
-+ setContentView(R.layout.jukebox);
-+
-+ jukebox = new Jukebox();
-+
-+ play = (ImageButton) findViewById(R.id.jukebox_start);
-+ stop = (ImageButton) findViewById(R.id.jukebox_stop);
-+ prev = (ImageButton) findViewById(R.id.jukebox_previous);
-+ next = (ImageButton) findViewById(R.id.jukebox_next);
-+ shuffle = (ImageButton) findViewById(R.id.jukebox_shuffle);
-+ entryList = (ListView) findViewById(R.id.jukebox_list);
-+
-+ gain = (SeekBar) findViewById(R.id.jukebox_seek);
-+ gain.setMax(100);
-+
-+ play.setOnClickListener(this);
-+ stop.setOnClickListener(this);
-+ next.setOnClickListener(this);
-+ prev.setOnClickListener(this);
-+ shuffle.setOnClickListener(this);
-+ gain.setOnSeekBarChangeListener(this);
-+ entryList.setOnItemClickListener(this);
-+
-+ registerForContextMenu(entryList);
-+ load();
-+ }
-+
-+ @Override
-+ public void updateProgress(int messageId){
-+
-+ }
-+
-+ private void load(){
-+ load(Jukebox.GET);
-+ }
-+
-+ private void load(String action){
-+ load(action, "");
-+ }
-+
-+ private void load(final String action, final String additional){
-+ BackgroundTask<Boolean> task = new TabActivityBackgroundTask<Boolean>(this){
-+
-+ protected Boolean doInBackground() throws Throwable{
-+ boolean update = false;
-+ if (!Util.isOffline(JukeboxActivity.this)) {
-+ MusicService musicService = MusicServiceFactory.getMusicService(JukeboxActivity.this);
-+ jukebox.lastAction = action;
-+ jukebox = musicService.getJukebox(jukebox, JukeboxActivity.this, this, additional);
-+ update = true;
-+ }
-+ return update;
-+ }
-+
-+ protected void done(Boolean result){
-+ if (jukebox.isSuccess()) {
-+ if (jukebox.lastAction.equals(Jukebox.SET_GAIN)) {
-+ jukebox.setGain((int) (Double.valueOf(additional.split("=")[1]) * 100));
-+ gain.setProgress(jukebox.getGain());
-+ } else if (jukebox.lastAction.equals(Jukebox.REMOVE_ITEM)) ((SongListAdapter) entryList.getAdapter()).remove((Entry) entryList.getAdapter().getItem(
-+ Integer.valueOf(additional.split("=")[1])));
-+ else if (jukebox.lastAction.equals(Jukebox.CLEAR_PLAYLIST)) ((SongListAdapter) entryList.getAdapter()).clear();
-+ else if (jukebox.lastAction.equals(Jukebox.SKIP_TO_INDEX)) jukebox.setCurrentIndex(Integer.valueOf(additional.split("=")[1]));
-+
-+ if (jukebox.isNewPlaylist()) entryList.setAdapter(new SongListAdapter(jukebox.getChildren()));
-+ }
-+ }
-+ };
-+ task.execute();
-+ }
-+
-+ @Override
-+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo){
-+ super.onCreateContextMenu(menu, view, menuInfo);
-+ MenuInflater inflater = getMenuInflater();
-+ inflater.inflate(R.menu.jukebox_context, menu);
-+ }
-+
-+ @Override
-+ public boolean onContextItemSelected(MenuItem menuItem){
-+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
-+ switch (menuItem.getItemId()) {
-+ case R.id.jukebox_remove:
-+ load(Jukebox.REMOVE_ITEM, "index=" + info.position);
-+ break;
-+ case R.id.jukebox_clear:
-+ load(Jukebox.CLEAR_PLAYLIST);
-+ break;
-+ default:
-+ return super.onContextItemSelected(menuItem);
-+ }
-+ return true;
-+ }
-+
-+ @Override
-+ protected void onResume(){
-+ super.onResume();
-+ load();
-+ }
-+
-+ @Override
-+ public void onClick(View arg0){
-+ if (arg0.equals(this.play)) {
-+ load(Jukebox.START_PLAYBACK);
-+ } else if (arg0.equals(this.stop)) {
-+ load(Jukebox.STOP_PLAYBACK);
-+ } else if (arg0.equals(this.prev)) {
-+ loadW();
-+ load(Jukebox.SKIP_TO_INDEX, "index=" + (jukebox.getCurrentIndex() - 1)); // TODO // MAYBE // BETTER // ?
-+ } else if (arg0.equals(this.next)) {
-+ loadW();
-+ load(Jukebox.SKIP_TO_INDEX, "index=" + (jukebox.getCurrentIndex() + 1));
-+ } else if (arg0.equals(this.shuffle)) {
-+ load(Jukebox.SHUFFLE_PLAYLIST);
-+ load();
-+ }
-+ }
-+
-+ @Override
-+ public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2){
-+ }
-+
-+ @Override
-+ public void onStartTrackingTouch(SeekBar arg0){
-+ }
-+
-+ @Override
-+ public void onStopTrackingTouch(SeekBar arg0){
-+ load(Jukebox.SET_GAIN, "gain=" + ((double) arg0.getProgress() / 100));
-+ }
-+
-+ private class SongListAdapter extends ArrayAdapter<MusicDirectory.Entry>{
-+
-+ public SongListAdapter(List<MusicDirectory.Entry> entries){
-+ super(JukeboxActivity.this, android.R.layout.simple_list_item_1, entries);
-+ }
-+
-+ @Override
-+ public View getView(int position, View convertView, ViewGroup parent){
-+ JukeboxSongView view;
-+ if (convertView != null && convertView instanceof JukeboxSongView) {
-+ view = (JukeboxSongView) convertView;
-+ } else {
-+ view = new JukeboxSongView(JukeboxActivity.this);
-+ }
-+ MusicDirectory.Entry entry = getItem(position);
-+
-+ if (position == jukebox.getCurrentIndex()) {
-+ view.setSong(entry, false, true);
-+ } else view.setSong(entry, false, false);
-+ return view;
-+ }
-+ }
-+
-+ @Override
-+ public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){
-+ load(Jukebox.SKIP_TO_INDEX, "index=" + arg3);
-+ }
-+
-+ public void loadW(){
-+ if (!Util.isOffline(JukeboxActivity.this)) {
-+ MusicService musicService = MusicServiceFactory.getMusicService(JukeboxActivity.this);
-+ jukebox.lastAction = Jukebox.GET;
-+ try {
-+ jukebox = musicService.getJukebox(jukebox, JukeboxActivity.this, this, "");
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+ }
-+ }
-+
-+}
-Index: src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java (working copy)
-@@ -252,6 +252,9 @@
- case R.id.album_menu_pin:
- downloadRecursively(entry.getId(), true, true, false);
- break;
-+ case R.id.album_menu_jukebox_add:
-+ addToJukebox(entry.getId());
-+ break;
- case R.id.song_menu_play_now:
- getDownloadService().download(songs, false, true, true);
- break;
-@@ -261,6 +264,8 @@
- case R.id.song_menu_play_last:
- getDownloadService().download(songs, false, false, false);
- break;
-+ case R.id.song_menu_jukebox_add:
-+ addToJukebox(entry);
- default:
- return super.onContextItemSelected(menuItem);
- }
-Index: src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java (working copy)
-@@ -210,6 +210,9 @@
- case R.id.artist_menu_pin:
- downloadRecursively(artist.getId(), true, true, false);
- break;
-+ case R.id.artist_menu_jukebox_add:
-+ addToJukebox(artist.getId());
-+ break;
- default:
- return super.onContextItemSelected(menuItem);
- }
-Index: src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java (working copy)
-@@ -23,6 +23,16 @@
- import java.util.LinkedList;
- import java.util.List;
-
-+import github.daneren2005.dsub.R;
-+import github.daneren2005.dsub.domain.MusicDirectory;
-+import github.daneren2005.dsub.service.DownloadService;
-+import github.daneren2005.dsub.service.DownloadServiceImpl;
-+import github.daneren2005.dsub.service.MusicService;
-+import github.daneren2005.dsub.service.MusicServiceFactory;
-+import github.daneren2005.dsub.util.Constants;
-+import github.daneren2005.dsub.util.ImageLoader;
-+import github.daneren2005.dsub.util.ModalBackgroundTask;
-+import github.daneren2005.dsub.util.Util;
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
-@@ -39,16 +49,6 @@
- import android.view.View;
- import android.view.Window;
- import android.widget.TextView;
--import github.daneren2005.dsub.R;
--import github.daneren2005.dsub.domain.MusicDirectory;
--import github.daneren2005.dsub.service.DownloadService;
--import github.daneren2005.dsub.service.DownloadServiceImpl;
--import github.daneren2005.dsub.service.MusicService;
--import github.daneren2005.dsub.service.MusicServiceFactory;
--import github.daneren2005.dsub.util.Constants;
--import github.daneren2005.dsub.util.ImageLoader;
--import github.daneren2005.dsub.util.ModalBackgroundTask;
--import github.daneren2005.dsub.util.Util;
-
- /**
- * @author Sindre Mehus
-@@ -63,6 +63,7 @@
- private View musicButton;
- private View searchButton;
- private View playlistButton;
-+ private View jukeboxButton;
- private View nowPlayingButton;
-
- @Override
-@@ -118,6 +119,14 @@
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
- }
- });
-+
-+ jukeboxButton = findViewById(R.id.button_bar_jukebox);
-+ jukeboxButton.setOnClickListener(new View.OnClickListener() {
-+ @Override
-+ public void onClick(View view) {
-+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, JukeboxActivity.class);
-+ }
-+ });
-
- nowPlayingButton = findViewById(R.id.button_bar_now_playing);
- nowPlayingButton.setOnClickListener(new View.OnClickListener() {
-@@ -225,6 +234,22 @@
- int visibility = Util.isOffline(this) ? View.GONE : View.VISIBLE;
- searchButton.setVisibility(visibility);
- playlistButton.setVisibility(visibility);
-+ jukeboxButton.setVisibility(visibility);
-+ /*
-+ * The following block would check for valid Permissions
-+ * but it is called too often -> network traffic/ problems ?
-+ *
-+ MusicService musicService = MusicServiceFactory.getMusicService(this);
-+ try {
-+ User user = musicService.getUser(this, null);
-+ if(!user.isJukeboxControl()){
-+ jukeboxButton.setVisibility(View.GONE);
-+ }
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+ */
- }
-
- public void setProgressVisible(boolean visible) {
-@@ -363,5 +388,67 @@
- }
- }
- }
-+
-+ protected void addToJukebox(String id) {
-+
-+ List<MusicDirectory.Entry> entries = new LinkedList<MusicDirectory.Entry>();
-+ MusicService musicService = MusicServiceFactory.getMusicService(this);
-+ MusicDirectory root;
-+
-+ try {
-+ root = musicService.getMusicDirectory(id, false, SubsonicTabActivity.this, null);
-+ collectEntries(root, entries);
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+
-+
-+ StringBuilder build = new StringBuilder();
-+ build.append("action=add");
-+ for(MusicDirectory.Entry entry2: entries){
-+ build.append("&id=");
-+ build.append(entry2.getId());
-+ }
-+ try {
-+ musicService.getJukebox(null, this, null, build.toString());
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+
-+ }
-+
-+ protected void addToJukebox(MusicDirectory.Entry entry) {
-+ try {
-+ MusicService musicService = MusicServiceFactory.getMusicService(this);
-+ musicService.getJukebox(null, this, null, "action=add&id="+entry.getId());
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+ }
-+
-+ private List<MusicDirectory.Entry> collectEntries(MusicDirectory parent, List<MusicDirectory.Entry> songs){
-+ for (MusicDirectory.Entry song : parent.getChildren(false, true)) {
-+ if (!song.isVideo()) {
-+ songs.add(song);
-+ }
-+ }
-+ for (MusicDirectory.Entry dir : parent.getChildren(true, false)) {
-+ MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
-+ try {
-+ collectEntries(musicService.getMusicDirectory(dir.getId(), false, SubsonicTabActivity.this, null), songs);
-+ } catch (Exception e) {
-+ // TODO Auto-generated catch block
-+ e.printStackTrace();
-+ }
-+ }
-+
-+ return songs;
-+ }
-+
-+
-+
- }
-
-Index: src/net/sourceforge/subsonic/androidapp/domain/Jukebox.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/domain/Jukebox.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/domain/Jukebox.java (revision 0)
-@@ -0,0 +1,113 @@
-+/*
-+ 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.domain;
-+
-+import java.io.Serializable;
-+import java.util.List;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class Jukebox extends MusicDirectory implements Serializable{
-+
-+ public String lastAction;
-+
-+ //get, start, stop, skip, add, clear, remove, shuffle, setGain
-+ public static final String GET = "get";
-+ public static final String START_PLAYBACK = "start";
-+ public static final String STOP_PLAYBACK = "stop";
-+ public static final String SKIP_TO_INDEX = "skip";
-+ public static final String ADD_TO_PLAYLIST = "add";
-+ public static final String CLEAR_PLAYLIST = "clear";
-+ public static final String REMOVE_ITEM = "remove";
-+ public static final String SHUFFLE_PLAYLIST = "shuffle";
-+ public static final String SET_GAIN = "setGain";
-+
-+ public Jukebox() {
-+ super();
-+ }
-+
-+ public boolean isPlaying() {
-+ return playing;
-+ }
-+
-+ public void setPlaying(boolean playing) {
-+ this.playing = playing;
-+ }
-+
-+ public int getGain() {
-+ return gain;
-+ }
-+
-+ public void setGain(int gain) {
-+ this.gain = gain;
-+ }
-+
-+ public int getCurrentIndex() {
-+ return currentIndex;
-+ }
-+
-+ public void setCurrentIndex(int currentIndex) {
-+ this.currentIndex = currentIndex;
-+ }
-+
-+ public boolean isAvailable() {
-+ return available;
-+ }
-+
-+ public boolean isSuccess() {
-+ return success;
-+ }
-+
-+ public void setAvailable(boolean available) {
-+ this.available = available;
-+ }
-+
-+ public void setSuccess(boolean success) {
-+ this.success = success;
-+ }
-+
-+ public boolean isNewPlaylist() {
-+ return newPlaylist;
-+ }
-+
-+ public void setNewPlaylist(boolean newPlaylist) {
-+ this.newPlaylist = newPlaylist;
-+ }
-+
-+ private boolean playing = false;
-+ private int gain = 0;
-+ private int currentIndex = 0;
-+ private boolean available = false;
-+ private boolean success = false;
-+ private boolean newPlaylist = false;
-+
-+ public void addChildren(List<Entry> children){
-+ super.addChildren(children);
-+ }
-+
-+ public void reset(){
-+ this.available = false;
-+ this.success = false;
-+ this.newPlaylist = false;
-+ }
-+
-+}
-Index: src/net/sourceforge/subsonic/androidapp/domain/MusicDirectory.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/domain/MusicDirectory.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/domain/MusicDirectory.java (working copy)
-@@ -59,6 +59,13 @@
- }
- return result;
- }
-+
-+ protected void addChildren(List<Entry> children){
-+ if(!children.isEmpty()) {
-+ this.children.clear();
-+ this.children.addAll(children);
-+ }
-+ }
-
- public static class Entry implements Serializable {
- private String id;
-Index: src/net/sourceforge/subsonic/androidapp/domain/User.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/domain/User.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/domain/User.java (revision 0)
-@@ -0,0 +1,43 @@
-+/*
-+ 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.domain;
-+
-+import java.io.Serializable;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class User implements Serializable{
-+
-+ //TODO implement missing user attributes
-+
-+ private boolean jukeboxControl;
-+
-+ public boolean isJukeboxControl() {
-+ return jukeboxControl;
-+ }
-+
-+ public void setJukeboxControl(boolean jukeboxControl) {
-+ this.jukeboxControl = jukeboxControl;
-+ }
-+
-+
-+}
-Index: src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/service/CachedMusicService.java (working copy)
-@@ -21,9 +21,11 @@
- import android.content.Context;
- import android.graphics.Bitmap;
- import github.daneren2005.dsub.domain.Indexes;
-+import github.daneren2005.dsub.domain.Jukebox;
- import github.daneren2005.dsub.domain.MusicDirectory;
- import github.daneren2005.dsub.domain.MusicFolder;
- import github.daneren2005.dsub.domain.Playlist;
-+import github.daneren2005.dsub.domain.User;
- import github.daneren2005.dsub.domain.Version;
- import github.daneren2005.dsub.domain.SearchResult;
- import github.daneren2005.dsub.domain.SearchCritera;
-@@ -199,4 +201,17 @@
- restUrl = newUrl;
- }
- }
-+
-+ @Override
-+ public Jukebox getJukebox(Jukebox jukebox, Context context,
-+ ProgressListener progressListener, String action) throws Exception {
-+ return musicService.getJukebox(jukebox, context, progressListener, action);
-+ }
-+
-+ @Override
-+ public User getUser(Context context, ProgressListener progressListener)
-+ throws Exception {
-+ return musicService.getUser(context, progressListener);
-+ }
-+
- }
-Index: src/net/sourceforge/subsonic/androidapp/service/MusicService.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/MusicService.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/service/MusicService.java (working copy)
-@@ -21,9 +21,11 @@
- import android.content.Context;
- import android.graphics.Bitmap;
- import github.daneren2005.dsub.domain.Indexes;
-+import github.daneren2005.dsub.domain.Jukebox;
- import github.daneren2005.dsub.domain.MusicDirectory;
- import github.daneren2005.dsub.domain.MusicFolder;
- import github.daneren2005.dsub.domain.Playlist;
-+import github.daneren2005.dsub.domain.User;
- import github.daneren2005.dsub.domain.Version;
- import github.daneren2005.dsub.domain.SearchResult;
- import github.daneren2005.dsub.domain.SearchCritera;
-@@ -74,4 +76,8 @@
- Version getLatestVersion(Context context, ProgressListener progressListener) throws Exception;
-
- String getVideoUrl(Context context, String id);
-+
-+ Jukebox getJukebox(Jukebox jukebox, Context context, ProgressListener progressListener , String action) throws Exception;
-+
-+ User getUser(Context context, ProgressListener progressListener) throws Exception;
- }
-\ No newline at end of file
-Index: src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/service/RESTMusicService.java (working copy)
-@@ -28,6 +28,7 @@
- import android.util.Log;
- import github.daneren2005.dsub.R;
- import github.daneren2005.dsub.domain.Indexes;
-+import github.daneren2005.dsub.domain.Jukebox;
- import github.daneren2005.dsub.domain.Lyrics;
- import github.daneren2005.dsub.domain.MusicDirectory;
- import github.daneren2005.dsub.domain.MusicFolder;
-@@ -35,10 +36,12 @@
- import github.daneren2005.dsub.domain.SearchCritera;
- import github.daneren2005.dsub.domain.SearchResult;
- import github.daneren2005.dsub.domain.ServerInfo;
-+import github.daneren2005.dsub.domain.User;
- import github.daneren2005.dsub.domain.Version;
- import github.daneren2005.dsub.service.parser.AlbumListParser;
- import github.daneren2005.dsub.service.parser.ErrorParser;
- import github.daneren2005.dsub.service.parser.IndexesParser;
-+import github.daneren2005.dsub.service.parser.JukeboxParser;
- import github.daneren2005.dsub.service.parser.LicenseParser;
- import github.daneren2005.dsub.service.parser.LyricsParser;
- import github.daneren2005.dsub.service.parser.MusicDirectoryParser;
-@@ -48,6 +51,7 @@
- import github.daneren2005.dsub.service.parser.RandomSongsParser;
- import github.daneren2005.dsub.service.parser.SearchResult2Parser;
- import github.daneren2005.dsub.service.parser.SearchResultParser;
-+import github.daneren2005.dsub.service.parser.UserParser;
- import github.daneren2005.dsub.service.parser.VersionParser;
- import github.daneren2005.dsub.service.ssl.SSLSocketFactory;
- import github.daneren2005.dsub.service.ssl.TrustSelfSignedStrategy;
-@@ -195,6 +199,53 @@
- Util.close(reader);
- }
- }
-+
-+ public Jukebox getJukebox(Jukebox jukebox, Context context, ProgressListener progressListener, String action) throws Exception {
-+
-+ List<String> parameterNames = new ArrayList<String>();
-+ List<Object> parameterValues = new ArrayList<Object>();
-+ if(jukebox != null){
-+ parameterNames.add("action");
-+ parameterValues.add(jukebox.lastAction);
-+ }
-+ if(!action.isEmpty()){
-+ String[] names_values = action.split("&");
-+ for(String name_value: names_values){
-+ String[] pair = name_value.split("=");
-+ parameterNames.add(pair[0]);
-+ parameterValues.add(pair[1]);
-+ }
-+ }
-+
-+ Reader reader = getReader(context, progressListener, "jukeboxControl", null, parameterNames, parameterValues);
-+
-+ try {
-+ return new JukeboxParser(context).parse(jukebox, reader, progressListener);
-+ } finally {
-+ Util.close(reader);
-+ }
-+ }
-+
-+ public User getUser(Context context, ProgressListener progressListener) throws Exception {
-+
-+ SharedPreferences prefs = Util.getPreferences(context);
-+ int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
-+ String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
-+
-+ List<String> parameterNames = new ArrayList<String>();
-+ List<Object> parameterValues = new ArrayList<Object>();
-+ parameterNames.add("username");
-+ parameterValues.add(username);
-+
-+ Reader reader = getReader(context, progressListener, "getUser", null, parameterNames, parameterValues);
-+
-+ try {
-+ return new UserParser(context).parse(reader, progressListener);
-+ } finally {
-+ Util.close(reader);
-+ }
-+ }
-+
-
- @Override
- public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
-Index: src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java (revision 2441)
-+++ src/net/sourceforge/subsonic/androidapp/service/parser/AbstractParser.java (working copy)
-@@ -97,6 +97,11 @@
- String s = get(name);
- return s == null ? null : Long.valueOf(s);
- }
-+
-+ protected Double getDouble(String name) {
-+ String s = get(name);
-+ return s == null ? null : Double.valueOf(s);
-+ }
-
- protected void init(Reader reader) throws Exception {
- parser = Xml.newPullParser();
-Index: src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxParser.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxParser.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/service/parser/JukeboxParser.java (revision 0)
-@@ -0,0 +1,86 @@
-+/*
-+ 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.service.parser;
-+
-+import java.io.Reader;
-+
-+import github.daneren2005.dsub.R;
-+import github.daneren2005.dsub.domain.Jukebox;
-+import github.daneren2005.dsub.domain.MusicDirectory;
-+import github.daneren2005.dsub.util.ProgressListener;
-+
-+import org.xmlpull.v1.XmlPullParser;
-+
-+import android.content.Context;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class JukeboxParser extends MusicDirectoryEntryParser {
-+
-+ public JukeboxParser(Context context) {
-+ super(context);
-+ }
-+
-+ public Jukebox parse(Jukebox jukebox, Reader reader,
-+ ProgressListener progressListener) throws Exception {
-+ updateProgress(progressListener, R.string.parser_reading);
-+
-+ if (jukebox == null)
-+ jukebox = new Jukebox();
-+ jukebox.reset();
-+ init(reader);
-+ jukebox.setAvailable(true);
-+
-+ MusicDirectory dir = new MusicDirectory();
-+
-+ int eventType;
-+ do {
-+ eventType = nextParseEvent();
-+ if (eventType == XmlPullParser.START_TAG) {
-+ String name = getElementName();
-+ if ("entry".equals(name)) {
-+ dir.addChild(parseEntry());
-+ jukebox.setNewPlaylist(true);
-+ } else if ("jukeboxPlaylist".equals(name)) {
-+ jukebox.setPlaying(getBoolean("playing"));
-+ jukebox.setGain((int) (getDouble("gain") * 100));
-+ jukebox.setCurrentIndex(getInteger("currentIndex"));
-+ } else if ("subsonic-response".equals(name)) {
-+ if (get("status").equals("ok"))
-+ jukebox.setSuccess(true);
-+ } else if ("error".equals(name)) {
-+ handleError();
-+ }
-+ }
-+ } while (eventType != XmlPullParser.END_DOCUMENT);
-+
-+ if(jukebox.isNewPlaylist()) {
-+ jukebox.addChildren(dir.getChildren());
-+ }
-+
-+ validate();
-+ updateProgress(progressListener, R.string.parser_reading_done);
-+
-+ return jukebox;
-+ }
-+
-+}
-Index: src/net/sourceforge/subsonic/androidapp/service/parser/UserParser.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/service/parser/UserParser.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/service/parser/UserParser.java (revision 0)
-@@ -0,0 +1,67 @@
-+/*
-+ 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.service.parser;
-+
-+import java.io.Reader;
-+
-+import github.daneren2005.dsub.R;
-+import github.daneren2005.dsub.domain.User;
-+import github.daneren2005.dsub.util.ProgressListener;
-+
-+import org.xmlpull.v1.XmlPullParser;
-+
-+import android.content.Context;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class UserParser extends AbstractParser{
-+
-+ public UserParser(Context context) {
-+ super(context);
-+ }
-+
-+ public User parse(Reader reader, ProgressListener progressListener) throws Exception {
-+ updateProgress(progressListener, R.string.parser_reading);
-+ init(reader);
-+
-+ User user = new User();
-+ int eventType;
-+ do {
-+ eventType = nextParseEvent();
-+ if (eventType == XmlPullParser.START_TAG) {
-+ String name = getElementName();
-+ if ("user".equals(name)) {
-+ user.setJukeboxControl(getBoolean("jukeboxRole"));
-+ } else if ("error".equals(name)) {
-+ handleError();
-+ }
-+ }
-+ } while (eventType != XmlPullParser.END_DOCUMENT);
-+
-+ validate();
-+ updateProgress(progressListener, R.string.parser_reading_done);
-+
-+ return user;
-+ }
-+
-+
-+}
-Index: src/net/sourceforge/subsonic/androidapp/util/JukeboxSongView.java
-===================================================================
---- src/net/sourceforge/subsonic/androidapp/util/JukeboxSongView.java (revision 0)
-+++ src/net/sourceforge/subsonic/androidapp/util/JukeboxSongView.java (revision 0)
-@@ -0,0 +1,88 @@
-+/*
-+ 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.util;
-+
-+import github.daneren2005.dsub.R;
-+import github.daneren2005.dsub.domain.MusicDirectory;
-+import android.content.Context;
-+import android.view.LayoutInflater;
-+import android.view.View;
-+import android.widget.CheckedTextView;
-+import android.widget.LinearLayout;
-+import android.widget.TextView;
-+
-+/**
-+ * @author meld0
-+ *
-+ */
-+public class JukeboxSongView extends LinearLayout{
-+
-+ private CheckedTextView checkedTextView;
-+ private TextView titleTextView;
-+ private TextView artistTextView;
-+ private TextView durationTextView;
-+ private TextView statusTextView;
-+ private MusicDirectory.Entry song;
-+
-+ public JukeboxSongView(Context context) {
-+ super(context);
-+ LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true);
-+
-+ checkedTextView = (CheckedTextView) findViewById(R.id.song_check);
-+ titleTextView = (TextView) findViewById(R.id.song_title);
-+ artistTextView = (TextView) findViewById(R.id.song_artist);
-+ durationTextView = (TextView) findViewById(R.id.song_duration);
-+ statusTextView = (TextView) findViewById(R.id.song_status);
-+
-+ }
-+
-+ public void setSong(MusicDirectory.Entry song, boolean checkable, boolean playing) {
-+ this.song = song;
-+ StringBuilder artist = new StringBuilder(40);
-+
-+ String bitRate = null;
-+ if (song.getBitRate() != null) {
-+ bitRate = String.format(getContext().getString(R.string.song_details_kbps), song.getBitRate());
-+ }
-+
-+ String fileFormat = null;
-+ if (song.getTranscodedSuffix() != null && !song.getTranscodedSuffix().equals(song.getSuffix())) {
-+ fileFormat = String.format("%s > %s", song.getSuffix(), song.getTranscodedSuffix());
-+ } else {
-+ fileFormat = song.getSuffix();
-+ }
-+
-+ artist.append(song.getArtist()).append(" (")
-+ .append(String.format(getContext().getString(R.string.song_details_all), bitRate == null ? "" : bitRate, fileFormat))
-+ .append(")");
-+
-+ titleTextView.setText(song.getTitle());
-+ artistTextView.setText(artist);
-+ durationTextView.setText(Util.formatDuration(song.getDuration()));
-+ checkedTextView.setVisibility(checkable && !song.isVideo() ? View.VISIBLE : View.GONE);
-+
-+ if(playing){
-+ titleTextView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.stat_notify_playing, 0, 0, 0);
-+ }else{
-+ titleTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
-+ }
-+ }
-+
-+}
diff --git a/subsonic-android/src/github/daneren2005/dsub/activity/SettingsActivity.java b/subsonic-android/src/github/daneren2005/dsub/activity/SettingsActivity.java
index 98454d4a..f5aea74a 100644
--- a/subsonic-android/src/github/daneren2005/dsub/activity/SettingsActivity.java
+++ b/subsonic-android/src/github/daneren2005/dsub/activity/SettingsActivity.java
@@ -39,9 +39,9 @@ import github.daneren2005.dsub.service.DownloadServiceImpl;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.util.Constants;
+import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.view.ErrorDialog;
import github.daneren2005.dsub.util.FileUtil;
-import github.daneren2005.dsub.util.ModalBackgroundTask;
import github.daneren2005.dsub.util.Util;
import java.io.File;
@@ -116,7 +116,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
Util.confirmDialog(SettingsActivity.this, R.string.common_delete, "cache", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- new ModalBackgroundTask<Void>(SettingsActivity.this) {
+ new LoadingTask<Void>(SettingsActivity.this, false) {
@Override
protected Void doInBackground() throws Throwable {
FileUtil.deleteMusicDirectory(SettingsActivity.this);
@@ -410,7 +410,7 @@ public class SettingsActivity extends PreferenceActivity implements SharedPrefer
}
private void testConnection(final int instance) {
- ModalBackgroundTask<Boolean> task = new ModalBackgroundTask<Boolean>(this, false) {
+ LoadingTask<Boolean> task = new LoadingTask<Boolean>(this) {
private int previousInstance;
@Override
diff --git a/subsonic-android/src/github/daneren2005/dsub/fragments/MainFragment.java b/subsonic-android/src/github/daneren2005/dsub/fragments/MainFragment.java
index 1c8afbaa..9a48acd5 100644
--- a/subsonic-android/src/github/daneren2005/dsub/fragments/MainFragment.java
+++ b/subsonic-android/src/github/daneren2005/dsub/fragments/MainFragment.java
@@ -19,6 +19,7 @@ import github.daneren2005.dsub.R;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.FileUtil;
+import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.view.MergeAdapter;
import github.daneren2005.dsub.util.Util;
import com.actionbarsherlock.view.Menu;
@@ -26,7 +27,6 @@ import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.MenuInflater;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
-import github.daneren2005.dsub.util.ModalBackgroundTask;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.view.ChangeLog;
import java.io.File;
@@ -326,7 +326,7 @@ public class MainFragment extends SubsonicFragment {
private void getLogs() {
try {
final String version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
- new ModalBackgroundTask<File>(context, false) {
+ new LoadingTask<File>(context) {
@Override
protected File doInBackground() throws Throwable {
updateProgress("Gathering Logs");
diff --git a/subsonic-android/src/github/daneren2005/dsub/fragments/SubsonicFragment.java b/subsonic-android/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
index 9b16fdcb..9e8ec29c 100644
--- a/subsonic-android/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/subsonic-android/src/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -61,7 +61,6 @@ import github.daneren2005.dsub.service.ServerTooOldException;
import github.daneren2005.dsub.util.Constants;
import github.daneren2005.dsub.util.FileUtil;
import github.daneren2005.dsub.util.ImageLoader;
-import github.daneren2005.dsub.util.ModalBackgroundTask;
import github.daneren2005.dsub.util.SilentBackgroundTask;
import github.daneren2005.dsub.util.LoadingTask;
import github.daneren2005.dsub.util.Util;
@@ -570,7 +569,7 @@ public class SubsonicFragment extends SherlockFragment {
downloadRecursively(id, name, false, save, append, autoplay, shuffle, background);
}
protected void downloadRecursively(final String id, final String name, final boolean isDirectory, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background) {
- ModalBackgroundTask<List<MusicDirectory.Entry>> task = new ModalBackgroundTask<List<MusicDirectory.Entry>>(context, false) {
+ LoadingTask<List<MusicDirectory.Entry>> task = new LoadingTask<List<MusicDirectory.Entry>>(context) {
private static final int MAX_SONGS = 500;
@Override
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/LoadingTask.java b/subsonic-android/src/github/daneren2005/dsub/util/LoadingTask.java
index 0b48a338..9ab5c86d 100644
--- a/subsonic-android/src/github/daneren2005/dsub/util/LoadingTask.java
+++ b/subsonic-android/src/github/daneren2005/dsub/util/LoadingTask.java
@@ -1,7 +1,9 @@
package github.daneren2005.dsub.util;
+import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
+
import github.daneren2005.dsub.activity.SubsonicActivity;
/**
@@ -10,11 +12,18 @@ import github.daneren2005.dsub.activity.SubsonicActivity;
*/
public abstract class LoadingTask<T> extends BackgroundTask<T> {
- private final SubsonicActivity tabActivity;
+ private final Activity tabActivity;
+ private ProgressDialog loading;
+ private Thread thread;
private final boolean cancellable;
private boolean cancelled = false;
- public LoadingTask(SubsonicActivity activity, final boolean cancellable) {
+ public LoadingTask(Activity activity) {
+ super(activity);
+ tabActivity = activity;
+ this.cancellable = true;
+ }
+ public LoadingTask(Activity activity, final boolean cancellable) {
super(activity);
tabActivity = activity;
this.cancellable = cancellable;
@@ -22,14 +31,14 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
@Override
public void execute() {
- final ProgressDialog loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() {
+ loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
- cancelled = true;
+ cancel();
}
});
- new Thread() {
+ thread = new Thread() {
@Override
public void run() {
try {
@@ -59,20 +68,30 @@ public abstract class LoadingTask<T> extends BackgroundTask<T> {
});
}
}
- }.start();
+ };
+ thread.start();
}
+ protected void cancel() {
+ cancelled = true;
+ if (thread != null) {
+ thread.interrupt();
+ }
+ }
+
private boolean isCancelled() {
- return tabActivity.isDestroyed() || cancelled;
+ return (tabActivity instanceof SubsonicActivity && ((SubsonicActivity)tabActivity).isDestroyed()) || cancelled;
}
@Override
public void updateProgress(final String message) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
-
- }
- });
+ if(!cancelled) {
+ getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ loading.setMessage(message);
+ }
+ });
+ }
}
}
diff --git a/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java b/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java
deleted file mode 100644
index f0310780..00000000
--- a/subsonic-android/src/github/daneren2005/dsub/util/ModalBackgroundTask.java
+++ /dev/null
@@ -1,150 +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.util;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
-import android.util.Log;
-import github.daneren2005.dsub.R;
-import github.daneren2005.dsub.view.ErrorDialog;
-
-/**
- * @author Sindre Mehus
- */
-public abstract class ModalBackgroundTask<T> extends BackgroundTask<T> {
-
- private static final String TAG = ModalBackgroundTask.class.getSimpleName();
-
- private final AlertDialog progressDialog;
- private Thread thread;
- private final boolean finishActivityOnCancel;
- private boolean cancelled;
-
- public ModalBackgroundTask(Activity activity, boolean finishActivityOnCancel) {
- super(activity);
- this.finishActivityOnCancel = finishActivityOnCancel;
- progressDialog = createProgressDialog();
- }
-
- public ModalBackgroundTask(Activity activity) {
- this(activity, true);
- }
-
- private AlertDialog createProgressDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder.setIcon(android.R.drawable.ic_dialog_info);
- builder.setTitle(R.string.background_task_wait);
- builder.setMessage(R.string.background_task_loading);
- builder.setCancelable(true);
- builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialogInterface) {
- cancel();
- }
- });
- builder.setPositiveButton(R.string.common_cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int i) {
- cancel();
- }
- });
-
- return builder.create();
- }
-
- public void execute() {
- cancelled = false;
- progressDialog.show();
-
- thread = new Thread() {
- @Override
- public void run() {
- try {
- final T result = doInBackground();
- if (cancelled) {
- progressDialog.dismiss();
- return;
- }
-
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- try {
- progressDialog.dismiss();
- } catch(Exception e) {
- Log.w(TAG, "Failed to dismiss dialog");
- }
- done(result);
- }
- });
-
- } catch (final Throwable t) {
- if (cancelled) {
- return;
- }
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- try {
- progressDialog.dismiss();
- } catch(Exception e) {
- Log.w(TAG, "Failed to dismiss dialog");
- }
- error(t);
- }
- });
- }
- }
- };
- thread.start();
- }
-
- protected void cancel() {
- cancelled = true;
- if (thread != null) {
- thread.interrupt();
- }
-
- if (finishActivityOnCancel) {
- getActivity().finish();
- }
- }
-
- protected boolean isCancelled() {
- return cancelled;
- }
-
- protected void error(Throwable error) {
- Log.w(TAG, "Got exception: " + error, error);
- new ErrorDialog(getActivity(), getErrorMessage(error), finishActivityOnCancel);
- }
-
- @Override
- public void updateProgress(final String message) {
- if(!cancelled) {
- getHandler().post(new Runnable() {
- @Override
- public void run() {
- progressDialog.setMessage(message);
- }
- });
- }
- }
-}