1
0
mirror of https://github.com/ultrasonic/ultrasonic synced 2025-04-26 16:18:51 +02:00

Removed Option Menu on post 3.x devices, added Settings and Help buttons instead of option menu, changed icon for server selection

This commit is contained in:
Joshua Bahnsen 2012-05-23 15:45:11 -07:00
parent b8222a6888
commit feca33c9ac
8 changed files with 1519 additions and 1414 deletions

View File

@ -19,7 +19,7 @@
a:paddingTop="2dip" a:paddingTop="2dip"
a:scaleType="centerInside" a:scaleType="centerInside"
a:src="@drawable/main_header_icon" /> a:src="@drawable/main_header_icon" />
/> />
<TextView <TextView
a:id="@+id/actionbar_title_text" a:id="@+id/actionbar_title_text"
@ -45,36 +45,48 @@
a:id="@+id/action_button_3" a:id="@+id/action_button_3"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="match_parent" a:layout_height="match_parent"
a:layout_alignParentTop="true"
a:layout_toLeftOf="@+id/action_button_4"
a:background="@drawable/list_selector_holo_dark"
a:padding="5dp"
a:scaleType="center"
a:showAsAction="ifRoom|withText"
a:src="@drawable/ic_menu_help" />
<ImageButton
a:id="@+id/action_button_4"
a:layout_width="wrap_content"
a:layout_height="match_parent"
a:layout_alignParentBottom="true" a:layout_alignParentBottom="true"
a:layout_alignParentRight="true" a:layout_alignParentRight="true"
a:background="@drawable/list_selector_holo_dark" a:background="@drawable/list_selector_holo_dark"
a:padding="5dp" a:padding="5dp"
a:scaleType="center" a:scaleType="center"
a:showAsAction="ifRoom|withText" a:showAsAction="ifRoom|withText"
a:src="@drawable/ic_menu_moreoverflow" /> a:src="@drawable/ic_menu_settings" />
<ImageButton <ImageButton
a:id="@+id/action_button_1" a:id="@+id/action_button_1"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="match_parent" a:layout_height="match_parent"
a:layout_alignParentTop="true" a:layout_alignParentTop="true"
a:layout_toLeftOf="@+id/action_button_2"
a:background="@drawable/list_selector_holo_dark"
a:padding="5dp"
a:scaleType="center"
a:showAsAction="ifRoom|withText"
a:src="@drawable/ic_menu_search" />
<ImageButton
a:id="@+id/action_button_2"
a:layout_width="wrap_content"
a:layout_height="match_parent"
a:layout_alignParentTop="true"
a:layout_toLeftOf="@+id/action_button_3" a:layout_toLeftOf="@+id/action_button_3"
a:background="@drawable/list_selector_holo_dark" a:background="@drawable/list_selector_holo_dark"
a:padding="5dp" a:padding="5dp"
a:scaleType="center" a:scaleType="center"
a:showAsAction="ifRoom|withText" a:showAsAction="ifRoom|withText"
a:src="@drawable/ic_menu_shuffle" /> a:src="@drawable/ic_menu_shuffle" />
<ImageButton </RelativeLayout>
a:id="@+id/action_button_2"
a:layout_width="wrap_content"
a:layout_height="match_parent"
a:layout_alignParentTop="true"
a:layout_toLeftOf="@+id/action_button_1"
a:background="@drawable/list_selector_holo_dark"
a:padding="5dp"
a:scaleType="center"
a:showAsAction="ifRoom|withText"
a:src="@drawable/ic_menu_search" />
</RelativeLayout>

View File

@ -13,12 +13,12 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:minHeight="?android:attr/listPreferredItemHeight"> a:minHeight="?android:attr/listPreferredItemHeight">
<ImageView <ImageView
a:src="@drawable/ic_menu_compass" a:layout_width="wrap_content"
a:layout_gravity="center_vertical" a:layout_height="wrap_content"
a:layout_width="wrap_content" a:layout_gravity="center_vertical"
a:layout_height="wrap_content"/> a:src="@drawable/ic_menu_select_artist_folder" />
<LinearLayout <LinearLayout
a:orientation="vertical" a:orientation="vertical"

View File

@ -1,268 +1,279 @@
/* /*
This file is part of Subsonic. This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Subsonic is distributed in the hope that it will be useful, Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>. along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package net.sourceforge.subsonic.androidapp.activity; package net.sourceforge.subsonic.androidapp.activity;
import java.util.Arrays; import java.util.Arrays;
import net.sourceforge.subsonic.androidapp.R; import net.sourceforge.subsonic.androidapp.R;
import net.sourceforge.subsonic.androidapp.service.DownloadService; import net.sourceforge.subsonic.androidapp.service.DownloadService;
import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl; import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
import net.sourceforge.subsonic.androidapp.util.Constants; import net.sourceforge.subsonic.androidapp.util.Constants;
import net.sourceforge.subsonic.androidapp.util.MergeAdapter; import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
import net.sourceforge.subsonic.androidapp.util.Util; import net.sourceforge.subsonic.androidapp.util.Util;
import net.sourceforge.subsonic.androidapp.util.FileUtil; import net.sourceforge.subsonic.androidapp.util.FileUtil;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.view.Window;
import android.widget.ImageButton; import android.widget.AdapterView;
import android.widget.ListView; import android.widget.ImageButton;
import android.widget.TextView; import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends SubsonicTabActivity {
public class MainActivity extends SubsonicTabActivity {
private static final int MENU_GROUP_SERVER = 10;
private static final int MENU_ITEM_SERVER_1 = 101; private static final int MENU_GROUP_SERVER = 10;
private static final int MENU_ITEM_SERVER_2 = 102; private static final int MENU_ITEM_SERVER_1 = 101;
private static final int MENU_ITEM_SERVER_3 = 103; private static final int MENU_ITEM_SERVER_2 = 102;
private static final int MENU_ITEM_OFFLINE = 104; private static final int MENU_ITEM_SERVER_3 = 103;
private static final int MENU_ITEM_OFFLINE = 104;
private String theme;
private String theme;
private static boolean infoDialogDisplayed;
private static boolean infoDialogDisplayed;
/**
* Called when the activity is first created. /**
*/ * Called when the activity is first created.
@Override */
public void onCreate(Bundle savedInstanceState) { @Override
super.onCreate(savedInstanceState); public void onCreate(Bundle savedInstanceState) {
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) { super.onCreate(savedInstanceState);
exit(); if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
} exit();
setContentView(R.layout.main); }
setContentView(R.layout.main);
loadSettings();
loadSettings();
View buttons = LayoutInflater.from(this).inflate(R.layout.main_buttons, null);
View buttons = LayoutInflater.from(this).inflate(R.layout.main_buttons, null);
final View serverButton = buttons.findViewById(R.id.main_select_server);
final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2); final View serverButton = buttons.findViewById(R.id.main_select_server);
final TextView serverTextView = (TextView) serverButton.findViewById(R.id.main_select_server_2);
final View albumsTitle = buttons.findViewById(R.id.main_albums);
final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest); final View albumsTitle = buttons.findViewById(R.id.main_albums);
final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random); final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest); final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent); final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent); final View albumsRecentButton = buttons.findViewById(R.id.main_albums_recent);
final View albumsFrequentButton = buttons.findViewById(R.id.main_albums_frequent);
final View dummyView = findViewById(R.id.main_dummy);
final View dummyView = findViewById(R.id.main_dummy);
int instance = Util.getActiveServer(this);
String name = Util.getServerName(this, instance); int instance = Util.getActiveServer(this);
serverTextView.setText(name); String name = Util.getServerName(this, instance);
serverTextView.setText(name);
ListView list = (ListView) findViewById(R.id.main_list);
ListView list = (ListView) findViewById(R.id.main_list);
MergeAdapter adapter = new MergeAdapter();
adapter.addViews(Arrays.asList(serverButton), true); MergeAdapter adapter = new MergeAdapter();
if (!Util.isOffline(this)) { adapter.addViews(Arrays.asList(serverButton), true);
adapter.addView(albumsTitle, false); if (!Util.isOffline(this)) {
adapter.addViews(Arrays.asList(albumsNewestButton, albumsRandomButton, albumsHighestButton, albumsRecentButton, albumsFrequentButton), true); adapter.addView(albumsTitle, false);
} adapter.addViews(Arrays.asList(albumsNewestButton, albumsRandomButton, albumsHighestButton, albumsRecentButton, albumsFrequentButton), true);
list.setAdapter(adapter); }
registerForContextMenu(dummyView); list.setAdapter(adapter);
registerForContextMenu(dummyView);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @Override
if (view == serverButton) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dummyView.showContextMenu(); if (view == serverButton) {
} else if (view == albumsNewestButton) { dummyView.showContextMenu();
showAlbumList("newest"); } else if (view == albumsNewestButton) {
} else if (view == albumsRandomButton) { showAlbumList("newest");
showAlbumList("random"); } else if (view == albumsRandomButton) {
} else if (view == albumsHighestButton) { showAlbumList("random");
showAlbumList("highest"); } else if (view == albumsHighestButton) {
} else if (view == albumsRecentButton) { showAlbumList("highest");
showAlbumList("recent"); } else if (view == albumsRecentButton) {
} else if (view == albumsFrequentButton) { showAlbumList("recent");
showAlbumList("frequent"); } else if (view == albumsFrequentButton) {
} showAlbumList("frequent");
} }
}); }
});
// Title: Subsonic
setTitle(R.string.common_appname); // Title: Subsonic
setTitle(R.string.common_appname);
// Button 1: shuffle
ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_1); // Button 1: search
actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle); ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_1);
actionShuffleButton.setOnClickListener(new View.OnClickListener() { actionSearchButton.setImageResource(R.drawable.ic_menu_search);
@Override actionSearchButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { @Override
Intent intent = new Intent(MainActivity.this, DownloadActivity.class); public void onClick(View view) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); Intent intent = new Intent(MainActivity.this, SearchActivity.class);
Util.startActivityWithoutTransition(MainActivity.this, intent); intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
} Util.startActivityWithoutTransition(MainActivity.this, intent);
}); }
});
// Button 2: search
ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2); // Button 2: shuffle
actionSearchButton.setImageResource(R.drawable.ic_menu_search); ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_2);
actionSearchButton.setOnClickListener(new View.OnClickListener() { actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
@Override actionShuffleButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { @Override
Intent intent = new Intent(MainActivity.this, SearchActivity.class); public void onClick(View view) {
intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true); Intent intent = new Intent(MainActivity.this, DownloadActivity.class);
Util.startActivityWithoutTransition(MainActivity.this, intent); intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
} Util.startActivityWithoutTransition(MainActivity.this, intent);
}); }
});
// Button 3: menu
ImageButton actionMenuButton = (ImageButton)findViewById(R.id.action_button_3); // Button 3: help
actionMenuButton.setImageResource(R.drawable.ic_menu_moreoverflow); ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
actionMenuButton.setOnClickListener(new View.OnClickListener() { actionHelpButton.setImageResource(R.drawable.ic_menu_help);
@Override actionHelpButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { @Override
openOptionsMenu(); public void onClick(View view) {
} startActivity(new Intent(MainActivity.this, HelpActivity.class));
}); }
});
// Remember the current theme.
theme = Util.getTheme(this); // Button 4: settings
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
showInfoDialog(); actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
} actionSettingsButton.setOnClickListener(new View.OnClickListener() {
@Override
private void loadSettings() { public void onClick(View view) {
PreferenceManager.setDefaultValues(this, R.xml.settings, false); startActivity(new Intent(MainActivity.this, SettingsActivity.class));
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()); // Remember the current theme.
editor.commit(); theme = Util.getTheme(this);
}
} showInfoDialog();
}
@Override
protected void onResume() { private void loadSettings() {
super.onResume(); PreferenceManager.setDefaultValues(this, R.xml.settings, false);
SharedPreferences prefs = Util.getPreferences(this);
// Restart activity if theme has changed. if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
if (theme != null && !theme.equals(Util.getTheme(this))) { SharedPreferences.Editor editor = prefs.edit();
restart(); editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
} editor.commit();
} }
}
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { @Override
super.onCreateContextMenu(menu, view, menuInfo); protected void onResume() {
super.onResume();
MenuItem menuItem1 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_1, MENU_ITEM_SERVER_1, Util.getServerName(this, 1));
MenuItem menuItem2 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_2, MENU_ITEM_SERVER_2, Util.getServerName(this, 2)); // Restart activity if theme has changed.
MenuItem menuItem3 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_3, MENU_ITEM_SERVER_3, Util.getServerName(this, 3)); if (theme != null && !theme.equals(Util.getTheme(this))) {
MenuItem menuItem4 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_OFFLINE, MENU_ITEM_OFFLINE, Util.getServerName(this, 0)); restart();
menu.setGroupCheckable(MENU_GROUP_SERVER, true, true); }
menu.setHeaderTitle(R.string.main_select_server); }
switch (Util.getActiveServer(this)) { @Override
case 0: public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
menuItem4.setChecked(true); super.onCreateContextMenu(menu, view, menuInfo);
break;
case 1: MenuItem menuItem1 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_1, MENU_ITEM_SERVER_1, Util.getServerName(this, 1));
menuItem1.setChecked(true); MenuItem menuItem2 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_2, MENU_ITEM_SERVER_2, Util.getServerName(this, 2));
break; MenuItem menuItem3 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_3, MENU_ITEM_SERVER_3, Util.getServerName(this, 3));
case 2: MenuItem menuItem4 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_OFFLINE, MENU_ITEM_OFFLINE, Util.getServerName(this, 0));
menuItem2.setChecked(true); menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
break; menu.setHeaderTitle(R.string.main_select_server);
case 3:
menuItem3.setChecked(true); switch (Util.getActiveServer(this)) {
break; case 0:
} menuItem4.setChecked(true);
} break;
case 1:
@Override menuItem1.setChecked(true);
public boolean onContextItemSelected(MenuItem menuItem) { break;
switch (menuItem.getItemId()) { case 2:
case MENU_ITEM_OFFLINE: menuItem2.setChecked(true);
setActiveServer(0); break;
break; case 3:
case MENU_ITEM_SERVER_1: menuItem3.setChecked(true);
setActiveServer(1); break;
break; }
case MENU_ITEM_SERVER_2: }
setActiveServer(2);
break; @Override
case MENU_ITEM_SERVER_3: public boolean onContextItemSelected(MenuItem menuItem) {
setActiveServer(3); switch (menuItem.getItemId()) {
break; case MENU_ITEM_OFFLINE:
default: setActiveServer(0);
return super.onContextItemSelected(menuItem); break;
} case MENU_ITEM_SERVER_1:
setActiveServer(1);
// Restart activity break;
restart(); case MENU_ITEM_SERVER_2:
return true; setActiveServer(2);
} break;
case MENU_ITEM_SERVER_3:
private void setActiveServer(int instance) { setActiveServer(3);
if (Util.getActiveServer(this) != instance) { break;
DownloadService service = getDownloadService(); default:
if (service != null) { return super.onContextItemSelected(menuItem);
service.clearIncomplete(); }
}
Util.setActiveServer(this, instance); // Restart activity
} restart();
} return true;
}
private void restart() {
Intent intent = new Intent(this, MainActivity.class); private void setActiveServer(int instance) {
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); if (Util.getActiveServer(this) != instance) {
Util.startActivityWithoutTransition(this, intent); DownloadService service = getDownloadService();
} if (service != null) {
service.clearIncomplete();
private void exit() { }
stopService(new Intent(this, DownloadServiceImpl.class)); Util.setActiveServer(this, instance);
finish(); }
} }
private void showInfoDialog() { private void restart() {
if (!infoDialogDisplayed) { Intent intent = new Intent(this, MainActivity.class);
infoDialogDisplayed = true; intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) { Util.startActivityWithoutTransition(this, intent);
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text); }
}
} private void exit() {
} stopService(new Intent(this, DownloadServiceImpl.class));
finish();
private void showAlbumList(String type) { }
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type); private void showInfoDialog() {
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20); if (!infoDialogDisplayed) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0); infoDialogDisplayed = true;
Util.startActivityWithoutTransition(this, intent); if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) {
} Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
}
}
}
private void showAlbumList(String type) {
Intent intent = new Intent(this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
Util.startActivityWithoutTransition(this, intent);
}
} }

View File

@ -1,368 +1,388 @@
/* /*
This file is part of Subsonic. This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Subsonic is distributed in the hope that it will be useful, Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>. along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package net.sourceforge.subsonic.androidapp.activity; package net.sourceforge.subsonic.androidapp.activity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ListAdapter; import android.widget.ListAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import android.net.Uri; import android.net.Uri;
import net.sourceforge.subsonic.androidapp.R; import net.sourceforge.subsonic.androidapp.R;
import net.sourceforge.subsonic.androidapp.domain.Artist; import net.sourceforge.subsonic.androidapp.domain.Artist;
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory; import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
import net.sourceforge.subsonic.androidapp.domain.SearchCritera; import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
import net.sourceforge.subsonic.androidapp.domain.SearchResult; import net.sourceforge.subsonic.androidapp.domain.SearchResult;
import net.sourceforge.subsonic.androidapp.service.MusicService; import net.sourceforge.subsonic.androidapp.service.MusicService;
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory; import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
import net.sourceforge.subsonic.androidapp.service.DownloadService; import net.sourceforge.subsonic.androidapp.service.DownloadService;
import net.sourceforge.subsonic.androidapp.util.ArtistAdapter; import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
import net.sourceforge.subsonic.androidapp.util.BackgroundTask; import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Constants; import net.sourceforge.subsonic.androidapp.util.Constants;
import net.sourceforge.subsonic.androidapp.util.EntryAdapter; import net.sourceforge.subsonic.androidapp.util.EntryAdapter;
import net.sourceforge.subsonic.androidapp.util.MergeAdapter; import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask; import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Util; import net.sourceforge.subsonic.androidapp.util.Util;
/** /**
* Performs searches and displays the matching artists, albums and songs. * Performs searches and displays the matching artists, albums and songs.
* *
* @author Sindre Mehus * @author Sindre Mehus
*/ */
public class SearchActivity extends SubsonicTabActivity { public class SearchActivity extends SubsonicTabActivity {
private static final int DEFAULT_ARTISTS = 3; private static final int DEFAULT_ARTISTS = 3;
private static final int DEFAULT_ALBUMS = 5; private static final int DEFAULT_ALBUMS = 5;
private static final int DEFAULT_SONGS = 10; private static final int DEFAULT_SONGS = 10;
private static final int MAX_ARTISTS = 10; private static final int MAX_ARTISTS = 10;
private static final int MAX_ALBUMS = 20; private static final int MAX_ALBUMS = 20;
private static final int MAX_SONGS = 25; private static final int MAX_SONGS = 25;
private ListView list; private ListView list;
private View artistsHeading; private View artistsHeading;
private View albumsHeading; private View albumsHeading;
private View songsHeading; private View songsHeading;
private TextView searchButton; private TextView searchButton;
private View moreArtistsButton; private View moreArtistsButton;
private View moreAlbumsButton; private View moreAlbumsButton;
private View moreSongsButton; private View moreSongsButton;
private SearchResult searchResult; private SearchResult searchResult;
private MergeAdapter mergeAdapter; private MergeAdapter mergeAdapter;
private ArtistAdapter artistAdapter; private ArtistAdapter artistAdapter;
private ListAdapter moreArtistsAdapter; private ListAdapter moreArtistsAdapter;
private EntryAdapter albumAdapter; private EntryAdapter albumAdapter;
private ListAdapter moreAlbumsAdapter; private ListAdapter moreAlbumsAdapter;
private ListAdapter moreSongsAdapter; private ListAdapter moreSongsAdapter;
private EntryAdapter songAdapter; private EntryAdapter songAdapter;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.search); setContentView(R.layout.search);
setTitle(R.string.search_title); setTitle(R.string.search_title);
View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null); View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
artistsHeading = buttons.findViewById(R.id.search_artists); artistsHeading = buttons.findViewById(R.id.search_artists);
albumsHeading = buttons.findViewById(R.id.search_albums); albumsHeading = buttons.findViewById(R.id.search_albums);
songsHeading = buttons.findViewById(R.id.search_songs); songsHeading = buttons.findViewById(R.id.search_songs);
searchButton = (TextView) buttons.findViewById(R.id.search_search); searchButton = (TextView) buttons.findViewById(R.id.search_search);
moreArtistsButton = buttons.findViewById(R.id.search_more_artists); moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
moreAlbumsButton = buttons.findViewById(R.id.search_more_albums); moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
moreSongsButton = buttons.findViewById(R.id.search_more_songs); moreSongsButton = buttons.findViewById(R.id.search_more_songs);
list = (ListView) findViewById(R.id.search_list); list = (ListView) findViewById(R.id.search_list);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() { list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view == searchButton) { if (view == searchButton) {
onSearchRequested(); onSearchRequested();
} else if (view == moreArtistsButton) { } else if (view == moreArtistsButton) {
expandArtists(); expandArtists();
} else if (view == moreAlbumsButton) { } else if (view == moreAlbumsButton) {
expandAlbums(); expandAlbums();
} else if (view == moreSongsButton) { } else if (view == moreSongsButton) {
expandSongs(); expandSongs();
} else { } else {
Object item = parent.getItemAtPosition(position); Object item = parent.getItemAtPosition(position);
if (item instanceof Artist) { if (item instanceof Artist) {
onArtistSelected((Artist) item); onArtistSelected((Artist) item);
} else if (item instanceof MusicDirectory.Entry) { } else if (item instanceof MusicDirectory.Entry) {
MusicDirectory.Entry entry = (MusicDirectory.Entry) item; MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
if (entry.isDirectory()) { if (entry.isDirectory()) {
onAlbumSelected(entry, false); onAlbumSelected(entry, false);
} else if (entry.isVideo()) { } else if (entry.isVideo()) {
onVideoSelected(entry); onVideoSelected(entry);
} else { } else {
onSongSelected(entry, false, true, true, false); onSongSelected(entry, false, true, true, false);
} }
} }
} }
} }
}); });
registerForContextMenu(list); registerForContextMenu(list);
// Button 1: gone // Button 1: gone
findViewById(R.id.action_button_1).setVisibility(View.GONE); findViewById(R.id.action_button_1).setVisibility(View.GONE);
// Button 2: search // Button 2: search
final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2); final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
actionSearchButton.setImageResource(R.drawable.ic_menu_search); actionSearchButton.setImageResource(R.drawable.ic_menu_search);
actionSearchButton.setOnClickListener(new View.OnClickListener() { actionSearchButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
onSearchRequested(); onSearchRequested();
} }
}); });
onNewIntent(getIntent()); // Button 3: help
} ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
@Override actionHelpButton.setOnClickListener(new View.OnClickListener() {
protected void onNewIntent(Intent intent) { @Override
super.onNewIntent(intent); public void onClick(View view) {
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY); startActivity(new Intent(SearchActivity.this, HelpActivity.class));
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); }
boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false); });
if (query != null) { // Button 4: settings
mergeAdapter = new MergeAdapter(); ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
list.setAdapter(mergeAdapter); actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
search(query, autoplay); actionSettingsButton.setOnClickListener(new View.OnClickListener() {
} else { @Override
populateList(); public void onClick(View view) {
if (requestsearch) startActivity(new Intent(SearchActivity.this, SettingsActivity.class));
onSearchRequested(); }
} });
}
onNewIntent(getIntent());
@Override }
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo); @Override
protected void onNewIntent(Intent intent) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; super.onNewIntent(intent);
Object selectedItem = list.getItemAtPosition(info.position); String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
boolean isArtist = selectedItem instanceof Artist; boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
boolean isSong = selectedItem instanceof MusicDirectory.Entry && (!((MusicDirectory.Entry) selectedItem).isDirectory()) if (query != null) {
&& (!((MusicDirectory.Entry) selectedItem).isVideo()); mergeAdapter = new MergeAdapter();
list.setAdapter(mergeAdapter);
if (isArtist || isAlbum) { search(query, autoplay);
MenuInflater inflater = getMenuInflater(); } else {
inflater.inflate(R.menu.select_album_context, menu); populateList();
} else if (isSong) { if (requestsearch)
MenuInflater inflater = getMenuInflater(); onSearchRequested();
inflater.inflate(R.menu.select_song_context, menu); }
} }
}
@Override
@Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
public boolean onContextItemSelected(MenuItem menuItem) { super.onCreateContextMenu(menu, view, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
Object selectedItem = list.getItemAtPosition(info.position); AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
Object selectedItem = list.getItemAtPosition(info.position);
Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
MusicDirectory.Entry entry = selectedItem instanceof MusicDirectory.Entry ? (MusicDirectory.Entry) selectedItem : null; boolean isArtist = selectedItem instanceof Artist;
String id = artist != null ? artist.getId() : entry.getId(); boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
boolean isSong = selectedItem instanceof MusicDirectory.Entry && (!((MusicDirectory.Entry) selectedItem).isDirectory())
switch (menuItem.getItemId()) { && (!((MusicDirectory.Entry) selectedItem).isVideo());
case R.id.album_menu_play_now:
downloadRecursively(id, false, false, true); if (isArtist || isAlbum) {
break; MenuInflater inflater = getMenuInflater();
case R.id.album_menu_play_last: inflater.inflate(R.menu.select_album_context, menu);
downloadRecursively(id, false, true, false); } else if (isSong) {
break; MenuInflater inflater = getMenuInflater();
case R.id.album_menu_pin: inflater.inflate(R.menu.select_song_context, menu);
downloadRecursively(id, true, true, false); }
break; }
case R.id.song_menu_play_now:
onSongSelected(entry, false, false, true, false); @Override
break; public boolean onContextItemSelected(MenuItem menuItem) {
case R.id.song_menu_play_next: AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
onSongSelected(entry, false, true, false, true); Object selectedItem = list.getItemAtPosition(info.position);
break;
case R.id.song_menu_play_last: Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null;
onSongSelected(entry, false, true, false, false); MusicDirectory.Entry entry = selectedItem instanceof MusicDirectory.Entry ? (MusicDirectory.Entry) selectedItem : null;
break; String id = artist != null ? artist.getId() : entry.getId();
default:
return super.onContextItemSelected(menuItem); switch (menuItem.getItemId()) {
} case R.id.album_menu_play_now:
downloadRecursively(id, false, false, true);
return true; break;
} case R.id.album_menu_play_last:
downloadRecursively(id, false, true, false);
private void search(final String query, final boolean autoplay) { break;
BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this) { case R.id.album_menu_pin:
@Override downloadRecursively(id, true, true, false);
protected SearchResult doInBackground() throws Throwable { break;
SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS); case R.id.song_menu_play_now:
MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this); onSongSelected(entry, false, false, true, false);
return service.search(criteria, SearchActivity.this, this); break;
} case R.id.song_menu_play_next:
onSongSelected(entry, false, true, false, true);
@Override break;
protected void done(SearchResult result) { case R.id.song_menu_play_last:
searchResult = result; onSongSelected(entry, false, true, false, false);
populateList(); break;
if (autoplay) { default:
autoplay(); return super.onContextItemSelected(menuItem);
} }
} return true;
}; }
task.execute();
} private void search(final String query, final boolean autoplay) {
BackgroundTask<SearchResult> task = new TabActivityBackgroundTask<SearchResult>(this) {
private void populateList() { @Override
mergeAdapter = new MergeAdapter(); protected SearchResult doInBackground() throws Throwable {
mergeAdapter.addView(searchButton, true); SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
if (searchResult != null) { return service.search(criteria, SearchActivity.this, this);
List<Artist> artists = searchResult.getArtists(); }
if (!artists.isEmpty()) {
mergeAdapter.addView(artistsHeading); @Override
List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size()))); protected void done(SearchResult result) {
artistAdapter = new ArtistAdapter(this, displayedArtists); searchResult = result;
mergeAdapter.addAdapter(artistAdapter); populateList();
if (artists.size() > DEFAULT_ARTISTS) { if (autoplay) {
moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true); autoplay();
} }
}
}
List<MusicDirectory.Entry> albums = searchResult.getAlbums(); };
if (!albums.isEmpty()) { task.execute();
mergeAdapter.addView(albumsHeading); }
List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false); private void populateList() {
mergeAdapter.addAdapter(albumAdapter); mergeAdapter = new MergeAdapter();
if (albums.size() > DEFAULT_ALBUMS) { mergeAdapter.addView(searchButton, true);
moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
} if (searchResult != null) {
} List<Artist> artists = searchResult.getArtists();
if (!artists.isEmpty()) {
List<MusicDirectory.Entry> songs = searchResult.getSongs(); mergeAdapter.addView(artistsHeading);
if (!songs.isEmpty()) { List<Artist> displayedArtists = new ArrayList<Artist>(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
mergeAdapter.addView(songsHeading); artistAdapter = new ArtistAdapter(this, displayedArtists);
List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size()))); mergeAdapter.addAdapter(artistAdapter);
songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false); if (artists.size() > DEFAULT_ARTISTS) {
mergeAdapter.addAdapter(songAdapter); moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
if (songs.size() > DEFAULT_SONGS) { }
moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true); }
}
} List<MusicDirectory.Entry> albums = searchResult.getAlbums();
if (!albums.isEmpty()) {
boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty(); mergeAdapter.addView(albumsHeading);
searchButton.setText(empty ? R.string.search_no_match : R.string.search_search); List<MusicDirectory.Entry> displayedAlbums = new ArrayList<MusicDirectory.Entry>(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
} albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
mergeAdapter.addAdapter(albumAdapter);
list.setAdapter(mergeAdapter); if (albums.size() > DEFAULT_ALBUMS) {
} moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
}
private void expandArtists() { }
artistAdapter.clear();
for (Artist artist : searchResult.getArtists()) { List<MusicDirectory.Entry> songs = searchResult.getSongs();
artistAdapter.add(artist); if (!songs.isEmpty()) {
} mergeAdapter.addView(songsHeading);
artistAdapter.notifyDataSetChanged(); List<MusicDirectory.Entry> displayedSongs = new ArrayList<MusicDirectory.Entry>(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
mergeAdapter.removeAdapter(moreArtistsAdapter); songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
mergeAdapter.notifyDataSetChanged(); mergeAdapter.addAdapter(songAdapter);
} if (songs.size() > DEFAULT_SONGS) {
moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
private void expandAlbums() { }
albumAdapter.clear(); }
for (MusicDirectory.Entry album : searchResult.getAlbums()) {
albumAdapter.add(album); boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
} searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
albumAdapter.notifyDataSetChanged(); }
mergeAdapter.removeAdapter(moreAlbumsAdapter);
mergeAdapter.notifyDataSetChanged(); list.setAdapter(mergeAdapter);
} }
private void expandSongs() { private void expandArtists() {
songAdapter.clear(); artistAdapter.clear();
for (MusicDirectory.Entry song : searchResult.getSongs()) { for (Artist artist : searchResult.getArtists()) {
songAdapter.add(song); artistAdapter.add(artist);
} }
songAdapter.notifyDataSetChanged(); artistAdapter.notifyDataSetChanged();
mergeAdapter.removeAdapter(moreSongsAdapter); mergeAdapter.removeAdapter(moreArtistsAdapter);
mergeAdapter.notifyDataSetChanged(); mergeAdapter.notifyDataSetChanged();
} }
private void onArtistSelected(Artist artist) { private void expandAlbums() {
Intent intent = new Intent(this, SelectAlbumActivity.class); albumAdapter.clear();
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId()); for (MusicDirectory.Entry album : searchResult.getAlbums()) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName()); albumAdapter.add(album);
Util.startActivityWithoutTransition(this, intent); }
} albumAdapter.notifyDataSetChanged();
mergeAdapter.removeAdapter(moreAlbumsAdapter);
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) { mergeAdapter.notifyDataSetChanged();
Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class); }
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle()); private void expandSongs() {
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay); songAdapter.clear();
Util.startActivityWithoutTransition(SearchActivity.this, intent); for (MusicDirectory.Entry song : searchResult.getSongs()) {
} songAdapter.add(song);
}
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) { songAdapter.notifyDataSetChanged();
DownloadService downloadService = getDownloadService(); mergeAdapter.removeAdapter(moreSongsAdapter);
if (downloadService != null) { mergeAdapter.notifyDataSetChanged();
if (!append) { }
downloadService.clear();
} private void onArtistSelected(Artist artist) {
downloadService.download(Arrays.asList(song), save, false, playNext); Intent intent = new Intent(this, SelectAlbumActivity.class);
if (autoplay) { intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
downloadService.play(downloadService.size() - 1); intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
} Util.startActivityWithoutTransition(this, intent);
}
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
} private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
} Intent intent = new Intent(SearchActivity.this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, album.getId());
private void onVideoSelected(MusicDirectory.Entry entry) { intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
Intent intent = new Intent(Intent.ACTION_VIEW); intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
intent.setData(Uri.parse(MusicServiceFactory.getMusicService(this).getVideoUrl(this, entry.getId()))); Util.startActivityWithoutTransition(SearchActivity.this, intent);
startActivity(intent); }
}
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
private void autoplay() { DownloadService downloadService = getDownloadService();
if (!searchResult.getSongs().isEmpty()) { if (downloadService != null) {
onSongSelected(searchResult.getSongs().get(0), false, false, true, false); if (!append) {
} else if (!searchResult.getAlbums().isEmpty()) { downloadService.clear();
onAlbumSelected(searchResult.getAlbums().get(0), true); }
} downloadService.download(Arrays.asList(song), save, false, playNext);
} if (autoplay) {
downloadService.play(downloadService.size() - 1);
}
Util.toast(SearchActivity.this, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
}
}
private void onVideoSelected(MusicDirectory.Entry entry) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(MusicServiceFactory.getMusicService(this).getVideoUrl(this, entry.getId())));
startActivity(intent);
}
private void autoplay() {
if (!searchResult.getSongs().isEmpty()) {
onSongSelected(searchResult.getSongs().get(0), false, false, true, false);
} else if (!searchResult.getAlbums().isEmpty()) {
onAlbumSelected(searchResult.getAlbums().get(0), true);
}
}
} }

View File

@ -190,6 +190,26 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
refresh(); refresh();
} }
}); });
// Button 3: help
ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
actionHelpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(SelectAlbumActivity.this, HelpActivity.class));
}
});
// Button 4: settings
ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
actionSettingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(SelectAlbumActivity.this, SettingsActivity.class));
}
});
} }
private void playAll() { private void playAll() {

View File

@ -1,228 +1,248 @@
/* /*
This file is part of Subsonic. This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Subsonic is distributed in the hope that it will be useful, Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>. along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package net.sourceforge.subsonic.androidapp.activity; package net.sourceforge.subsonic.androidapp.activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import net.sourceforge.subsonic.androidapp.R; import net.sourceforge.subsonic.androidapp.R;
import net.sourceforge.subsonic.androidapp.domain.Artist; import net.sourceforge.subsonic.androidapp.domain.Artist;
import net.sourceforge.subsonic.androidapp.domain.Indexes; import net.sourceforge.subsonic.androidapp.domain.Indexes;
import net.sourceforge.subsonic.androidapp.domain.MusicFolder; import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
import net.sourceforge.subsonic.androidapp.service.MusicService; import net.sourceforge.subsonic.androidapp.service.MusicService;
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory; import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
import net.sourceforge.subsonic.androidapp.util.ArtistAdapter; import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
import net.sourceforge.subsonic.androidapp.util.BackgroundTask; import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Constants; import net.sourceforge.subsonic.androidapp.util.Constants;
import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask; import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Util; import net.sourceforge.subsonic.androidapp.util.Util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener { public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
private static final int MENU_GROUP_MUSIC_FOLDER = 10; private static final int MENU_GROUP_MUSIC_FOLDER = 10;
private ListView artistList; private ListView artistList;
private View folderButton; private View folderButton;
private TextView folderName; private TextView folderName;
private List<MusicFolder> musicFolders; private List<MusicFolder> musicFolders;
/** /**
* Called when the activity is first created. * Called when the activity is first created.
*/ */
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.select_artist); setContentView(R.layout.select_artist);
artistList = (ListView) findViewById(R.id.select_artist_list); artistList = (ListView) findViewById(R.id.select_artist_list);
artistList.setOnItemClickListener(this); artistList.setOnItemClickListener(this);
folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistList, false); folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistList, false);
folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2); folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
if (!Util.isOffline(this)) { if (!Util.isOffline(this)) {
artistList.addHeaderView(folderButton); artistList.addHeaderView(folderButton);
} }
registerForContextMenu(artistList); registerForContextMenu(artistList);
setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label); setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
// Button 1: shuffle // Button 1: shuffle
ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_1); ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_1);
shuffleButton.setImageResource(R.drawable.ic_menu_shuffle); shuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
shuffleButton.setOnClickListener(new View.OnClickListener() { shuffleButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(SelectArtistActivity.this, DownloadActivity.class); Intent intent = new Intent(SelectArtistActivity.this, DownloadActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
Util.startActivityWithoutTransition(SelectArtistActivity.this, intent); Util.startActivityWithoutTransition(SelectArtistActivity.this, intent);
} }
}); });
// Button 2: refresh // Button 2: refresh
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2); ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
refreshButton.setImageResource(R.drawable.ic_menu_refresh); refreshButton.setImageResource(R.drawable.ic_menu_refresh);
refreshButton.setOnClickListener(new View.OnClickListener() { refreshButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
refresh(); refresh();
} }
}); });
musicFolders = null; // Button 3: help
load(); ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
} actionHelpButton.setImageResource(R.drawable.ic_menu_help);
actionHelpButton.setOnClickListener(new View.OnClickListener() {
private void refresh() { @Override
finish(); public void onClick(View view) {
Intent intent = getIntent(); startActivity(new Intent(SelectArtistActivity.this, HelpActivity.class));
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true); }
Util.startActivityWithoutTransition(this, intent); });
}
// Button 4: settings
private void selectFolder() { ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
folderButton.showContextMenu(); actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
} actionSettingsButton.setOnClickListener(new View.OnClickListener() {
@Override
private void load() { public void onClick(View view) {
BackgroundTask<Indexes> task = new TabActivityBackgroundTask<Indexes>(this) { startActivity(new Intent(SelectArtistActivity.this, SettingsActivity.class));
@Override }
protected Indexes doInBackground() throws Throwable { });
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this); musicFolders = null;
if (!Util.isOffline(SelectArtistActivity.this)) { load();
musicFolders = musicService.getMusicFolders(SelectArtistActivity.this, this); }
}
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this); private void refresh() {
return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this); finish();
} Intent intent = getIntent();
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
@Override Util.startActivityWithoutTransition(this, intent);
protected void done(Indexes result) { }
List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
artists.addAll(result.getShortcuts()); private void selectFolder() {
artists.addAll(result.getArtists()); folderButton.showContextMenu();
artistList.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists)); }
// Display selected music folder private void load() {
if (musicFolders != null) { BackgroundTask<Indexes> task = new TabActivityBackgroundTask<Indexes>(this) {
String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this); @Override
if (musicFolderId == null) { protected Indexes doInBackground() throws Throwable {
folderName.setText(R.string.select_artist_all_folders); boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
} else { MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
for (MusicFolder musicFolder : musicFolders) { if (!Util.isOffline(SelectArtistActivity.this)) {
if (musicFolder.getId().equals(musicFolderId)) { musicFolders = musicService.getMusicFolders(SelectArtistActivity.this, this);
folderName.setText(musicFolder.getName()); }
break; String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
} return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
} }
}
} @Override
} protected void done(Indexes result) {
}; List<Artist> artists = new ArrayList<Artist>(result.getShortcuts().size() + result.getArtists().size());
task.execute(); artists.addAll(result.getShortcuts());
} artists.addAll(result.getArtists());
artistList.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // Display selected music folder
if (view == folderButton) { if (musicFolders != null) {
selectFolder(); String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
} else { if (musicFolderId == null) {
Artist artist = (Artist) parent.getItemAtPosition(position); folderName.setText(R.string.select_artist_all_folders);
Intent intent = new Intent(this, SelectAlbumActivity.class); } else {
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId()); for (MusicFolder musicFolder : musicFolders) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName()); if (musicFolder.getId().equals(musicFolderId)) {
Util.startActivityWithoutTransition(this, intent); folderName.setText(musicFolder.getName());
} break;
} }
}
@Override }
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { }
super.onCreateContextMenu(menu, view, menuInfo); }
};
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; task.execute();
}
if (artistList.getItemAtPosition(info.position) instanceof Artist) {
MenuInflater inflater = getMenuInflater(); @Override
inflater.inflate(R.menu.select_artist_context, menu); public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
} else if (info.position == 0) { if (view == folderButton) {
String musicFolderId = Util.getSelectedMusicFolderId(this); selectFolder();
MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders); } else {
if (musicFolderId == null) { Artist artist = (Artist) parent.getItemAtPosition(position);
menuItem.setChecked(true); Intent intent = new Intent(this, SelectAlbumActivity.class);
} intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
if (musicFolders != null) { intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
for (int i = 0; i < musicFolders.size(); i++) { Util.startActivityWithoutTransition(this, intent);
MusicFolder musicFolder = musicFolders.get(i); }
menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, musicFolder.getName()); }
if (musicFolder.getId().equals(musicFolderId)) {
menuItem.setChecked(true); @Override
} public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
} super.onCreateContextMenu(menu, view, menuInfo);
}
menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true); AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
}
} if (artistList.getItemAtPosition(info.position) instanceof Artist) {
MenuInflater inflater = getMenuInflater();
@Override inflater.inflate(R.menu.select_artist_context, menu);
public boolean onContextItemSelected(MenuItem menuItem) { } else if (info.position == 0) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); String musicFolderId = Util.getSelectedMusicFolderId(this);
MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
Artist artist = (Artist) artistList.getItemAtPosition(info.position); if (musicFolderId == null) {
menuItem.setChecked(true);
if (artist != null) { }
switch (menuItem.getItemId()) { if (musicFolders != null) {
case R.id.artist_menu_play_now: for (int i = 0; i < musicFolders.size(); i++) {
downloadRecursively(artist.getId(), false, false, true); MusicFolder musicFolder = musicFolders.get(i);
break; menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, i, i + 1, musicFolder.getName());
case R.id.artist_menu_play_last: if (musicFolder.getId().equals(musicFolderId)) {
downloadRecursively(artist.getId(), false, true, false); menuItem.setChecked(true);
break; }
case R.id.artist_menu_pin: }
downloadRecursively(artist.getId(), true, true, false); }
break; menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
default: }
return super.onContextItemSelected(menuItem); }
}
} else if (info.position == 0) { @Override
MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId()); public boolean onContextItemSelected(MenuItem menuItem) {
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId(); AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders)
: selectedFolder.getName(); Artist artist = (Artist) artistList.getItemAtPosition(info.position);
Util.setSelectedMusicFolderId(this, musicFolderId);
folderName.setText(musicFolderName); if (artist != null) {
refresh(); switch (menuItem.getItemId()) {
} case R.id.artist_menu_play_now:
downloadRecursively(artist.getId(), false, false, true);
return true; break;
} case R.id.artist_menu_play_last:
downloadRecursively(artist.getId(), false, true, false);
break;
case R.id.artist_menu_pin:
downloadRecursively(artist.getId(), true, true, false);
break;
default:
return super.onContextItemSelected(menuItem);
}
} else if (info.position == 0) {
MusicFolder selectedFolder = menuItem.getItemId() == -1 ? null : musicFolders.get(menuItem.getItemId());
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
String musicFolderName = selectedFolder == null ? getString(R.string.select_artist_all_folders)
: selectedFolder.getName();
Util.setSelectedMusicFolderId(this, musicFolderId);
folderName.setText(musicFolderName);
refresh();
}
return true;
}
} }

View File

@ -1,146 +1,166 @@
/* /*
This file is part of Subsonic. This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Subsonic is distributed in the hope that it will be useful, Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>. along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package net.sourceforge.subsonic.androidapp.activity; package net.sourceforge.subsonic.androidapp.activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ListView; import android.widget.ListView;
import net.sourceforge.subsonic.androidapp.R; import net.sourceforge.subsonic.androidapp.R;
import net.sourceforge.subsonic.androidapp.domain.Playlist; import net.sourceforge.subsonic.androidapp.domain.Playlist;
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory; import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
import net.sourceforge.subsonic.androidapp.service.MusicService; import net.sourceforge.subsonic.androidapp.service.MusicService;
import net.sourceforge.subsonic.androidapp.util.BackgroundTask; import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Constants; import net.sourceforge.subsonic.androidapp.util.Constants;
import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask; import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Util; import net.sourceforge.subsonic.androidapp.util.Util;
import java.util.List; import java.util.List;
public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener { public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
private static final int MENU_ITEM_PLAY_ALL = 1; private static final int MENU_ITEM_PLAY_ALL = 1;
private ListView list; private ListView list;
private View emptyTextView; private View emptyTextView;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.select_playlist); setContentView(R.layout.select_playlist);
list = (ListView) findViewById(R.id.select_playlist_list); list = (ListView) findViewById(R.id.select_playlist_list);
emptyTextView = findViewById(R.id.select_playlist_empty); emptyTextView = findViewById(R.id.select_playlist_empty);
list.setOnItemClickListener(this); list.setOnItemClickListener(this);
registerForContextMenu(list); registerForContextMenu(list);
// Title: Playlists // Title: Playlists
setTitle(R.string.playlist_label); setTitle(R.string.playlist_label);
// Button 1: gone // Button 1: gone
ImageButton searchButton = (ImageButton)findViewById(R.id.action_button_1); ImageButton searchButton = (ImageButton)findViewById(R.id.action_button_1);
searchButton.setVisibility(View.GONE); searchButton.setVisibility(View.GONE);
// Button 2: refresh // Button 2: refresh
ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2); ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
refreshButton.setImageResource(R.drawable.ic_menu_refresh); refreshButton.setImageResource(R.drawable.ic_menu_refresh);
refreshButton.setOnClickListener(new View.OnClickListener() { refreshButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
refresh(); refresh();
} }
}); });
load(); // Button 3: help
} ImageButton actionHelpButton = (ImageButton)findViewById(R.id.action_button_3);
actionHelpButton.setImageResource(R.drawable.ic_menu_help);
private void refresh() { actionHelpButton.setOnClickListener(new View.OnClickListener() {
finish(); @Override
Intent intent = new Intent(this, SelectPlaylistActivity.class); public void onClick(View view) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true); startActivity(new Intent(SelectPlaylistActivity.this, HelpActivity.class));
Util.startActivityWithoutTransition(this, intent); }
} });
private void load() { // Button 4: settings
BackgroundTask<List<Playlist>> task = new TabActivityBackgroundTask<List<Playlist>>(this) { ImageButton actionSettingsButton = (ImageButton)findViewById(R.id.action_button_4);
@Override actionSettingsButton.setImageResource(R.drawable.ic_menu_settings);
protected List<Playlist> doInBackground() throws Throwable { actionSettingsButton.setOnClickListener(new View.OnClickListener() {
MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this); @Override
boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false); public void onClick(View view) {
return musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this); startActivity(new Intent(SelectPlaylistActivity.this, SettingsActivity.class));
} }
});
@Override
protected void done(List<Playlist> result) { load();
list.setAdapter(new PlaylistAdapter(result)); }
emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
} private void refresh() {
}; finish();
task.execute(); Intent intent = new Intent(this, SelectPlaylistActivity.class);
} intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
Util.startActivityWithoutTransition(this, intent);
@Override }
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo); private void load() {
menu.add(Menu.NONE, MENU_ITEM_PLAY_ALL, MENU_ITEM_PLAY_ALL, R.string.common_play_now); BackgroundTask<List<Playlist>> task = new TabActivityBackgroundTask<List<Playlist>>(this) {
} @Override
protected List<Playlist> doInBackground() throws Throwable {
@Override MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
public boolean onContextItemSelected(MenuItem menuItem) { boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo(); return musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this);
Playlist playlist = (Playlist) list.getItemAtPosition(info.position); }
switch (menuItem.getItemId()) { @Override
case MENU_ITEM_PLAY_ALL: protected void done(List<Playlist> result) {
Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class); list.setAdapter(new PlaylistAdapter(result));
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId()); emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName()); }
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); };
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent); task.execute();
break; }
default:
return super.onContextItemSelected(menuItem); @Override
} public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
return true; super.onCreateContextMenu(menu, view, menuInfo);
} menu.add(Menu.NONE, MENU_ITEM_PLAY_ALL, MENU_ITEM_PLAY_ALL, R.string.common_play_now);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { @Override
public boolean onContextItemSelected(MenuItem menuItem) {
Playlist playlist = (Playlist) parent.getItemAtPosition(position); AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
Playlist playlist = (Playlist) list.getItemAtPosition(info.position);
Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId()); switch (menuItem.getItemId()) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName()); case MENU_ITEM_PLAY_ALL:
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent); Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
} intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
private class PlaylistAdapter extends ArrayAdapter<Playlist> { intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
public PlaylistAdapter(List<Playlist> playlists) { Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
super(SelectPlaylistActivity.this, R.layout.playlist_list_item, playlists); break;
} default:
} return super.onContextItemSelected(menuItem);
}
return true;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Playlist playlist = (Playlist) parent.getItemAtPosition(position);
Intent intent = new Intent(SelectPlaylistActivity.this, SelectAlbumActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
intent.putExtra(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
}
private class PlaylistAdapter extends ArrayAdapter<Playlist> {
public PlaylistAdapter(List<Playlist> playlists) {
super(SelectPlaylistActivity.this, R.layout.playlist_list_item, playlists);
}
}
} }

View File

@ -1,387 +1,389 @@
/* /*
This file is part of Subsonic. This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Subsonic is distributed in the hope that it will be useful, Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Subsonic. If not, see <http://www.gnu.org/licenses/>. along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009 (C) Sindre Mehus Copyright 2009 (C) Sindre Mehus
*/ */
package net.sourceforge.subsonic.androidapp.activity; package net.sourceforge.subsonic.androidapp.activity;
import java.io.File; import java.io.File;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
import android.widget.TextView; import android.widget.TextView;
import net.sourceforge.subsonic.androidapp.R; import net.sourceforge.subsonic.androidapp.R;
import net.sourceforge.subsonic.androidapp.domain.MusicDirectory; import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
import net.sourceforge.subsonic.androidapp.service.DownloadService; import net.sourceforge.subsonic.androidapp.service.DownloadService;
import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl; import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
import net.sourceforge.subsonic.androidapp.service.MusicService; import net.sourceforge.subsonic.androidapp.service.MusicService;
import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory; import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
import net.sourceforge.subsonic.androidapp.util.Constants; import net.sourceforge.subsonic.androidapp.util.Constants;
import net.sourceforge.subsonic.androidapp.util.ImageLoader; import net.sourceforge.subsonic.androidapp.util.ImageLoader;
import net.sourceforge.subsonic.androidapp.util.ModalBackgroundTask; import net.sourceforge.subsonic.androidapp.util.ModalBackgroundTask;
import net.sourceforge.subsonic.androidapp.util.Util; import net.sourceforge.subsonic.androidapp.util.Util;
/** /**
* @author Sindre Mehus * @author Sindre Mehus
*/ */
public class SubsonicTabActivity extends Activity { public class SubsonicTabActivity extends Activity {
private static final String TAG = SubsonicTabActivity.class.getSimpleName(); private static final String TAG = SubsonicTabActivity.class.getSimpleName();
private static ImageLoader IMAGE_LOADER; private static ImageLoader IMAGE_LOADER;
private boolean destroyed; private boolean destroyed;
private View homeButton; private View homeButton;
private View musicButton; private View musicButton;
private View searchButton; private View searchButton;
private View playlistButton; private View playlistButton;
private View nowPlayingButton; private View nowPlayingButton;
@Override @Override
protected void onCreate(Bundle bundle) { protected void onCreate(Bundle bundle) {
setUncaughtExceptionHandler(); setUncaughtExceptionHandler();
applyTheme(); applyTheme();
super.onCreate(bundle); super.onCreate(bundle);
requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_NO_TITLE);
startService(new Intent(this, DownloadServiceImpl.class)); startService(new Intent(this, DownloadServiceImpl.class));
setVolumeControlStream(AudioManager.STREAM_MUSIC); setVolumeControlStream(AudioManager.STREAM_MUSIC);
} }
@Override @Override
protected void onPostCreate(Bundle bundle) { protected void onPostCreate(Bundle bundle) {
super.onPostCreate(bundle); super.onPostCreate(bundle);
homeButton = findViewById(R.id.button_bar_home); homeButton = findViewById(R.id.button_bar_home);
homeButton.setOnClickListener(new View.OnClickListener() { homeButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(SubsonicTabActivity.this, MainActivity.class); Intent intent = new Intent(SubsonicTabActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent); Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
} }
}); });
musicButton = findViewById(R.id.button_bar_music); musicButton = findViewById(R.id.button_bar_music);
musicButton.setOnClickListener(new View.OnClickListener() { musicButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(SubsonicTabActivity.this, SelectArtistActivity.class); Intent intent = new Intent(SubsonicTabActivity.this, SelectArtistActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent); Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
} }
}); });
searchButton = findViewById(R.id.button_bar_search); searchButton = findViewById(R.id.button_bar_search);
searchButton.setOnClickListener(new View.OnClickListener() { searchButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(SubsonicTabActivity.this, SearchActivity.class); Intent intent = new Intent(SubsonicTabActivity.this, SearchActivity.class);
intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true); intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent); Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
} }
}); });
playlistButton = findViewById(R.id.button_bar_playlists); playlistButton = findViewById(R.id.button_bar_playlists);
playlistButton.setOnClickListener(new View.OnClickListener() { playlistButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Intent intent = new Intent(SubsonicTabActivity.this, SelectPlaylistActivity.class); Intent intent = new Intent(SubsonicTabActivity.this, SelectPlaylistActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent); Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
} }
}); });
nowPlayingButton = findViewById(R.id.button_bar_now_playing); nowPlayingButton = findViewById(R.id.button_bar_now_playing);
nowPlayingButton.setOnClickListener(new View.OnClickListener() { nowPlayingButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class); Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
} }
}); });
if (this instanceof MainActivity) { if (this instanceof MainActivity) {
homeButton.setEnabled(false); homeButton.setEnabled(false);
} else if (this instanceof SelectAlbumActivity || this instanceof SelectArtistActivity) { } else if (this instanceof SelectAlbumActivity || this instanceof SelectArtistActivity) {
musicButton.setEnabled(false); musicButton.setEnabled(false);
} else if (this instanceof SearchActivity) { } else if (this instanceof SearchActivity) {
searchButton.setEnabled(false); searchButton.setEnabled(false);
} else if (this instanceof SelectPlaylistActivity) { } else if (this instanceof SelectPlaylistActivity) {
playlistButton.setEnabled(false); playlistButton.setEnabled(false);
} else if (this instanceof DownloadActivity || this instanceof LyricsActivity) { } else if (this instanceof DownloadActivity || this instanceof LyricsActivity) {
nowPlayingButton.setEnabled(false); nowPlayingButton.setEnabled(false);
} }
updateButtonVisibility(); updateButtonVisibility();
} }
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
Util.registerMediaButtonEventReceiver(this); Util.registerMediaButtonEventReceiver(this);
} }
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater(); if (android.os.Build.VERSION.SDK_INT < 11) {
inflater.inflate(R.menu.main, menu); MenuInflater inflater = getMenuInflater();
return true; inflater.inflate(R.menu.main, menu);
} }
return true;
@Override }
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { @Override
public boolean onOptionsItemSelected(MenuItem item) {
case R.id.menu_exit: switch (item.getItemId()) {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); case R.id.menu_exit:
intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true); Intent intent = new Intent(this, MainActivity.class);
Util.startActivityWithoutTransition(this, intent); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return true; intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
Util.startActivityWithoutTransition(this, intent);
case R.id.menu_settings: return true;
startActivity(new Intent(this, SettingsActivity.class));
return true; case R.id.menu_settings:
startActivity(new Intent(this, SettingsActivity.class));
case R.id.menu_help: return true;
startActivity(new Intent(this, HelpActivity.class));
return true; case R.id.menu_help:
} startActivity(new Intent(this, HelpActivity.class));
return true;
return false; }
}
return false;
@Override }
protected void onDestroy() {
super.onDestroy(); @Override
destroyed = true; protected void onDestroy() {
getImageLoader().clear(); super.onDestroy();
} destroyed = true;
getImageLoader().clear();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN; @Override
boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP; public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean isVolumeAdjust = isVolumeDown || isVolumeUp; boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN;
boolean isJukebox = getDownloadService() != null && getDownloadService().isJukeboxEnabled(); boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP;
boolean isVolumeAdjust = isVolumeDown || isVolumeUp;
if (isVolumeAdjust && isJukebox) { boolean isJukebox = getDownloadService() != null && getDownloadService().isJukeboxEnabled();
getDownloadService().adjustJukeboxVolume(isVolumeUp);
return true; if (isVolumeAdjust && isJukebox) {
} getDownloadService().adjustJukeboxVolume(isVolumeUp);
return super.onKeyDown(keyCode, event); return true;
} }
return super.onKeyDown(keyCode, event);
@Override }
public void finish() {
super.finish(); @Override
Util.disablePendingTransition(this); public void finish() {
} super.finish();
Util.disablePendingTransition(this);
@Override }
public void setTitle(CharSequence title) {
super.setTitle(title); @Override
public void setTitle(CharSequence title) {
// Set the font of title in the action bar. super.setTitle(title);
TextView text = (TextView) findViewById(R.id.actionbar_title_text);
Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf"); // Set the font of title in the action bar.
text.setTypeface(typeface); TextView text = (TextView) findViewById(R.id.actionbar_title_text);
Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf");
text.setText(title); text.setTypeface(typeface);
}
text.setText(title);
@Override }
public void setTitle(int titleId) {
setTitle(getString(titleId)); @Override
} public void setTitle(int titleId) {
setTitle(getString(titleId));
private void applyTheme() { }
String theme = Util.getTheme(this);
if ("dark".equals(theme)) { private void applyTheme() {
setTheme(R.style.Dark); String theme = Util.getTheme(this);
} else if ("light".equals(theme)) { if ("dark".equals(theme)) {
setTheme(R.style.Light); setTheme(R.style.Dark);
} else if ("fullscreen".equals(theme)) { } else if ("light".equals(theme)) {
setTheme(R.style.Fullscreen); setTheme(R.style.Light);
} else if ("fullscreenlight".equals(theme)) { } else if ("fullscreen".equals(theme)) {
setTheme(R.style.Fullscreenlight); setTheme(R.style.Fullscreen);
} } else if ("fullscreenlight".equals(theme)) {
} setTheme(R.style.Fullscreenlight);
}
public boolean isDestroyed() { }
return destroyed;
} public boolean isDestroyed() {
return destroyed;
private void updateButtonVisibility() { }
int visibility = Util.isOffline(this) ? View.GONE : View.VISIBLE;
searchButton.setVisibility(visibility); private void updateButtonVisibility() {
playlistButton.setVisibility(visibility); int visibility = Util.isOffline(this) ? View.GONE : View.VISIBLE;
} searchButton.setVisibility(visibility);
playlistButton.setVisibility(visibility);
public void setProgressVisible(boolean visible) { }
View view = findViewById(R.id.tab_progress);
if (view != null) { public void setProgressVisible(boolean visible) {
view.setVisibility(visible ? View.VISIBLE : View.GONE); View view = findViewById(R.id.tab_progress);
} if (view != null) {
} view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
public void updateProgress(String message) { }
TextView view = (TextView) findViewById(R.id.tab_progress_message);
if (view != null) { public void updateProgress(String message) {
view.setText(message); TextView view = (TextView) findViewById(R.id.tab_progress_message);
} if (view != null) {
} view.setText(message);
}
public DownloadService getDownloadService() { }
// If service is not available, request it to start and wait for it.
for (int i = 0; i < 5; i++) { public DownloadService getDownloadService() {
DownloadService downloadService = DownloadServiceImpl.getInstance(); // If service is not available, request it to start and wait for it.
if (downloadService != null) { for (int i = 0; i < 5; i++) {
return downloadService; DownloadService downloadService = DownloadServiceImpl.getInstance();
} if (downloadService != null) {
Log.w(TAG, "DownloadService not running. Attempting to start it."); return downloadService;
startService(new Intent(this, DownloadServiceImpl.class)); }
Util.sleepQuietly(50L); Log.w(TAG, "DownloadService not running. Attempting to start it.");
} startService(new Intent(this, DownloadServiceImpl.class));
return DownloadServiceImpl.getInstance(); Util.sleepQuietly(50L);
} }
return DownloadServiceImpl.getInstance();
protected void warnIfNetworkOrStorageUnavailable() { }
if (!Util.isExternalStoragePresent()) {
Util.toast(this, R.string.select_album_no_sdcard); protected void warnIfNetworkOrStorageUnavailable() {
} else if (!Util.isOffline(this) && !Util.isNetworkConnected(this)) { if (!Util.isExternalStoragePresent()) {
Util.toast(this, R.string.select_album_no_network); Util.toast(this, R.string.select_album_no_sdcard);
} } else if (!Util.isOffline(this) && !Util.isNetworkConnected(this)) {
} Util.toast(this, R.string.select_album_no_network);
}
protected synchronized ImageLoader getImageLoader() { }
if (IMAGE_LOADER == null) {
IMAGE_LOADER = new ImageLoader(this); protected synchronized ImageLoader getImageLoader() {
} if (IMAGE_LOADER == null) {
return IMAGE_LOADER; IMAGE_LOADER = new ImageLoader(this);
} }
return IMAGE_LOADER;
protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay) { }
ModalBackgroundTask<List<MusicDirectory.Entry>> task = new ModalBackgroundTask<List<MusicDirectory.Entry>>(this, false) {
protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay) {
private static final int MAX_SONGS = 500; ModalBackgroundTask<List<MusicDirectory.Entry>> task = new ModalBackgroundTask<List<MusicDirectory.Entry>>(this, false) {
@Override private static final int MAX_SONGS = 500;
protected List<MusicDirectory.Entry> doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this); @Override
MusicDirectory root = musicService.getMusicDirectory(id, false, SubsonicTabActivity.this, this); protected List<MusicDirectory.Entry> doInBackground() throws Throwable {
List<MusicDirectory.Entry> songs = new LinkedList<MusicDirectory.Entry>(); MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
getSongsRecursively(root, songs); MusicDirectory root = musicService.getMusicDirectory(id, false, SubsonicTabActivity.this, this);
return songs; List<MusicDirectory.Entry> songs = new LinkedList<MusicDirectory.Entry>();
} getSongsRecursively(root, songs);
return songs;
private void getSongsRecursively(MusicDirectory parent, List<MusicDirectory.Entry> songs) throws Exception { }
if (songs.size() > MAX_SONGS) {
return; private void getSongsRecursively(MusicDirectory parent, List<MusicDirectory.Entry> songs) throws Exception {
} if (songs.size() > MAX_SONGS) {
return;
for (MusicDirectory.Entry song : parent.getChildren(false, true)) { }
if (!song.isVideo()) {
songs.add(song); 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); }
getSongsRecursively(musicService.getMusicDirectory(dir.getId(), false, SubsonicTabActivity.this, this), songs); for (MusicDirectory.Entry dir : parent.getChildren(true, false)) {
} MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
} getSongsRecursively(musicService.getMusicDirectory(dir.getId(), false, SubsonicTabActivity.this, this), songs);
}
@Override }
protected void done(List<MusicDirectory.Entry> songs) {
DownloadService downloadService = getDownloadService(); @Override
if (!songs.isEmpty() && downloadService != null) { protected void done(List<MusicDirectory.Entry> songs) {
if (!append) { DownloadService downloadService = getDownloadService();
downloadService.clear(); if (!songs.isEmpty() && downloadService != null) {
} if (!append) {
warnIfNetworkOrStorageUnavailable(); downloadService.clear();
downloadService.download(songs, save, autoplay, false); }
Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class); warnIfNetworkOrStorageUnavailable();
} downloadService.download(songs, save, autoplay, false);
} Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
}; }
}
task.execute(); };
}
task.execute();
private void setUncaughtExceptionHandler() { }
Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
if (!(handler instanceof SubsonicUncaughtExceptionHandler)) { private void setUncaughtExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new SubsonicUncaughtExceptionHandler(this)); Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
} if (!(handler instanceof SubsonicUncaughtExceptionHandler)) {
} Thread.setDefaultUncaughtExceptionHandler(new SubsonicUncaughtExceptionHandler(this));
}
/** }
* Logs the stack trace of uncaught exceptions to a file on the SD card.
*/ /**
private static class SubsonicUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { * Logs the stack trace of uncaught exceptions to a file on the SD card.
*/
private final Thread.UncaughtExceptionHandler defaultHandler; private static class SubsonicUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private final Context context;
private final Thread.UncaughtExceptionHandler defaultHandler;
private SubsonicUncaughtExceptionHandler(Context context) { private final Context context;
this.context = context;
defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); private SubsonicUncaughtExceptionHandler(Context context) {
} this.context = context;
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
@Override }
public void uncaughtException(Thread thread, Throwable throwable) {
File file = null; @Override
PrintWriter printWriter = null; public void uncaughtException(Thread thread, Throwable throwable) {
try { File file = null;
PrintWriter printWriter = null;
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.sourceforge.subsonic.androidapp", 0); try {
file = new File(Environment.getExternalStorageDirectory(), "subsonic-stacktrace.txt");
printWriter = new PrintWriter(file); PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.sourceforge.subsonic.androidapp", 0);
printWriter.println("Android API level: " + Build.VERSION.SDK); file = new File(Environment.getExternalStorageDirectory(), "subsonic-stacktrace.txt");
printWriter.println("Subsonic version name: " + packageInfo.versionName); printWriter = new PrintWriter(file);
printWriter.println("Subsonic version code: " + packageInfo.versionCode); printWriter.println("Android API level: " + Build.VERSION.SDK);
printWriter.println(); printWriter.println("Subsonic version name: " + packageInfo.versionName);
throwable.printStackTrace(printWriter); printWriter.println("Subsonic version code: " + packageInfo.versionCode);
Log.i(TAG, "Stack trace written to " + file); printWriter.println();
} catch (Throwable x) { throwable.printStackTrace(printWriter);
Log.e(TAG, "Failed to write stack trace to " + file, x); Log.i(TAG, "Stack trace written to " + file);
} finally { } catch (Throwable x) {
Util.close(printWriter); Log.e(TAG, "Failed to write stack trace to " + file, x);
if (defaultHandler != null) { } finally {
defaultHandler.uncaughtException(thread, throwable); Util.close(printWriter);
} if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, throwable);
} }
}
} }
} }
}
}