diff --git a/res/layout/action_bar.xml b/res/layout/action_bar.xml
index c2f0343c..ea3b302a 100644
--- a/res/layout/action_bar.xml
+++ b/res/layout/action_bar.xml
@@ -19,7 +19,7 @@
a:paddingTop="2dip"
a:scaleType="centerInside"
a:src="@drawable/main_header_icon" />
- />
+ />
+
+
+ a:src="@drawable/ic_menu_settings" />
+
+
+ a:src="@drawable/ic_menu_shuffle" />
-
-
-
+
\ No newline at end of file
diff --git a/res/layout/main_buttons.xml b/res/layout/main_buttons.xml
index fa28cd72..de2cc574 100644
--- a/res/layout/main_buttons.xml
+++ b/res/layout/main_buttons.xml
@@ -13,12 +13,12 @@
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:minHeight="?android:attr/listPreferredItemHeight">
-
+
+ a:layout_width="wrap_content"
+ a:layout_height="wrap_content"
+ a:layout_gravity="center_vertical"
+ a:src="@drawable/ic_menu_select_artist_folder" />
.
-
- Copyright 2009 (C) Sindre Mehus
- */
-
-package net.sourceforge.subsonic.androidapp.activity;
-
-import java.util.Arrays;
-
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.service.DownloadService;
-import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
-import net.sourceforge.subsonic.androidapp.util.Util;
-import net.sourceforge.subsonic.androidapp.util.FileUtil;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import android.widget.TextView;
-
-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_ITEM_SERVER_2 = 102;
- private static final int MENU_ITEM_SERVER_3 = 103;
- private static final int MENU_ITEM_OFFLINE = 104;
-
- private String theme;
-
- private static boolean infoDialogDisplayed;
-
- /**
- * Called when the activity is first created.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
- exit();
- }
- setContentView(R.layout.main);
-
- loadSettings();
-
- 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 albumsTitle = buttons.findViewById(R.id.main_albums);
- final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
- final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
- final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
- 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);
-
- int instance = Util.getActiveServer(this);
- String name = Util.getServerName(this, instance);
- serverTextView.setText(name);
-
- ListView list = (ListView) findViewById(R.id.main_list);
-
- MergeAdapter adapter = new MergeAdapter();
- adapter.addViews(Arrays.asList(serverButton), true);
- if (!Util.isOffline(this)) {
- adapter.addView(albumsTitle, false);
- adapter.addViews(Arrays.asList(albumsNewestButton, albumsRandomButton, albumsHighestButton, albumsRecentButton, albumsFrequentButton), true);
- }
- list.setAdapter(adapter);
- registerForContextMenu(dummyView);
-
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (view == serverButton) {
- dummyView.showContextMenu();
- } else if (view == albumsNewestButton) {
- showAlbumList("newest");
- } else if (view == albumsRandomButton) {
- showAlbumList("random");
- } else if (view == albumsHighestButton) {
- showAlbumList("highest");
- } else if (view == albumsRecentButton) {
- showAlbumList("recent");
- } else if (view == albumsFrequentButton) {
- showAlbumList("frequent");
- }
- }
- });
-
- // Title: Subsonic
- setTitle(R.string.common_appname);
-
- // Button 1: shuffle
- ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_1);
- actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
- actionShuffleButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(MainActivity.this, DownloadActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
- Util.startActivityWithoutTransition(MainActivity.this, intent);
- }
- });
-
- // Button 2: search
- ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
- actionSearchButton.setImageResource(R.drawable.ic_menu_search);
- actionSearchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(MainActivity.this, SearchActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
- Util.startActivityWithoutTransition(MainActivity.this, intent);
- }
- });
-
- // Button 3: menu
- ImageButton actionMenuButton = (ImageButton)findViewById(R.id.action_button_3);
- actionMenuButton.setImageResource(R.drawable.ic_menu_moreoverflow);
- actionMenuButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- openOptionsMenu();
- }
- });
-
- // Remember the current theme.
- theme = Util.getTheme(this);
-
- showInfoDialog();
- }
-
- private void loadSettings() {
- PreferenceManager.setDefaultValues(this, R.xml.settings, false);
- SharedPreferences prefs = Util.getPreferences(this);
- if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
- editor.commit();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- // Restart activity if theme has changed.
- if (theme != null && !theme.equals(Util.getTheme(this))) {
- restart();
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
-
- 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));
- MenuItem menuItem3 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_3, MENU_ITEM_SERVER_3, Util.getServerName(this, 3));
- MenuItem menuItem4 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_OFFLINE, MENU_ITEM_OFFLINE, Util.getServerName(this, 0));
- menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
- menu.setHeaderTitle(R.string.main_select_server);
-
- switch (Util.getActiveServer(this)) {
- case 0:
- menuItem4.setChecked(true);
- break;
- case 1:
- menuItem1.setChecked(true);
- break;
- case 2:
- menuItem2.setChecked(true);
- break;
- case 3:
- menuItem3.setChecked(true);
- break;
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem menuItem) {
- switch (menuItem.getItemId()) {
- case MENU_ITEM_OFFLINE:
- setActiveServer(0);
- break;
- case MENU_ITEM_SERVER_1:
- setActiveServer(1);
- break;
- case MENU_ITEM_SERVER_2:
- setActiveServer(2);
- break;
- case MENU_ITEM_SERVER_3:
- setActiveServer(3);
- break;
- default:
- return super.onContextItemSelected(menuItem);
- }
-
- // Restart activity
- restart();
- return true;
- }
-
- private void setActiveServer(int instance) {
- if (Util.getActiveServer(this) != instance) {
- DownloadService service = getDownloadService();
- if (service != null) {
- service.clearIncomplete();
- }
- Util.setActiveServer(this, instance);
- }
- }
-
- private void restart() {
- Intent intent = new Intent(this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Util.startActivityWithoutTransition(this, intent);
- }
-
- private void exit() {
- stopService(new Intent(this, DownloadServiceImpl.class));
- finish();
- }
-
- private void showInfoDialog() {
- if (!infoDialogDisplayed) {
- infoDialogDisplayed = true;
- 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);
- }
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see .
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+
+package net.sourceforge.subsonic.androidapp.activity;
+
+import java.util.Arrays;
+
+import net.sourceforge.subsonic.androidapp.R;
+import net.sourceforge.subsonic.androidapp.service.DownloadService;
+import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
+import net.sourceforge.subsonic.androidapp.util.Constants;
+import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
+import net.sourceforge.subsonic.androidapp.util.Util;
+import net.sourceforge.subsonic.androidapp.util.FileUtil;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.TextView;
+
+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_ITEM_SERVER_2 = 102;
+ private static final int MENU_ITEM_SERVER_3 = 103;
+ private static final int MENU_ITEM_OFFLINE = 104;
+
+ private String theme;
+
+ private static boolean infoDialogDisplayed;
+
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
+ exit();
+ }
+ setContentView(R.layout.main);
+
+ loadSettings();
+
+ 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 albumsTitle = buttons.findViewById(R.id.main_albums);
+ final View albumsNewestButton = buttons.findViewById(R.id.main_albums_newest);
+ final View albumsRandomButton = buttons.findViewById(R.id.main_albums_random);
+ final View albumsHighestButton = buttons.findViewById(R.id.main_albums_highest);
+ 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);
+
+ int instance = Util.getActiveServer(this);
+ String name = Util.getServerName(this, instance);
+ serverTextView.setText(name);
+
+ ListView list = (ListView) findViewById(R.id.main_list);
+
+ MergeAdapter adapter = new MergeAdapter();
+ adapter.addViews(Arrays.asList(serverButton), true);
+ if (!Util.isOffline(this)) {
+ adapter.addView(albumsTitle, false);
+ adapter.addViews(Arrays.asList(albumsNewestButton, albumsRandomButton, albumsHighestButton, albumsRecentButton, albumsFrequentButton), true);
+ }
+ list.setAdapter(adapter);
+ registerForContextMenu(dummyView);
+
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (view == serverButton) {
+ dummyView.showContextMenu();
+ } else if (view == albumsNewestButton) {
+ showAlbumList("newest");
+ } else if (view == albumsRandomButton) {
+ showAlbumList("random");
+ } else if (view == albumsHighestButton) {
+ showAlbumList("highest");
+ } else if (view == albumsRecentButton) {
+ showAlbumList("recent");
+ } else if (view == albumsFrequentButton) {
+ showAlbumList("frequent");
+ }
+ }
+ });
+
+ // Title: Subsonic
+ setTitle(R.string.common_appname);
+
+ // Button 1: search
+ ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_1);
+ actionSearchButton.setImageResource(R.drawable.ic_menu_search);
+ actionSearchButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(MainActivity.this, SearchActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
+ Util.startActivityWithoutTransition(MainActivity.this, intent);
+ }
+ });
+
+ // Button 2: shuffle
+ ImageButton actionShuffleButton = (ImageButton)findViewById(R.id.action_button_2);
+ actionShuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
+ actionShuffleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(MainActivity.this, DownloadActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
+ Util.startActivityWithoutTransition(MainActivity.this, intent);
+ }
+ });
+
+ // 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(MainActivity.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(MainActivity.this, SettingsActivity.class));
+ }
+ });
+
+ // Remember the current theme.
+ theme = Util.getTheme(this);
+
+ showInfoDialog();
+ }
+
+ private void loadSettings() {
+ PreferenceManager.setDefaultValues(this, R.xml.settings, false);
+ SharedPreferences prefs = Util.getPreferences(this);
+ if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
+ editor.commit();
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ // Restart activity if theme has changed.
+ if (theme != null && !theme.equals(Util.getTheme(this))) {
+ restart();
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+
+ 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));
+ MenuItem menuItem3 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_3, MENU_ITEM_SERVER_3, Util.getServerName(this, 3));
+ MenuItem menuItem4 = menu.add(MENU_GROUP_SERVER, MENU_ITEM_OFFLINE, MENU_ITEM_OFFLINE, Util.getServerName(this, 0));
+ menu.setGroupCheckable(MENU_GROUP_SERVER, true, true);
+ menu.setHeaderTitle(R.string.main_select_server);
+
+ switch (Util.getActiveServer(this)) {
+ case 0:
+ menuItem4.setChecked(true);
+ break;
+ case 1:
+ menuItem1.setChecked(true);
+ break;
+ case 2:
+ menuItem2.setChecked(true);
+ break;
+ case 3:
+ menuItem3.setChecked(true);
+ break;
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ switch (menuItem.getItemId()) {
+ case MENU_ITEM_OFFLINE:
+ setActiveServer(0);
+ break;
+ case MENU_ITEM_SERVER_1:
+ setActiveServer(1);
+ break;
+ case MENU_ITEM_SERVER_2:
+ setActiveServer(2);
+ break;
+ case MENU_ITEM_SERVER_3:
+ setActiveServer(3);
+ break;
+ default:
+ return super.onContextItemSelected(menuItem);
+ }
+
+ // Restart activity
+ restart();
+ return true;
+ }
+
+ private void setActiveServer(int instance) {
+ if (Util.getActiveServer(this) != instance) {
+ DownloadService service = getDownloadService();
+ if (service != null) {
+ service.clearIncomplete();
+ }
+ Util.setActiveServer(this, instance);
+ }
+ }
+
+ private void restart() {
+ Intent intent = new Intent(this, MainActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Util.startActivityWithoutTransition(this, intent);
+ }
+
+ private void exit() {
+ stopService(new Intent(this, DownloadServiceImpl.class));
+ finish();
+ }
+
+ private void showInfoDialog() {
+ if (!infoDialogDisplayed) {
+ infoDialogDisplayed = true;
+ 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);
+ }
}
\ No newline at end of file
diff --git a/src/net/sourceforge/subsonic/androidapp/activity/SearchActivity.java b/src/net/sourceforge/subsonic/androidapp/activity/SearchActivity.java
index 31f70678..9ea95ad6 100644
--- a/src/net/sourceforge/subsonic/androidapp/activity/SearchActivity.java
+++ b/src/net/sourceforge/subsonic/androidapp/activity/SearchActivity.java
@@ -1,368 +1,388 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see .
-
- Copyright 2009 (C) Sindre Mehus
- */
-
-package net.sourceforge.subsonic.androidapp.activity;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Arrays;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.MenuItem;
-import android.widget.AdapterView;
-import android.widget.ImageButton;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.net.Uri;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
-import net.sourceforge.subsonic.androidapp.domain.SearchResult;
-import net.sourceforge.subsonic.androidapp.service.MusicService;
-import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
-import net.sourceforge.subsonic.androidapp.service.DownloadService;
-import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
-import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.EntryAdapter;
-import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
-import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * Performs searches and displays the matching artists, albums and songs.
- *
- * @author Sindre Mehus
- */
-public class SearchActivity extends SubsonicTabActivity {
-
- private static final int DEFAULT_ARTISTS = 3;
- private static final int DEFAULT_ALBUMS = 5;
- private static final int DEFAULT_SONGS = 10;
-
- private static final int MAX_ARTISTS = 10;
- private static final int MAX_ALBUMS = 20;
- private static final int MAX_SONGS = 25;
- private ListView list;
-
- private View artistsHeading;
- private View albumsHeading;
- private View songsHeading;
- private TextView searchButton;
- private View moreArtistsButton;
- private View moreAlbumsButton;
- private View moreSongsButton;
- private SearchResult searchResult;
- private MergeAdapter mergeAdapter;
- private ArtistAdapter artistAdapter;
- private ListAdapter moreArtistsAdapter;
- private EntryAdapter albumAdapter;
- private ListAdapter moreAlbumsAdapter;
- private ListAdapter moreSongsAdapter;
- private EntryAdapter songAdapter;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.search);
-
- setTitle(R.string.search_title);
-
- View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
-
- artistsHeading = buttons.findViewById(R.id.search_artists);
- albumsHeading = buttons.findViewById(R.id.search_albums);
- songsHeading = buttons.findViewById(R.id.search_songs);
-
- searchButton = (TextView) buttons.findViewById(R.id.search_search);
- moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
- moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
- moreSongsButton = buttons.findViewById(R.id.search_more_songs);
-
- list = (ListView) findViewById(R.id.search_list);
-
- list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (view == searchButton) {
- onSearchRequested();
- } else if (view == moreArtistsButton) {
- expandArtists();
- } else if (view == moreAlbumsButton) {
- expandAlbums();
- } else if (view == moreSongsButton) {
- expandSongs();
- } else {
- Object item = parent.getItemAtPosition(position);
- if (item instanceof Artist) {
- onArtistSelected((Artist) item);
- } else if (item instanceof MusicDirectory.Entry) {
- MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
- if (entry.isDirectory()) {
- onAlbumSelected(entry, false);
- } else if (entry.isVideo()) {
- onVideoSelected(entry);
- } else {
- onSongSelected(entry, false, true, true, false);
- }
-
- }
- }
- }
- });
- registerForContextMenu(list);
-
- // Button 1: gone
- findViewById(R.id.action_button_1).setVisibility(View.GONE);
-
- // Button 2: search
- final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
- actionSearchButton.setImageResource(R.drawable.ic_menu_search);
- actionSearchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onSearchRequested();
- }
- });
-
- onNewIntent(getIntent());
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
- boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
- boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
-
- if (query != null) {
- mergeAdapter = new MergeAdapter();
- list.setAdapter(mergeAdapter);
- search(query, autoplay);
- } else {
- populateList();
- if (requestsearch)
- onSearchRequested();
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
- Object selectedItem = list.getItemAtPosition(info.position);
-
- boolean isArtist = selectedItem instanceof Artist;
- boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
- boolean isSong = selectedItem instanceof MusicDirectory.Entry && (!((MusicDirectory.Entry) selectedItem).isDirectory())
- && (!((MusicDirectory.Entry) selectedItem).isVideo());
-
- if (isArtist || isAlbum) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.select_album_context, menu);
- } else if (isSong) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.select_song_context, menu);
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem menuItem) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- 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;
- String id = artist != null ? artist.getId() : entry.getId();
-
- switch (menuItem.getItemId()) {
- case R.id.album_menu_play_now:
- downloadRecursively(id, false, false, true);
- break;
- case R.id.album_menu_play_last:
- downloadRecursively(id, false, true, false);
- break;
- case R.id.album_menu_pin:
- downloadRecursively(id, true, true, false);
- break;
- case R.id.song_menu_play_now:
- onSongSelected(entry, false, false, true, false);
- break;
- case R.id.song_menu_play_next:
- onSongSelected(entry, false, true, false, true);
- break;
- case R.id.song_menu_play_last:
- onSongSelected(entry, false, true, false, false);
- break;
- default:
- return super.onContextItemSelected(menuItem);
- }
-
- return true;
- }
-
- private void search(final String query, final boolean autoplay) {
- BackgroundTask task = new TabActivityBackgroundTask(this) {
- @Override
- protected SearchResult doInBackground() throws Throwable {
- SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
- MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
- return service.search(criteria, SearchActivity.this, this);
- }
-
- @Override
- protected void done(SearchResult result) {
- searchResult = result;
- populateList();
- if (autoplay) {
- autoplay();
- }
-
- }
- };
- task.execute();
- }
-
- private void populateList() {
- mergeAdapter = new MergeAdapter();
- mergeAdapter.addView(searchButton, true);
-
- if (searchResult != null) {
- List artists = searchResult.getArtists();
- if (!artists.isEmpty()) {
- mergeAdapter.addView(artistsHeading);
- List displayedArtists = new ArrayList(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
- artistAdapter = new ArtistAdapter(this, displayedArtists);
- mergeAdapter.addAdapter(artistAdapter);
- if (artists.size() > DEFAULT_ARTISTS) {
- moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
- }
- }
-
- List albums = searchResult.getAlbums();
- if (!albums.isEmpty()) {
- mergeAdapter.addView(albumsHeading);
- List displayedAlbums = new ArrayList(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
- albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
- mergeAdapter.addAdapter(albumAdapter);
- if (albums.size() > DEFAULT_ALBUMS) {
- moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
- }
- }
-
- List songs = searchResult.getSongs();
- if (!songs.isEmpty()) {
- mergeAdapter.addView(songsHeading);
- List displayedSongs = new ArrayList(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
- songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
- mergeAdapter.addAdapter(songAdapter);
- if (songs.size() > DEFAULT_SONGS) {
- moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
- }
- }
-
- boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
- searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
- }
-
- list.setAdapter(mergeAdapter);
- }
-
- private void expandArtists() {
- artistAdapter.clear();
- for (Artist artist : searchResult.getArtists()) {
- artistAdapter.add(artist);
- }
- artistAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreArtistsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
- private void expandAlbums() {
- albumAdapter.clear();
- for (MusicDirectory.Entry album : searchResult.getAlbums()) {
- albumAdapter.add(album);
- }
- albumAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreAlbumsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
- private void expandSongs() {
- songAdapter.clear();
- for (MusicDirectory.Entry song : searchResult.getSongs()) {
- songAdapter.add(song);
- }
- songAdapter.notifyDataSetChanged();
- mergeAdapter.removeAdapter(moreSongsAdapter);
- mergeAdapter.notifyDataSetChanged();
- }
-
- private void onArtistSelected(Artist artist) {
- Intent intent = new Intent(this, SelectAlbumActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- Util.startActivityWithoutTransition(this, intent);
- }
-
- 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());
- intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
- intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
- Util.startActivityWithoutTransition(SearchActivity.this, intent);
- }
-
- private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
- DownloadService downloadService = getDownloadService();
- if (downloadService != null) {
- if (!append) {
- downloadService.clear();
- }
- 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);
- }
- }
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see .
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+
+package net.sourceforge.subsonic.androidapp.activity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Arrays;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.MenuItem;
+import android.widget.AdapterView;
+import android.widget.ImageButton;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.net.Uri;
+import net.sourceforge.subsonic.androidapp.R;
+import net.sourceforge.subsonic.androidapp.domain.Artist;
+import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
+import net.sourceforge.subsonic.androidapp.domain.SearchCritera;
+import net.sourceforge.subsonic.androidapp.domain.SearchResult;
+import net.sourceforge.subsonic.androidapp.service.MusicService;
+import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
+import net.sourceforge.subsonic.androidapp.service.DownloadService;
+import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
+import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Constants;
+import net.sourceforge.subsonic.androidapp.util.EntryAdapter;
+import net.sourceforge.subsonic.androidapp.util.MergeAdapter;
+import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Util;
+
+/**
+ * Performs searches and displays the matching artists, albums and songs.
+ *
+ * @author Sindre Mehus
+ */
+public class SearchActivity extends SubsonicTabActivity {
+
+ private static final int DEFAULT_ARTISTS = 3;
+ private static final int DEFAULT_ALBUMS = 5;
+ private static final int DEFAULT_SONGS = 10;
+
+ private static final int MAX_ARTISTS = 10;
+ private static final int MAX_ALBUMS = 20;
+ private static final int MAX_SONGS = 25;
+ private ListView list;
+
+ private View artistsHeading;
+ private View albumsHeading;
+ private View songsHeading;
+ private TextView searchButton;
+ private View moreArtistsButton;
+ private View moreAlbumsButton;
+ private View moreSongsButton;
+ private SearchResult searchResult;
+ private MergeAdapter mergeAdapter;
+ private ArtistAdapter artistAdapter;
+ private ListAdapter moreArtistsAdapter;
+ private EntryAdapter albumAdapter;
+ private ListAdapter moreAlbumsAdapter;
+ private ListAdapter moreSongsAdapter;
+ private EntryAdapter songAdapter;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.search);
+
+ setTitle(R.string.search_title);
+
+ View buttons = LayoutInflater.from(this).inflate(R.layout.search_buttons, null);
+
+ artistsHeading = buttons.findViewById(R.id.search_artists);
+ albumsHeading = buttons.findViewById(R.id.search_albums);
+ songsHeading = buttons.findViewById(R.id.search_songs);
+
+ searchButton = (TextView) buttons.findViewById(R.id.search_search);
+ moreArtistsButton = buttons.findViewById(R.id.search_more_artists);
+ moreAlbumsButton = buttons.findViewById(R.id.search_more_albums);
+ moreSongsButton = buttons.findViewById(R.id.search_more_songs);
+
+ list = (ListView) findViewById(R.id.search_list);
+
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (view == searchButton) {
+ onSearchRequested();
+ } else if (view == moreArtistsButton) {
+ expandArtists();
+ } else if (view == moreAlbumsButton) {
+ expandAlbums();
+ } else if (view == moreSongsButton) {
+ expandSongs();
+ } else {
+ Object item = parent.getItemAtPosition(position);
+ if (item instanceof Artist) {
+ onArtistSelected((Artist) item);
+ } else if (item instanceof MusicDirectory.Entry) {
+ MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
+ if (entry.isDirectory()) {
+ onAlbumSelected(entry, false);
+ } else if (entry.isVideo()) {
+ onVideoSelected(entry);
+ } else {
+ onSongSelected(entry, false, true, true, false);
+ }
+
+ }
+ }
+ }
+ });
+ registerForContextMenu(list);
+
+ // Button 1: gone
+ findViewById(R.id.action_button_1).setVisibility(View.GONE);
+
+ // Button 2: search
+ final ImageButton actionSearchButton = (ImageButton)findViewById(R.id.action_button_2);
+ actionSearchButton.setImageResource(R.drawable.ic_menu_search);
+ actionSearchButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onSearchRequested();
+ }
+ });
+
+ // 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(SearchActivity.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(SearchActivity.this, SettingsActivity.class));
+ }
+ });
+
+ onNewIntent(getIntent());
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
+ boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
+ boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
+
+ if (query != null) {
+ mergeAdapter = new MergeAdapter();
+ list.setAdapter(mergeAdapter);
+ search(query, autoplay);
+ } else {
+ populateList();
+ if (requestsearch)
+ onSearchRequested();
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ Object selectedItem = list.getItemAtPosition(info.position);
+
+ boolean isArtist = selectedItem instanceof Artist;
+ boolean isAlbum = selectedItem instanceof MusicDirectory.Entry && ((MusicDirectory.Entry) selectedItem).isDirectory();
+ boolean isSong = selectedItem instanceof MusicDirectory.Entry && (!((MusicDirectory.Entry) selectedItem).isDirectory())
+ && (!((MusicDirectory.Entry) selectedItem).isVideo());
+
+ if (isArtist || isAlbum) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.select_album_context, menu);
+ } else if (isSong) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.select_song_context, menu);
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
+ 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;
+ String id = artist != null ? artist.getId() : entry.getId();
+
+ switch (menuItem.getItemId()) {
+ case R.id.album_menu_play_now:
+ downloadRecursively(id, false, false, true);
+ break;
+ case R.id.album_menu_play_last:
+ downloadRecursively(id, false, true, false);
+ break;
+ case R.id.album_menu_pin:
+ downloadRecursively(id, true, true, false);
+ break;
+ case R.id.song_menu_play_now:
+ onSongSelected(entry, false, false, true, false);
+ break;
+ case R.id.song_menu_play_next:
+ onSongSelected(entry, false, true, false, true);
+ break;
+ case R.id.song_menu_play_last:
+ onSongSelected(entry, false, true, false, false);
+ break;
+ default:
+ return super.onContextItemSelected(menuItem);
+ }
+
+ return true;
+ }
+
+ private void search(final String query, final boolean autoplay) {
+ BackgroundTask task = new TabActivityBackgroundTask(this) {
+ @Override
+ protected SearchResult doInBackground() throws Throwable {
+ SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
+ MusicService service = MusicServiceFactory.getMusicService(SearchActivity.this);
+ return service.search(criteria, SearchActivity.this, this);
+ }
+
+ @Override
+ protected void done(SearchResult result) {
+ searchResult = result;
+ populateList();
+ if (autoplay) {
+ autoplay();
+ }
+
+ }
+ };
+ task.execute();
+ }
+
+ private void populateList() {
+ mergeAdapter = new MergeAdapter();
+ mergeAdapter.addView(searchButton, true);
+
+ if (searchResult != null) {
+ List artists = searchResult.getArtists();
+ if (!artists.isEmpty()) {
+ mergeAdapter.addView(artistsHeading);
+ List displayedArtists = new ArrayList(artists.subList(0, Math.min(DEFAULT_ARTISTS, artists.size())));
+ artistAdapter = new ArtistAdapter(this, displayedArtists);
+ mergeAdapter.addAdapter(artistAdapter);
+ if (artists.size() > DEFAULT_ARTISTS) {
+ moreArtistsAdapter = mergeAdapter.addView(moreArtistsButton, true);
+ }
+ }
+
+ List albums = searchResult.getAlbums();
+ if (!albums.isEmpty()) {
+ mergeAdapter.addView(albumsHeading);
+ List displayedAlbums = new ArrayList(albums.subList(0, Math.min(DEFAULT_ALBUMS, albums.size())));
+ albumAdapter = new EntryAdapter(this, getImageLoader(), displayedAlbums, false);
+ mergeAdapter.addAdapter(albumAdapter);
+ if (albums.size() > DEFAULT_ALBUMS) {
+ moreAlbumsAdapter = mergeAdapter.addView(moreAlbumsButton, true);
+ }
+ }
+
+ List songs = searchResult.getSongs();
+ if (!songs.isEmpty()) {
+ mergeAdapter.addView(songsHeading);
+ List displayedSongs = new ArrayList(songs.subList(0, Math.min(DEFAULT_SONGS, songs.size())));
+ songAdapter = new EntryAdapter(this, getImageLoader(), displayedSongs, false);
+ mergeAdapter.addAdapter(songAdapter);
+ if (songs.size() > DEFAULT_SONGS) {
+ moreSongsAdapter = mergeAdapter.addView(moreSongsButton, true);
+ }
+ }
+
+ boolean empty = searchResult.getArtists().isEmpty() && searchResult.getAlbums().isEmpty() && searchResult.getSongs().isEmpty();
+ searchButton.setText(empty ? R.string.search_no_match : R.string.search_search);
+ }
+
+ list.setAdapter(mergeAdapter);
+ }
+
+ private void expandArtists() {
+ artistAdapter.clear();
+ for (Artist artist : searchResult.getArtists()) {
+ artistAdapter.add(artist);
+ }
+ artistAdapter.notifyDataSetChanged();
+ mergeAdapter.removeAdapter(moreArtistsAdapter);
+ mergeAdapter.notifyDataSetChanged();
+ }
+
+ private void expandAlbums() {
+ albumAdapter.clear();
+ for (MusicDirectory.Entry album : searchResult.getAlbums()) {
+ albumAdapter.add(album);
+ }
+ albumAdapter.notifyDataSetChanged();
+ mergeAdapter.removeAdapter(moreAlbumsAdapter);
+ mergeAdapter.notifyDataSetChanged();
+ }
+
+ private void expandSongs() {
+ songAdapter.clear();
+ for (MusicDirectory.Entry song : searchResult.getSongs()) {
+ songAdapter.add(song);
+ }
+ songAdapter.notifyDataSetChanged();
+ mergeAdapter.removeAdapter(moreSongsAdapter);
+ mergeAdapter.notifyDataSetChanged();
+ }
+
+ private void onArtistSelected(Artist artist) {
+ Intent intent = new Intent(this, SelectAlbumActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ Util.startActivityWithoutTransition(this, intent);
+ }
+
+ 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());
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, autoplay);
+ Util.startActivityWithoutTransition(SearchActivity.this, intent);
+ }
+
+ private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
+ DownloadService downloadService = getDownloadService();
+ if (downloadService != null) {
+ if (!append) {
+ downloadService.clear();
+ }
+ 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);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java b/src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java
index 4c7fb4b0..3cec42cd 100644
--- a/src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java
+++ b/src/net/sourceforge/subsonic/androidapp/activity/SelectAlbumActivity.java
@@ -190,6 +190,26 @@ public class SelectAlbumActivity extends SubsonicTabActivity {
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() {
diff --git a/src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java b/src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java
index 1a444868..4e74404b 100644
--- a/src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java
+++ b/src/net/sourceforge/subsonic/androidapp/activity/SelectArtistActivity.java
@@ -1,228 +1,248 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see .
-
- Copyright 2009 (C) Sindre Mehus
- */
-
-package net.sourceforge.subsonic.androidapp.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import android.widget.TextView;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Artist;
-import net.sourceforge.subsonic.androidapp.domain.Indexes;
-import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
-import net.sourceforge.subsonic.androidapp.service.MusicService;
-import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
-import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
-import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
-
- private static final int MENU_GROUP_MUSIC_FOLDER = 10;
-
- private ListView artistList;
- private View folderButton;
- private TextView folderName;
- private List musicFolders;
-
- /**
- * Called when the activity is first created.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.select_artist);
-
- artistList = (ListView) findViewById(R.id.select_artist_list);
- artistList.setOnItemClickListener(this);
-
- folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistList, false);
- folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
-
- if (!Util.isOffline(this)) {
- artistList.addHeaderView(folderButton);
- }
-
- registerForContextMenu(artistList);
-
- setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
-
- // Button 1: shuffle
- ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_1);
- shuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
- shuffleButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(SelectArtistActivity.this, DownloadActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
- Util.startActivityWithoutTransition(SelectArtistActivity.this, intent);
- }
- });
-
- // Button 2: refresh
- ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
- refreshButton.setImageResource(R.drawable.ic_menu_refresh);
- refreshButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- refresh();
- }
- });
-
- musicFolders = null;
- load();
- }
-
- private void refresh() {
- finish();
- Intent intent = getIntent();
- intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
- Util.startActivityWithoutTransition(this, intent);
- }
-
- private void selectFolder() {
- folderButton.showContextMenu();
- }
-
- private void load() {
- BackgroundTask task = new TabActivityBackgroundTask(this) {
- @Override
- protected Indexes doInBackground() throws Throwable {
- boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
- MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
- if (!Util.isOffline(SelectArtistActivity.this)) {
- musicFolders = musicService.getMusicFolders(SelectArtistActivity.this, this);
- }
- String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
- return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
- }
-
- @Override
- protected void done(Indexes result) {
- List artists = new ArrayList(result.getShortcuts().size() + result.getArtists().size());
- artists.addAll(result.getShortcuts());
- artists.addAll(result.getArtists());
- artistList.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
-
- // Display selected music folder
- if (musicFolders != null) {
- String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
- if (musicFolderId == null) {
- folderName.setText(R.string.select_artist_all_folders);
- } else {
- for (MusicFolder musicFolder : musicFolders) {
- if (musicFolder.getId().equals(musicFolderId)) {
- folderName.setText(musicFolder.getName());
- break;
- }
- }
- }
- }
- }
- };
- task.execute();
- }
-
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- if (view == folderButton) {
- selectFolder();
- } else {
- Artist artist = (Artist) parent.getItemAtPosition(position);
- Intent intent = new Intent(this, SelectAlbumActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- Util.startActivityWithoutTransition(this, intent);
- }
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
-
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
-
- if (artistList.getItemAtPosition(info.position) instanceof Artist) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.select_artist_context, menu);
- } else if (info.position == 0) {
- String musicFolderId = Util.getSelectedMusicFolderId(this);
- MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
- if (musicFolderId == null) {
- menuItem.setChecked(true);
- }
- if (musicFolders != null) {
- for (int i = 0; i < musicFolders.size(); i++) {
- 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);
- }
- }
- }
- menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem menuItem) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
-
- Artist artist = (Artist) artistList.getItemAtPosition(info.position);
-
- if (artist != null) {
- switch (menuItem.getItemId()) {
- case R.id.artist_menu_play_now:
- downloadRecursively(artist.getId(), false, false, 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;
- }
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see .
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+
+package net.sourceforge.subsonic.androidapp.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.TextView;
+import net.sourceforge.subsonic.androidapp.R;
+import net.sourceforge.subsonic.androidapp.domain.Artist;
+import net.sourceforge.subsonic.androidapp.domain.Indexes;
+import net.sourceforge.subsonic.androidapp.domain.MusicFolder;
+import net.sourceforge.subsonic.androidapp.service.MusicService;
+import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
+import net.sourceforge.subsonic.androidapp.util.ArtistAdapter;
+import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Constants;
+import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SelectArtistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
+
+ private static final int MENU_GROUP_MUSIC_FOLDER = 10;
+
+ private ListView artistList;
+ private View folderButton;
+ private TextView folderName;
+ private List musicFolders;
+
+ /**
+ * Called when the activity is first created.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.select_artist);
+
+ artistList = (ListView) findViewById(R.id.select_artist_list);
+ artistList.setOnItemClickListener(this);
+
+ folderButton = LayoutInflater.from(this).inflate(R.layout.select_artist_header, artistList, false);
+ folderName = (TextView) folderButton.findViewById(R.id.select_artist_folder_2);
+
+ if (!Util.isOffline(this)) {
+ artistList.addHeaderView(folderButton);
+ }
+
+ registerForContextMenu(artistList);
+
+ setTitle(Util.isOffline(this) ? R.string.music_library_label_offline : R.string.music_library_label);
+
+ // Button 1: shuffle
+ ImageButton shuffleButton = (ImageButton) findViewById(R.id.action_button_1);
+ shuffleButton.setImageResource(R.drawable.ic_menu_shuffle);
+ shuffleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SelectArtistActivity.this, DownloadActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
+ Util.startActivityWithoutTransition(SelectArtistActivity.this, intent);
+ }
+ });
+
+ // Button 2: refresh
+ ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
+ refreshButton.setImageResource(R.drawable.ic_menu_refresh);
+ refreshButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ 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(SelectArtistActivity.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(SelectArtistActivity.this, SettingsActivity.class));
+ }
+ });
+
+ musicFolders = null;
+ load();
+ }
+
+ private void refresh() {
+ finish();
+ Intent intent = getIntent();
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
+ Util.startActivityWithoutTransition(this, intent);
+ }
+
+ private void selectFolder() {
+ folderButton.showContextMenu();
+ }
+
+ private void load() {
+ BackgroundTask task = new TabActivityBackgroundTask(this) {
+ @Override
+ protected Indexes doInBackground() throws Throwable {
+ boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
+ MusicService musicService = MusicServiceFactory.getMusicService(SelectArtistActivity.this);
+ if (!Util.isOffline(SelectArtistActivity.this)) {
+ musicFolders = musicService.getMusicFolders(SelectArtistActivity.this, this);
+ }
+ String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
+ return musicService.getIndexes(musicFolderId, refresh, SelectArtistActivity.this, this);
+ }
+
+ @Override
+ protected void done(Indexes result) {
+ List artists = new ArrayList(result.getShortcuts().size() + result.getArtists().size());
+ artists.addAll(result.getShortcuts());
+ artists.addAll(result.getArtists());
+ artistList.setAdapter(new ArtistAdapter(SelectArtistActivity.this, artists));
+
+ // Display selected music folder
+ if (musicFolders != null) {
+ String musicFolderId = Util.getSelectedMusicFolderId(SelectArtistActivity.this);
+ if (musicFolderId == null) {
+ folderName.setText(R.string.select_artist_all_folders);
+ } else {
+ for (MusicFolder musicFolder : musicFolders) {
+ if (musicFolder.getId().equals(musicFolderId)) {
+ folderName.setText(musicFolder.getName());
+ break;
+ }
+ }
+ }
+ }
+ }
+ };
+ task.execute();
+ }
+
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (view == folderButton) {
+ selectFolder();
+ } else {
+ Artist artist = (Artist) parent.getItemAtPosition(position);
+ Intent intent = new Intent(this, SelectAlbumActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ Util.startActivityWithoutTransition(this, intent);
+ }
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+
+ if (artistList.getItemAtPosition(info.position) instanceof Artist) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.select_artist_context, menu);
+ } else if (info.position == 0) {
+ String musicFolderId = Util.getSelectedMusicFolderId(this);
+ MenuItem menuItem = menu.add(MENU_GROUP_MUSIC_FOLDER, -1, 0, R.string.select_artist_all_folders);
+ if (musicFolderId == null) {
+ menuItem.setChecked(true);
+ }
+ if (musicFolders != null) {
+ for (int i = 0; i < musicFolders.size(); i++) {
+ 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);
+ }
+ }
+ }
+ menu.setGroupCheckable(MENU_GROUP_MUSIC_FOLDER, true, true);
+ }
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
+
+ Artist artist = (Artist) artistList.getItemAtPosition(info.position);
+
+ if (artist != null) {
+ switch (menuItem.getItemId()) {
+ case R.id.artist_menu_play_now:
+ downloadRecursively(artist.getId(), false, false, 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;
+ }
}
\ No newline at end of file
diff --git a/src/net/sourceforge/subsonic/androidapp/activity/SelectPlaylistActivity.java b/src/net/sourceforge/subsonic/androidapp/activity/SelectPlaylistActivity.java
index 1706f8c2..fb31a088 100644
--- a/src/net/sourceforge/subsonic/androidapp/activity/SelectPlaylistActivity.java
+++ b/src/net/sourceforge/subsonic/androidapp/activity/SelectPlaylistActivity.java
@@ -1,146 +1,166 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see .
-
- Copyright 2009 (C) Sindre Mehus
- */
-
-package net.sourceforge.subsonic.androidapp.activity;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ImageButton;
-import android.widget.ListView;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.Playlist;
-import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
-import net.sourceforge.subsonic.androidapp.service.MusicService;
-import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-import java.util.List;
-
-public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
-
- private static final int MENU_ITEM_PLAY_ALL = 1;
-
- private ListView list;
- private View emptyTextView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.select_playlist);
-
- list = (ListView) findViewById(R.id.select_playlist_list);
- emptyTextView = findViewById(R.id.select_playlist_empty);
- list.setOnItemClickListener(this);
- registerForContextMenu(list);
-
- // Title: Playlists
- setTitle(R.string.playlist_label);
-
- // Button 1: gone
- ImageButton searchButton = (ImageButton)findViewById(R.id.action_button_1);
- searchButton.setVisibility(View.GONE);
-
- // Button 2: refresh
- ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
- refreshButton.setImageResource(R.drawable.ic_menu_refresh);
- refreshButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- refresh();
- }
- });
-
- load();
- }
-
- private void refresh() {
- finish();
- Intent intent = new Intent(this, SelectPlaylistActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
- Util.startActivityWithoutTransition(this, intent);
- }
-
- private void load() {
- BackgroundTask> task = new TabActivityBackgroundTask>(this) {
- @Override
- protected List doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
- boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
- return musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this);
- }
-
- @Override
- protected void done(List result) {
- list.setAdapter(new PlaylistAdapter(result));
- emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
- }
- };
- task.execute();
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
- menu.add(Menu.NONE, MENU_ITEM_PLAY_ALL, MENU_ITEM_PLAY_ALL, R.string.common_play_now);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem menuItem) {
- AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
- Playlist playlist = (Playlist) list.getItemAtPosition(info.position);
-
- switch (menuItem.getItemId()) {
- case MENU_ITEM_PLAY_ALL:
- 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());
- intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
- Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
- 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 {
- public PlaylistAdapter(List playlists) {
- super(SelectPlaylistActivity.this, R.layout.playlist_list_item, playlists);
- }
- }
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see .
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+
+package net.sourceforge.subsonic.androidapp.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import net.sourceforge.subsonic.androidapp.R;
+import net.sourceforge.subsonic.androidapp.domain.Playlist;
+import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
+import net.sourceforge.subsonic.androidapp.service.MusicService;
+import net.sourceforge.subsonic.androidapp.util.BackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Constants;
+import net.sourceforge.subsonic.androidapp.util.TabActivityBackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Util;
+
+import java.util.List;
+
+public class SelectPlaylistActivity extends SubsonicTabActivity implements AdapterView.OnItemClickListener {
+
+ private static final int MENU_ITEM_PLAY_ALL = 1;
+
+ private ListView list;
+ private View emptyTextView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.select_playlist);
+
+ list = (ListView) findViewById(R.id.select_playlist_list);
+ emptyTextView = findViewById(R.id.select_playlist_empty);
+ list.setOnItemClickListener(this);
+ registerForContextMenu(list);
+
+ // Title: Playlists
+ setTitle(R.string.playlist_label);
+
+ // Button 1: gone
+ ImageButton searchButton = (ImageButton)findViewById(R.id.action_button_1);
+ searchButton.setVisibility(View.GONE);
+
+ // Button 2: refresh
+ ImageButton refreshButton = (ImageButton) findViewById(R.id.action_button_2);
+ refreshButton.setImageResource(R.drawable.ic_menu_refresh);
+ refreshButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ 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(SelectPlaylistActivity.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(SelectPlaylistActivity.this, SettingsActivity.class));
+ }
+ });
+
+ load();
+ }
+
+ private void refresh() {
+ finish();
+ Intent intent = new Intent(this, SelectPlaylistActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_REFRESH, true);
+ Util.startActivityWithoutTransition(this, intent);
+ }
+
+ private void load() {
+ BackgroundTask> task = new TabActivityBackgroundTask>(this) {
+ @Override
+ protected List doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(SelectPlaylistActivity.this);
+ boolean refresh = getIntent().getBooleanExtra(Constants.INTENT_EXTRA_NAME_REFRESH, false);
+ return musicService.getPlaylists(refresh, SelectPlaylistActivity.this, this);
+ }
+
+ @Override
+ protected void done(List result) {
+ list.setAdapter(new PlaylistAdapter(result));
+ emptyTextView.setVisibility(result.isEmpty() ? View.VISIBLE : View.GONE);
+ }
+ };
+ task.execute();
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, view, menuInfo);
+ menu.add(Menu.NONE, MENU_ITEM_PLAY_ALL, MENU_ITEM_PLAY_ALL, R.string.common_play_now);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem menuItem) {
+ AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuItem.getMenuInfo();
+ Playlist playlist = (Playlist) list.getItemAtPosition(info.position);
+
+ switch (menuItem.getItemId()) {
+ case MENU_ITEM_PLAY_ALL:
+ 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());
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
+ Util.startActivityWithoutTransition(SelectPlaylistActivity.this, intent);
+ 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 {
+ public PlaylistAdapter(List playlists) {
+ super(SelectPlaylistActivity.this, R.layout.playlist_list_item, playlists);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java b/src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java
index 2a5e266a..88420b6d 100644
--- a/src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java
+++ b/src/net/sourceforge/subsonic/androidapp/activity/SubsonicTabActivity.java
@@ -1,387 +1,389 @@
-/*
- This file is part of Subsonic.
-
- Subsonic is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Subsonic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Subsonic. If not, see .
-
- Copyright 2009 (C) Sindre Mehus
- */
-package net.sourceforge.subsonic.androidapp.activity;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.util.LinkedList;
-import java.util.List;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.graphics.Typeface;
-import android.media.AudioManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.Window;
-import android.widget.TextView;
-import net.sourceforge.subsonic.androidapp.R;
-import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
-import net.sourceforge.subsonic.androidapp.service.DownloadService;
-import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
-import net.sourceforge.subsonic.androidapp.service.MusicService;
-import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
-import net.sourceforge.subsonic.androidapp.util.Constants;
-import net.sourceforge.subsonic.androidapp.util.ImageLoader;
-import net.sourceforge.subsonic.androidapp.util.ModalBackgroundTask;
-import net.sourceforge.subsonic.androidapp.util.Util;
-
-/**
- * @author Sindre Mehus
- */
-public class SubsonicTabActivity extends Activity {
-
- private static final String TAG = SubsonicTabActivity.class.getSimpleName();
- private static ImageLoader IMAGE_LOADER;
-
- private boolean destroyed;
- private View homeButton;
- private View musicButton;
- private View searchButton;
- private View playlistButton;
- private View nowPlayingButton;
-
- @Override
- protected void onCreate(Bundle bundle) {
- setUncaughtExceptionHandler();
- applyTheme();
- super.onCreate(bundle);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- startService(new Intent(this, DownloadServiceImpl.class));
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- }
-
- @Override
- protected void onPostCreate(Bundle bundle) {
- super.onPostCreate(bundle);
-
- homeButton = findViewById(R.id.button_bar_home);
- homeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(SubsonicTabActivity.this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
- }
- });
-
- musicButton = findViewById(R.id.button_bar_music);
- musicButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(SubsonicTabActivity.this, SelectArtistActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
- }
- });
-
- searchButton = findViewById(R.id.button_bar_search);
- searchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(SubsonicTabActivity.this, SearchActivity.class);
- intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
- }
- });
-
- playlistButton = findViewById(R.id.button_bar_playlists);
- playlistButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Intent intent = new Intent(SubsonicTabActivity.this, SelectPlaylistActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
- }
- });
-
- nowPlayingButton = findViewById(R.id.button_bar_now_playing);
- nowPlayingButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
- }
- });
-
- if (this instanceof MainActivity) {
- homeButton.setEnabled(false);
- } else if (this instanceof SelectAlbumActivity || this instanceof SelectArtistActivity) {
- musicButton.setEnabled(false);
- } else if (this instanceof SearchActivity) {
- searchButton.setEnabled(false);
- } else if (this instanceof SelectPlaylistActivity) {
- playlistButton.setEnabled(false);
- } else if (this instanceof DownloadActivity || this instanceof LyricsActivity) {
- nowPlayingButton.setEnabled(false);
- }
-
- updateButtonVisibility();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- Util.registerMediaButtonEventReceiver(this);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case R.id.menu_exit:
- Intent intent = new Intent(this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
- Util.startActivityWithoutTransition(this, intent);
- return true;
-
- case R.id.menu_settings:
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
-
- case R.id.menu_help:
- startActivity(new Intent(this, HelpActivity.class));
- return true;
- }
-
- return false;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- destroyed = true;
- getImageLoader().clear();
- }
-
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN;
- boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP;
- boolean isVolumeAdjust = isVolumeDown || isVolumeUp;
- boolean isJukebox = getDownloadService() != null && getDownloadService().isJukeboxEnabled();
-
- if (isVolumeAdjust && isJukebox) {
- getDownloadService().adjustJukeboxVolume(isVolumeUp);
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void finish() {
- super.finish();
- Util.disablePendingTransition(this);
- }
-
- @Override
- public void setTitle(CharSequence title) {
- super.setTitle(title);
-
- // Set the font of title in the action bar.
- TextView text = (TextView) findViewById(R.id.actionbar_title_text);
- Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf");
- text.setTypeface(typeface);
-
- text.setText(title);
- }
-
- @Override
- public void setTitle(int titleId) {
- setTitle(getString(titleId));
- }
-
- private void applyTheme() {
- String theme = Util.getTheme(this);
- if ("dark".equals(theme)) {
- setTheme(R.style.Dark);
- } else if ("light".equals(theme)) {
- setTheme(R.style.Light);
- } else if ("fullscreen".equals(theme)) {
- setTheme(R.style.Fullscreen);
- } else if ("fullscreenlight".equals(theme)) {
- setTheme(R.style.Fullscreenlight);
- }
- }
-
- public boolean isDestroyed() {
- return destroyed;
- }
-
- private void updateButtonVisibility() {
- 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) {
- view.setVisibility(visible ? View.VISIBLE : View.GONE);
- }
- }
-
- public void updateProgress(String 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++) {
- DownloadService downloadService = DownloadServiceImpl.getInstance();
- if (downloadService != null) {
- return downloadService;
- }
- Log.w(TAG, "DownloadService not running. Attempting to start it.");
- startService(new Intent(this, DownloadServiceImpl.class));
- Util.sleepQuietly(50L);
- }
- return DownloadServiceImpl.getInstance();
- }
-
- protected void warnIfNetworkOrStorageUnavailable() {
- if (!Util.isExternalStoragePresent()) {
- 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);
- }
- return IMAGE_LOADER;
- }
-
- protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay) {
- ModalBackgroundTask> task = new ModalBackgroundTask>(this, false) {
-
- private static final int MAX_SONGS = 500;
-
- @Override
- protected List doInBackground() throws Throwable {
- MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
- MusicDirectory root = musicService.getMusicDirectory(id, false, SubsonicTabActivity.this, this);
- List songs = new LinkedList();
- getSongsRecursively(root, songs);
- return songs;
- }
-
- private void getSongsRecursively(MusicDirectory parent, List 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 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 songs) {
- DownloadService downloadService = getDownloadService();
- if (!songs.isEmpty() && downloadService != null) {
- if (!append) {
- downloadService.clear();
- }
- warnIfNetworkOrStorageUnavailable();
- downloadService.download(songs, save, autoplay, false);
- Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
- }
- }
- };
-
- task.execute();
- }
-
- private void setUncaughtExceptionHandler() {
- 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 {
-
- private final Thread.UncaughtExceptionHandler defaultHandler;
- private final Context context;
-
- private SubsonicUncaughtExceptionHandler(Context context) {
- this.context = context;
- defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
- }
-
- @Override
- public void uncaughtException(Thread thread, Throwable throwable) {
- File file = null;
- PrintWriter printWriter = null;
- try {
-
- PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.sourceforge.subsonic.androidapp", 0);
- file = new File(Environment.getExternalStorageDirectory(), "subsonic-stacktrace.txt");
- printWriter = new PrintWriter(file);
- printWriter.println("Android API level: " + Build.VERSION.SDK);
- printWriter.println("Subsonic version name: " + packageInfo.versionName);
- printWriter.println("Subsonic version code: " + packageInfo.versionCode);
- printWriter.println();
- throwable.printStackTrace(printWriter);
- Log.i(TAG, "Stack trace written to " + file);
- } catch (Throwable x) {
- Log.e(TAG, "Failed to write stack trace to " + file, x);
- } finally {
- Util.close(printWriter);
- if (defaultHandler != null) {
- defaultHandler.uncaughtException(thread, throwable);
- }
-
- }
- }
- }
-}
-
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see .
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.androidapp.activity;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.graphics.Typeface;
+import android.media.AudioManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.TextView;
+import net.sourceforge.subsonic.androidapp.R;
+import net.sourceforge.subsonic.androidapp.domain.MusicDirectory;
+import net.sourceforge.subsonic.androidapp.service.DownloadService;
+import net.sourceforge.subsonic.androidapp.service.DownloadServiceImpl;
+import net.sourceforge.subsonic.androidapp.service.MusicService;
+import net.sourceforge.subsonic.androidapp.service.MusicServiceFactory;
+import net.sourceforge.subsonic.androidapp.util.Constants;
+import net.sourceforge.subsonic.androidapp.util.ImageLoader;
+import net.sourceforge.subsonic.androidapp.util.ModalBackgroundTask;
+import net.sourceforge.subsonic.androidapp.util.Util;
+
+/**
+ * @author Sindre Mehus
+ */
+public class SubsonicTabActivity extends Activity {
+
+ private static final String TAG = SubsonicTabActivity.class.getSimpleName();
+ private static ImageLoader IMAGE_LOADER;
+
+ private boolean destroyed;
+ private View homeButton;
+ private View musicButton;
+ private View searchButton;
+ private View playlistButton;
+ private View nowPlayingButton;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ setUncaughtExceptionHandler();
+ applyTheme();
+ super.onCreate(bundle);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ startService(new Intent(this, DownloadServiceImpl.class));
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+ }
+
+ @Override
+ protected void onPostCreate(Bundle bundle) {
+ super.onPostCreate(bundle);
+
+ homeButton = findViewById(R.id.button_bar_home);
+ homeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SubsonicTabActivity.this, MainActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
+ }
+ });
+
+ musicButton = findViewById(R.id.button_bar_music);
+ musicButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SubsonicTabActivity.this, SelectArtistActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
+ }
+ });
+
+ searchButton = findViewById(R.id.button_bar_search);
+ searchButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SubsonicTabActivity.this, SearchActivity.class);
+ intent.putExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, true);
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
+ }
+ });
+
+ playlistButton = findViewById(R.id.button_bar_playlists);
+ playlistButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SubsonicTabActivity.this, SelectPlaylistActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, intent);
+ }
+ });
+
+ nowPlayingButton = findViewById(R.id.button_bar_now_playing);
+ nowPlayingButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
+ }
+ });
+
+ if (this instanceof MainActivity) {
+ homeButton.setEnabled(false);
+ } else if (this instanceof SelectAlbumActivity || this instanceof SelectArtistActivity) {
+ musicButton.setEnabled(false);
+ } else if (this instanceof SearchActivity) {
+ searchButton.setEnabled(false);
+ } else if (this instanceof SelectPlaylistActivity) {
+ playlistButton.setEnabled(false);
+ } else if (this instanceof DownloadActivity || this instanceof LyricsActivity) {
+ nowPlayingButton.setEnabled(false);
+ }
+
+ updateButtonVisibility();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Util.registerMediaButtonEventReceiver(this);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ if (android.os.Build.VERSION.SDK_INT < 11) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main, menu);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ case R.id.menu_exit:
+ Intent intent = new Intent(this, MainActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true);
+ Util.startActivityWithoutTransition(this, intent);
+ return true;
+
+ case R.id.menu_settings:
+ startActivity(new Intent(this, SettingsActivity.class));
+ return true;
+
+ case R.id.menu_help:
+ startActivity(new Intent(this, HelpActivity.class));
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ destroyed = true;
+ getImageLoader().clear();
+ }
+
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN;
+ boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP;
+ boolean isVolumeAdjust = isVolumeDown || isVolumeUp;
+ boolean isJukebox = getDownloadService() != null && getDownloadService().isJukeboxEnabled();
+
+ if (isVolumeAdjust && isJukebox) {
+ getDownloadService().adjustJukeboxVolume(isVolumeUp);
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ Util.disablePendingTransition(this);
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ super.setTitle(title);
+
+ // Set the font of title in the action bar.
+ TextView text = (TextView) findViewById(R.id.actionbar_title_text);
+ Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Regular.ttf");
+ text.setTypeface(typeface);
+
+ text.setText(title);
+ }
+
+ @Override
+ public void setTitle(int titleId) {
+ setTitle(getString(titleId));
+ }
+
+ private void applyTheme() {
+ String theme = Util.getTheme(this);
+ if ("dark".equals(theme)) {
+ setTheme(R.style.Dark);
+ } else if ("light".equals(theme)) {
+ setTheme(R.style.Light);
+ } else if ("fullscreen".equals(theme)) {
+ setTheme(R.style.Fullscreen);
+ } else if ("fullscreenlight".equals(theme)) {
+ setTheme(R.style.Fullscreenlight);
+ }
+ }
+
+ public boolean isDestroyed() {
+ return destroyed;
+ }
+
+ private void updateButtonVisibility() {
+ 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) {
+ view.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ public void updateProgress(String 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++) {
+ DownloadService downloadService = DownloadServiceImpl.getInstance();
+ if (downloadService != null) {
+ return downloadService;
+ }
+ Log.w(TAG, "DownloadService not running. Attempting to start it.");
+ startService(new Intent(this, DownloadServiceImpl.class));
+ Util.sleepQuietly(50L);
+ }
+ return DownloadServiceImpl.getInstance();
+ }
+
+ protected void warnIfNetworkOrStorageUnavailable() {
+ if (!Util.isExternalStoragePresent()) {
+ 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);
+ }
+ return IMAGE_LOADER;
+ }
+
+ protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay) {
+ ModalBackgroundTask> task = new ModalBackgroundTask>(this, false) {
+
+ private static final int MAX_SONGS = 500;
+
+ @Override
+ protected List doInBackground() throws Throwable {
+ MusicService musicService = MusicServiceFactory.getMusicService(SubsonicTabActivity.this);
+ MusicDirectory root = musicService.getMusicDirectory(id, false, SubsonicTabActivity.this, this);
+ List songs = new LinkedList();
+ getSongsRecursively(root, songs);
+ return songs;
+ }
+
+ private void getSongsRecursively(MusicDirectory parent, List 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 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 songs) {
+ DownloadService downloadService = getDownloadService();
+ if (!songs.isEmpty() && downloadService != null) {
+ if (!append) {
+ downloadService.clear();
+ }
+ warnIfNetworkOrStorageUnavailable();
+ downloadService.download(songs, save, autoplay, false);
+ Util.startActivityWithoutTransition(SubsonicTabActivity.this, DownloadActivity.class);
+ }
+ }
+ };
+
+ task.execute();
+ }
+
+ private void setUncaughtExceptionHandler() {
+ 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 {
+
+ private final Thread.UncaughtExceptionHandler defaultHandler;
+ private final Context context;
+
+ private SubsonicUncaughtExceptionHandler(Context context) {
+ this.context = context;
+ defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
+ }
+
+ @Override
+ public void uncaughtException(Thread thread, Throwable throwable) {
+ File file = null;
+ PrintWriter printWriter = null;
+ try {
+
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.sourceforge.subsonic.androidapp", 0);
+ file = new File(Environment.getExternalStorageDirectory(), "subsonic-stacktrace.txt");
+ printWriter = new PrintWriter(file);
+ printWriter.println("Android API level: " + Build.VERSION.SDK);
+ printWriter.println("Subsonic version name: " + packageInfo.versionName);
+ printWriter.println("Subsonic version code: " + packageInfo.versionCode);
+ printWriter.println();
+ throwable.printStackTrace(printWriter);
+ Log.i(TAG, "Stack trace written to " + file);
+ } catch (Throwable x) {
+ Log.e(TAG, "Failed to write stack trace to " + file, x);
+ } finally {
+ Util.close(printWriter);
+ if (defaultHandler != null) {
+ defaultHandler.uncaughtException(thread, throwable);
+ }
+
+ }
+ }
+ }
+}
+