aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorScott Jackson <daneren2005@gmail.com>2016-07-25 08:26:56 -0700
committerScott Jackson <daneren2005@gmail.com>2016-07-25 08:26:56 -0700
commitc6a2210258d0f91e147b091d357652d3f921e916 (patch)
tree2729aeca66b2dc287e5dfaf91a78073770fc85e6 /app
parent21806c87a6290e731b314ade5809424217dd4c31 (diff)
parent82399945f6287e8d7630532dfe8a4d1a7fa9c747 (diff)
downloaddsub-c6a2210258d0f91e147b091d357652d3f921e916.tar.gz
dsub-c6a2210258d0f91e147b091d357652d3f921e916.tar.bz2
dsub-c6a2210258d0f91e147b091d357652d3f921e916.zip
Merge branch 'master' into playback_speed
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle4
-rw-r--r--app/proguard.cfg1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java28
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java39
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java6
-rw-r--r--app/src/main/java/github/daneren2005/dsub/adapter/ExpandableSectionAdapter.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/domain/Artist.java6
-rw-r--r--app/src/main/java/github/daneren2005/dsub/domain/Indexes.java7
-rw-r--r--app/src/main/java/github/daneren2005/dsub/domain/ServerInfo.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java7
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java22
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java118
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java11
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java6
-rw-r--r--app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java37
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java3
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java13
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java2
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java12
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/BackgroundTask.java14
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Constants.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Util.java20
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java43
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/CardView.java1
-rw-r--r--app/src/main/java/github/daneren2005/dsub/view/SongView.java11
-rw-r--r--app/src/main/res/menu/abstract_top_menu.xml3
-rw-r--r--app/src/main/res/menu/main.xml5
-rw-r--r--app/src/main/res/menu/search.xml3
-rw-r--r--app/src/main/res/menu/select_artist.xml5
-rw-r--r--app/src/main/res/menu/select_podcasts.xml5
-rw-r--r--app/src/main/res/values-fr/strings.xml12
-rw-r--r--app/src/main/res/values-pt-rPT/strings.xml185
-rw-r--r--app/src/main/res/xml/changelog.xml16
34 files changed, 423 insertions, 228 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 584f10f3..f5072c42 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,8 +9,8 @@ android {
applicationId "github.daneren2005.dsub"
minSdkVersion 14
targetSdkVersion 22
- versionCode 178
- versionName '5.1.7'
+ versionCode 181
+ versionName '5.1.9'
setProperty("archivesBaseName", "DSub $versionName")
}
buildTypes {
diff --git a/app/proguard.cfg b/app/proguard.cfg
index 8e1a0a0a..a18ae91a 100644
--- a/app/proguard.cfg
+++ b/app/proguard.cfg
@@ -44,6 +44,7 @@
}
-keep class android.support.v7.app.MediaRouteButton { *; }
+-keep class android.support.v7.widget.SearchView { *; }
-dontwarn android.support.**
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
index 51de1f6c..ca6dd168 100644
--- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
+++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicFragmentActivity.java
@@ -225,7 +225,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
bottomBar.setVisibility(View.GONE);
nowPlayingToolbar.setVisibility(View.VISIBLE);
setSupportActionBar(nowPlayingToolbar);
- nowPlayingFragment.setPrimaryFragment(true);
+
+ if(secondaryFragment == null) {
+ nowPlayingFragment.setPrimaryFragment(true);
+ } else {
+ secondaryFragment.setPrimaryFragment(true);
+ }
drawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -396,14 +401,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
if(currentFragment instanceof SearchFragment) {
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
- boolean requestsearch = intent.getBooleanExtra(Constants.INTENT_EXTRA_REQUEST_SEARCH, false);
if (query != null) {
((SearchFragment)currentFragment).search(query, autoplay);
- } else {
- if (requestsearch) {
- onSearchRequested();
- }
}
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_QUERY);
} else {
@@ -472,6 +472,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag());
+ if(secondaryFragment != null) {
+ savedInstanceState.putString(Constants.MAIN_NOW_PLAYING_SECONDARY, secondaryFragment.getTag());
+ }
savedInstanceState.putInt(Constants.MAIN_SLIDE_PANEL_STATE, slideUpPanel.getPanelState().hashCode());
}
@Override
@@ -481,6 +484,19 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
String id = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING);
FragmentManager fm = getSupportFragmentManager();
nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id);
+
+ String secondaryId = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING_SECONDARY);
+ if(secondaryId != null) {
+ secondaryFragment = (SubsonicFragment) fm.findFragmentByTag(secondaryId);
+
+ nowPlayingFragment.setPrimaryFragment(false);
+ secondaryFragment.setPrimaryFragment(true);
+
+ FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
+ trans.hide(nowPlayingFragment);
+ trans.commit();
+ }
+
if(drawerToggle != null && backStack.size() > 0) {
drawerToggle.setDrawerIndicatorEnabled(false);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
index 207dc0b2..5ed79e82 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/ArtistAdapter.java
@@ -23,27 +23,32 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import java.io.Serializable;
import java.util.List;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Artist;
+import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
import github.daneren2005.dsub.domain.MusicFolder;
import github.daneren2005.dsub.util.Util;
import github.daneren2005.dsub.view.ArtistView;
import github.daneren2005.dsub.view.FastScroller;
+import github.daneren2005.dsub.view.SongView;
import github.daneren2005.dsub.view.UpdateView;
-public class ArtistAdapter extends SectionAdapter<Artist> implements FastScroller.BubbleTextGetter {
+public class ArtistAdapter extends SectionAdapter<Serializable> implements FastScroller.BubbleTextGetter {
+ public static int VIEW_TYPE_SONG = 3;
public static int VIEW_TYPE_ARTIST = 4;
private List<MusicFolder> musicFolders;
private OnMusicFolderChanged onMusicFolderChanged;
- public ArtistAdapter(Context context, List<Artist> artists, OnItemClickedListener listener) {
+ public ArtistAdapter(Context context, List<Serializable> artists, OnItemClickedListener listener) {
this(context, artists, null, listener, null);
}
- public ArtistAdapter(Context context, List<Artist> artists, List<MusicFolder> musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) {
+ public ArtistAdapter(Context context, List<Serializable> artists, List<MusicFolder> musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) {
super(context, artists);
this.musicFolders = musicFolders;
this.onItemClickedListener = onItemClickedListener;
@@ -110,17 +115,35 @@ public class ArtistAdapter extends SectionAdapter<Artist> implements FastScrolle
@Override
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
- return new UpdateView.UpdateViewHolder(new ArtistView(context));
+ UpdateView updateView = null;
+ if(viewType == VIEW_TYPE_ARTIST) {
+ updateView = new ArtistView(context);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ updateView = new SongView(context);
+ }
+
+ return new UpdateView.UpdateViewHolder(updateView);
}
@Override
- public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Artist item, int viewType) {
- holder.getUpdateView().setObject(item);
+ public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
+ UpdateView view = holder.getUpdateView();
+ if(viewType == VIEW_TYPE_ARTIST) {
+ view.setObject(item);
+ } else if(viewType == VIEW_TYPE_SONG) {
+ SongView songView = (SongView) view;
+ Entry entry = (Entry) item;
+ songView.setObject(entry, checkable && !entry.isVideo());
+ }
}
@Override
- public int getItemViewType(Artist item) {
- return VIEW_TYPE_ARTIST;
+ public int getItemViewType(Serializable item) {
+ if(item instanceof Artist) {
+ return VIEW_TYPE_ARTIST;
+ } else {
+ return VIEW_TYPE_SONG;
+ }
}
@Override
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java
index b07d4731..e75a5104 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/EntryGridAdapter.java
@@ -44,6 +44,7 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
private ImageLoader imageLoader;
private boolean largeAlbums;
private boolean showArtist = false;
+ private boolean showAlbum = false;
private boolean removeFromPlaylist = false;
private View header;
@@ -87,6 +88,7 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
albumView.setObject(entry, imageLoader);
} else if(viewType == VIEW_TYPE_SONG) {
SongView songView = (SongView) view;
+ songView.setShowAlbum(showAlbum);
songView.setObject(entry, checkable && !entry.isVideo());
}
}
@@ -123,6 +125,10 @@ public class EntryGridAdapter extends SectionAdapter<Entry> {
this.showArtist = showArtist;
}
+ public void setShowAlbum(boolean showAlbum) {
+ this.showAlbum = showAlbum;
+ }
+
public void removeAt(int index) {
sections.get(0).remove(index);
if(header != null) {
diff --git a/app/src/main/java/github/daneren2005/dsub/adapter/ExpandableSectionAdapter.java b/app/src/main/java/github/daneren2005/dsub/adapter/ExpandableSectionAdapter.java
index b1a692d5..6ebb34e3 100644
--- a/app/src/main/java/github/daneren2005/dsub/adapter/ExpandableSectionAdapter.java
+++ b/app/src/main/java/github/daneren2005/dsub/adapter/ExpandableSectionAdapter.java
@@ -78,7 +78,6 @@ public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
} else {
visibleSection.addAll(fullSection.subList(0, defaultVisible));
this.sectionsExtras.add(fullSection.subList(defaultVisible, fullSection.size()));
- Log.d(TAG, visibleSection.size() + " + " + this.sectionsExtras.get(i).size());
}
this.sections.add(visibleSection);
diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
index 5809146d..ff4d86ce 100644
--- a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
+++ b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java
@@ -130,12 +130,6 @@ public class Artist implements Serializable {
}
public int compare(Artist lhsArtist, Artist rhsArtist) {
- if("root".equals(lhsArtist.getId())) {
- return 1;
- } else if("root".equals(rhsArtist.getId())) {
- return -1;
- }
-
String lhs = lhsArtist.getName().toLowerCase();
String rhs = rhsArtist.getName().toLowerCase();
diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Indexes.java b/app/src/main/java/github/daneren2005/dsub/domain/Indexes.java
index e15ccf9f..05e686ca 100644
--- a/app/src/main/java/github/daneren2005/dsub/domain/Indexes.java
+++ b/app/src/main/java/github/daneren2005/dsub/domain/Indexes.java
@@ -52,13 +52,6 @@ public class Indexes implements Serializable {
this.shortcuts = shortcuts;
this.artists = artists;
this.entries = entries;
- if(!entries.isEmpty()) {
- Artist root = new Artist();
- root.setId("root");
- root.setName("Root");
- root.setIndex("#");
- artists.add(root);
- }
}
public long getLastModified() {
diff --git a/app/src/main/java/github/daneren2005/dsub/domain/ServerInfo.java b/app/src/main/java/github/daneren2005/dsub/domain/ServerInfo.java
index e4c9b17d..7f538484 100644
--- a/app/src/main/java/github/daneren2005/dsub/domain/ServerInfo.java
+++ b/app/src/main/java/github/daneren2005/dsub/domain/ServerInfo.java
@@ -203,7 +203,7 @@ public class ServerInfo implements Serializable {
}
public static boolean hasArtistInfo(Context context) {
- if(isStockSubsonic(context) && ServerInfo.checkServerVersion(context, "1.11")) {
+ if(!isMadsonic(context) && ServerInfo.checkServerVersion(context, "1.11")) {
return true;
} else if(isMadsonic(context)) {
return checkServerVersion(context, "2.0");
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
index f3d675f0..8c2fa4bf 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/MainFragment.java
@@ -1,6 +1,7 @@
package github.daneren2005.dsub.fragments;
import android.content.Intent;
+import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
@@ -63,6 +64,7 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.main, menu);
+ onFinishSetupOptionsMenu(menu);
try {
if (!ServerInfo.isMadsonic(context) || !UserUtil.isCurrentAdmin()) {
@@ -269,7 +271,7 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
private void getLogs() {
try {
- final String version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+ final PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
new LoadingTask<String>(context) {
@Override
protected String doInBackground() throws Throwable {
@@ -372,10 +374,11 @@ public class MainFragment extends SelectRecyclerFragment<Integer> {
footer += "\nDevice Name: " + Build.MANUFACTURER + " " + Build.PRODUCT;
footer += "\nROM: " + Build.DISPLAY;
footer += "\nLogs: " + logcat;
+ footer += "\nBuild Number: " + packageInfo.versionCode;
Intent email = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts("mailto", "dsub.android@gmail.com", null));
- email.putExtra(Intent.EXTRA_SUBJECT, "DSub " + version + " Error Logs");
+ email.putExtra(Intent.EXTRA_SUBJECT, "DSub " + packageInfo.versionName + " Error Logs");
email.putExtra(Intent.EXTRA_TEXT, "Describe the problem here\n\n\n" + footer);
startActivity(email);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
index 87ccbd64..530c03b6 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java
@@ -1244,7 +1244,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
this.currentPlaying = currentPlaying;
setupSubtitle(currentPlayingIndex);
- if(currentPlaying != null && currentPlaying.getSong() != null && (currentPlaying.getSong().isPodcast() || currentPlaying.getSong().isAudioBook())) {
+ if(currentPlaying != null && !currentPlaying.isSong()) {
previousButton.setVisibility(View.GONE);
nextButton.setVisibility(View.GONE);
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
index c891da34..eed714af 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SearchFragment.java
@@ -7,6 +7,7 @@ import java.util.List;
import android.content.Intent;
import android.os.Bundle;
+import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
@@ -125,18 +126,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.search, menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_global_search:
- context.startSearch(currentQuery, false, null, false);
- return true;
- }
-
- return super.onOptionsItemSelected(item);
-
+ onFinishSetupOptionsMenu(menu);
}
@Override
@@ -218,6 +208,14 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O
}
};
task.execute();
+
+ if(searchItem != null) {
+ MenuItemCompat.collapseActionView(searchItem);
+ }
+ }
+
+ protected String getCurrentQuery() {
+ return currentQuery;
}
private void onArtistSelected(Artist artist, boolean autoplay) {
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
index 6890f572..c9b94c9a 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectArtistFragment.java
@@ -17,6 +17,7 @@ import github.daneren2005.dsub.adapter.SectionAdapter;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.Indexes;
import github.daneren2005.dsub.domain.MusicDirectory;
+import github.daneren2005.dsub.domain.MusicDirectory.Entry;
import github.daneren2005.dsub.domain.MusicFolder;
import github.daneren2005.dsub.domain.ServerInfo;
import github.daneren2005.dsub.service.MusicService;
@@ -29,12 +30,11 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-public class SelectArtistFragment extends SelectRecyclerFragment<Artist> implements ArtistAdapter.OnMusicFolderChanged {
+public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> implements ArtistAdapter.OnMusicFolderChanged {
private static final String TAG = SelectArtistFragment.class.getSimpleName();
- private static final int MENU_GROUP_MUSIC_FOLDER = 10;
private List<MusicFolder> musicFolders = null;
- private List<MusicDirectory.Entry> entries;
+ private List<Entry> entries;
private String groupId;
private String groupName;
@@ -80,48 +80,68 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Artist> impleme
}
@Override
- public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Artist> updateView, Artist item) {
+ public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
recreateContextMenu(menu);
}
@Override
- public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Artist> updateView, Artist item) {
+ public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
return onContextItemSelected(menuItem, item);
}
@Override
- public void onItemClicked(UpdateView<Artist> updateView, Artist artist) {
+ public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
SubsonicFragment fragment;
- if((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || "root".equals(artist.getId()) || groupId != null) {
- fragment = new SelectDirectoryFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
-
- if ("root".equals(artist.getId())) {
- args.putSerializable(Constants.FRAGMENT_LIST, (Serializable) entries);
- }
- if(ServerInfo.checkServerVersion(context, "1.13") && !Util.isOffline(context)) {
- args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new MusicDirectory.Entry(artist));
+ if(item instanceof Artist) {
+ Artist artist = (Artist) item;
+
+ if ((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || groupId != null) {
+ fragment = new SelectDirectoryFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+
+ if (ServerInfo.checkServerVersion(context, "1.13") && !Util.isOffline(context)) {
+ args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
+ }
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+
+ fragment.setArguments(args);
+ } else {
+ fragment = new SelectArtistFragment();
+ Bundle args = new Bundle();
+ args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
+ args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
+ args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
+ if (ServerInfo.checkServerVersion(context, "1.13") && !Util.isOffline(context)) {
+ args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
+ }
+
+ fragment.setArguments(args);
}
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- fragment.setArguments(args);
+ replaceFragment(fragment);
} else {
- fragment = new SelectArtistFragment();
- Bundle args = new Bundle();
- args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
- args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
- args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
- if(ServerInfo.checkServerVersion(context, "1.13") && !Util.isOffline(context)) {
- args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new MusicDirectory.Entry(artist));
+ Entry entry = (Entry) item;
+ if (entry.isVideo()) {
+ playVideo(entry);
+ } else {
+ List<Entry> songs = new ArrayList<Entry>();
+
+ if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PLAY_NOW_AFTER, true)) {
+ for (Entry song : entries) {
+ if (!song.isDirectory() && !song.isVideo()) {
+ songs.add(song);
+ }
+ }
+ playNow(songs, entry, 0);
+ } else {
+ songs.add(entry);
+ playNow(songs);
+ }
}
-
- fragment.setArguments(args);
}
-
- replaceFragment(fragment);
}
@Override
@@ -158,13 +178,13 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Artist> impleme
}
@Override
- public SectionAdapter getAdapter(List<Artist> objects) {
+ public SectionAdapter getAdapter(List<Serializable> objects) {
return new ArtistAdapter(context, objects, musicFolders, this, this);
}
@Override
- public List<Artist> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
- List<Artist> artists;
+ public List<Serializable> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
+ List<Serializable> items;
if(groupId == null) {
if (!Util.isOffline(context) && (!Util.isTagBrowsing(context) || ServerInfo.checkServerVersion(context, "1.14"))) {
musicFolders = musicService.getMusicFolders(refresh, context, listener);
@@ -181,14 +201,16 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Artist> impleme
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
indexes.sortChildren(context);
- artists = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
- artists.addAll(indexes.getShortcuts());
- artists.addAll(indexes.getArtists());
+ items = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
+ items.addAll(indexes.getShortcuts());
+ items.addAll(indexes.getArtists());
entries = indexes.getEntries();
+ items.addAll(entries);
} else {
- artists = new ArrayList<>();
+ List<Artist> artists = new ArrayList<>();
+ items = new ArrayList<>();
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
- for(MusicDirectory.Entry entry: dir.getChildren(true, false)) {
+ for(Entry entry: dir.getChildren(true, false)) {
Artist artist = new Artist();
artist.setId(entry.getId());
artist.setName(entry.getTitle());
@@ -196,21 +218,17 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Artist> impleme
artists.add(artist);
}
- entries = new ArrayList<>();
- entries.addAll(dir.getChildren(false, true));
- if(!entries.isEmpty()) {
- Artist root = new Artist();
- root.setId("root");
- root.setName("Root");
- root.setIndex("#");
- artists.add(root);
- }
-
- Indexes indexes = new Indexes(0, artists, new ArrayList<Artist>());
+ Indexes indexes = new Indexes(0, new ArrayList<Artist>(), artists);
indexes.sortChildren(context);
+ items.addAll(indexes.getArtists());
+
+ entries = dir.getChildren(false, true);
+ for(Entry entry: entries) {
+ items.add(entry);
+ }
}
- return artists;
+ return items;
}
@Override
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
index 67dcc6a2..de74d0ed 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java
@@ -234,7 +234,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
if(!ServerInfo.hasTopSongs(context)) {
menu.removeItem(R.id.menu_top_tracks);
}
- if(!ServerInfo.checkServerVersion(context, "1.11") || (id != null && "root".equals(id))) {
+ if(!ServerInfo.checkServerVersion(context, "1.11")) {
menu.removeItem(R.id.menu_radio);
menu.removeItem(R.id.menu_similar_artists);
} else if(!ServerInfo.hasSimilarArtists(context)) {
@@ -379,9 +379,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
@Override
protected void refresh(boolean refresh) {
- if(!"root".equals(id)) {
- load(refresh);
- }
+ load(refresh);
}
@Override
@@ -747,11 +745,14 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section
if(!artist) {
entryGridAdapter.setShowArtist(true);
}
+ if(topTracks) {
+ entryGridAdapter.setShowAlbum(true);
+ }
// Show header if not album list type and not root and not artist
// For Subsonic 5.1+ display a header for artists with getArtistInfo data if it exists
boolean addedHeader = false;
- if(albumListType == null && !"root".equals(id) && (!artist || artistInfo != null || artistInfoDelayed != null) && (share == null || entries.size() != albums.size())) {
+ if(albumListType == null && (!artist || artistInfo != null || artistInfoDelayed != null) && (share == null || entries.size() != albums.size())) {
View header = createHeader();
if(header != null) {
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java
index 7ae7fff8..0d4506ac 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java
@@ -15,10 +15,15 @@
package github.daneren2005.dsub.fragments;
+import android.app.SearchManager;
+import android.app.SearchableInfo;
+import android.content.Context;
import android.os.Bundle;
+import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -102,6 +107,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme
}
menuInflater.inflate(getOptionsMenu(), menu);
+ onFinishSetupOptionsMenu(menu);
}
@Override
diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
index f733c977..9cc27128 100644
--- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
+++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java
@@ -20,6 +20,9 @@ package github.daneren2005.dsub.fragments;
import android.annotation.TargetApi;
import android.app.Activity;
+import android.app.SearchManager;
+import android.app.SearchableInfo;
+import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -37,6 +40,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Menu;
@@ -125,6 +129,8 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
protected boolean artistOverride = false;
protected SwipeRefreshLayout refreshLayout;
protected boolean firstRun;
+ protected MenuItem searchItem;
+ protected SearchView searchView;
public SubsonicFragment() {
super();
@@ -177,15 +183,36 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
this.context = context;
}
+ protected void onFinishSetupOptionsMenu(final Menu menu) {
+ searchItem = menu.findItem(R.id.menu_global_search);
+ if(searchItem != null) {
+ searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
+ SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+ SearchableInfo searchableInfo = searchManager.getSearchableInfo(context.getComponentName());
+ if(searchableInfo == null) {
+ Log.w(TAG, "Failed to get SearchableInfo");
+ } else {
+ searchView.setSearchableInfo(searchableInfo);
+ }
+
+ String currentQuery = getCurrentQuery();
+ if(currentQuery != null) {
+ searchView.setOnSearchClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ searchView.setQuery(getCurrentQuery(), false);
+ }
+ });
+ }
+ }
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_global_shuffle:
onShuffleRequested();
return true;
- case R.id.menu_global_search:
- context.onSearchRequested();
- return true;
case R.id.menu_exit:
exit();
return true;
@@ -1927,6 +1954,10 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR
return false;
}
+ protected String getCurrentQuery() {
+ return null;
+ }
+
public abstract class RecursiveLoader extends LoadingTask<Boolean> {
protected MusicService musicService;
protected static final int MAX_SONGS = 500;
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
index 20126f01..e4bab798 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadFile.java
@@ -84,6 +84,9 @@ public class DownloadFile implements BufferFile {
public MusicDirectory.Entry getSong() {
return song;
}
+ public boolean isSong() {
+ return song.isSong();
+ }
public Context getContext() {
return context;
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
index 98e678c1..7168083c 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -88,6 +88,7 @@ import android.support.v7.media.MediaRouteSelector;
import android.support.v7.media.MediaRouter;
import android.util.Log;
import android.support.v4.util.LruCache;
+import android.view.KeyEvent;
/**
* @author Sindre Mehus
@@ -1169,8 +1170,8 @@ public class DownloadService extends Service {
}
// If only one song, just skip within song
- if(size() == 1) {
- seekTo(getPlayerPosition() - REWIND);
+ if(size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) {
+ rewind();
return;
}
@@ -1195,8 +1196,8 @@ public class DownloadService extends Service {
}
public synchronized void next(boolean forceCutoff, boolean forceStart) {
// If only one song, just skip within song
- if(size() == 1) {
- seekTo(getPlayerPosition() + FAST_FORWARD);
+ if(size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) {
+ fastForward();
return;
} else if(playerState == PREPARING || playerState == PREPARED) {
return;
@@ -2719,6 +2720,10 @@ public class DownloadService extends Service {
wakeLock.acquire(ms);
}
+ public void handleKeyEvent(KeyEvent keyEvent) {
+ lifecycleSupport.handleKeyEvent(keyEvent);
+ }
+
public void addOnSongChangedListener(OnSongChangedListener listener) {
addOnSongChangedListener(listener, false);
}
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java
index 5e9e04fc..f8272356 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java
@@ -386,7 +386,7 @@ public class DownloadServiceLifecycleSupport {
return lastChange;
}
- private void handleKeyEvent(KeyEvent event) {
+ public void handleKeyEvent(KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) {
switch (event.getKeyCode()) {
case RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS:
diff --git a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
index 4c3a121d..1f9e5494 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java
@@ -608,7 +608,7 @@ public class RESTMusicService implements MusicService {
int decade = Integer.parseInt(extra);
// Reverse chronological order only supported in 5.3+
- if(ServerInfo.checkServerVersion(context, "1.13", instance) && ServerInfo.isStockSubsonic(context, instance)) {
+ if(ServerInfo.checkServerVersion(context, "1.13", instance) && !ServerInfo.isMadsonic(context, instance)) {
values.add(decade + 9);
values.add(decade);
} else {
@@ -696,7 +696,13 @@ public class RESTMusicService implements MusicService {
int instance = getInstance(context);
String method;
- if(ServerInfo.isMadsonic(context, instance)) {
+ if(ServerInfo.isMadsonic6(context, instance)) {
+ if (Util.isTagBrowsing(context, instance)) {
+ method = "getSimilarSongsID3";
+ } else {
+ method = "getSimilarSongs";
+ }
+ } else if(ServerInfo.isMadsonic(context, instance)) {
method = "getPandoraSongs";
} else {
if (Util.isTagBrowsing(context, instance)) {
@@ -1942,7 +1948,7 @@ public class RESTMusicService implements MusicService {
for (int i = 0; i < parameterNames.size(); i++) {
builder.append("&").append(parameterNames.get(i)).append("=");
String part = URLEncoder.encode(String.valueOf(parameterValues.get(i)), "UTF-8");
- part = part.replaceAll("\\%27", "&#39;");
+ part = part.replaceAll("\\%27", "'");
builder.append(part);
}
url = builder.toString();
diff --git a/app/src/main/java/github/daneren2005/dsub/util/BackgroundTask.java b/app/src/main/java/github/daneren2005/dsub/util/BackgroundTask.java
index fce855fe..31e83200 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/BackgroundTask.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/BackgroundTask.java
@@ -208,8 +208,18 @@ public abstract class BackgroundTask<T> implements ProgressListener {
handler.post(new Runnable() {
@Override
public void run() {
- if(!isCancelled()) {
- onDone(result);
+ if (!isCancelled()) {
+ try {
+ onDone(result);
+ } catch (Throwable t) {
+ if(!isCancelled()) {
+ try {
+ onError(t);
+ } catch(Exception e) {
+ // Don't care
+ }
+ }
+ }
}
taskStart.set(false);
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Constants.java b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
index 230cce16..c8c580ff 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Constants.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Constants.java
@@ -191,6 +191,7 @@ public final class Constants {
public static final String MAIN_BACK_STACK = "backStackIds";
public static final String MAIN_BACK_STACK_SIZE = "backStackIdsSize";
public static final String MAIN_NOW_PLAYING = "nowPlayingId";
+ public static final String MAIN_NOW_PLAYING_SECONDARY = "nowPlayingSecondaryId";
public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState";
public static final String FRAGMENT_LIST = "fragmentList";
public static final String FRAGMENT_LIST2 = "fragmentList2";
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java
index c3f1a086..9f742ef0 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Util.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java
@@ -412,13 +412,15 @@ public final class Util {
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
if(allowAltAddress && Util.isWifiConnected(context)) {
String SSID = prefs.getString(Constants.PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID + instance, "");
- String currentSSID = Util.getSSID(context);
-
- String[] ssidParts = SSID.split(",");
- if("".equals(SSID) || SSID.equals(currentSSID) || Arrays.asList(ssidParts).contains(currentSSID)) {
- String internalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance, null);
- if(internalUrl != null && !"".equals(internalUrl) && !"http://".equals(internalUrl)) {
- serverUrl = internalUrl;
+ if(!SSID.isEmpty()) {
+ String currentSSID = Util.getSSID(context);
+
+ String[] ssidParts = SSID.split(",");
+ if ("".equals(SSID) || SSID.equals(currentSSID) || Arrays.asList(ssidParts).contains(currentSSID)) {
+ String internalUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance, null);
+ if (internalUrl != null && !"".equals(internalUrl) && !"http://".equals(internalUrl)) {
+ serverUrl = internalUrl;
+ }
}
}
}
@@ -919,6 +921,10 @@ public final class Util {
return formatDate(context, dateString, true);
}
public static String formatDate(Context context, String dateString, boolean includeTime) {
+ if(dateString == null) {
+ return "";
+ }
+
try {
dateString = dateString.replace(' ', 'T');
boolean isDateNormalized = ServerInfo.checkServerVersion(context, "1.11");
diff --git a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
index d210fbb0..df468155 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java
@@ -34,7 +34,10 @@ import android.media.session.PlaybackState;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
+import android.support.annotation.NonNull;
import android.support.v7.media.MediaRouter;
+import android.util.Log;
+import android.view.KeyEvent;
import java.io.Serializable;
import java.util.ArrayList;
@@ -145,11 +148,17 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
position = downloadService.getPlayerPosition();
}
builder.setState(newState, position, 1.0f);
- builder.setActions(getPlaybackActions());
-
DownloadFile downloadFile = downloadService.getCurrentPlaying();
+ Entry entry = null;
+ boolean isSong = true;
if(downloadFile != null) {
- Entry entry = downloadFile.getSong();
+ entry = downloadFile.getSong();
+ isSong = entry.isSong();
+ }
+
+ builder.setActions(getPlaybackActions(isSong));
+
+ if(entry != null) {
addCustomActions(entry, builder);
builder.setActiveQueueItemId(entry.getId().hashCode());
}
@@ -231,7 +240,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
return mediaSession;
}
- protected long getPlaybackActions() {
+ protected long getPlaybackActions(boolean isSong) {
long actions = PlaybackState.ACTION_PLAY |
PlaybackState.ACTION_PAUSE |
PlaybackState.ACTION_SEEK_TO |
@@ -239,10 +248,15 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
int currentIndex = downloadService.getCurrentPlayingIndex();
int size = downloadService.size();
- if(currentIndex > 0) {
+ if(isSong) {
+ if (currentIndex > 0) {
+ actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
+ }
+ if (currentIndex < size - 1) {
+ actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
+ }
+ } else {
actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
- }
- if(currentIndex < size - 1) {
actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
}
@@ -311,7 +325,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
return null;
}
-
+
private void playFromParent(Entry parent) throws Exception {
List<Entry> songs = new ArrayList<>();
getSongsRecursively(parent, songs);
@@ -569,5 +583,18 @@ public class RemoteControlClientLP extends RemoteControlClientBase {
downloadService.toggleStarred();
}
}
+
+ @Override
+ public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
+ if (getMediaSession() != null && Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {
+ KeyEvent keyEvent = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
+ if (keyEvent != null) {
+ downloadService.handleKeyEvent(keyEvent);
+ return true;
+ }
+ }
+
+ return super.onMediaButtonEvent(mediaButtonIntent);
+ }
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/CardView.java b/app/src/main/java/github/daneren2005/dsub/view/CardView.java
index b9e0bcce..d6bca330 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/CardView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/CardView.java
@@ -61,7 +61,6 @@ public class CardView extends FrameLayout{
// clipPath is not supported with Hardware Acceleration before API 18
// http://stackoverflow.com/questions/8895677/work-around-canvas-clippath-that-is-not-supported-in-android-any-more/8895894#8895894
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2 && isHardwareAccelerated()) {
- Log.d(TAG, "Change to software");
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
}
diff --git a/app/src/main/java/github/daneren2005/dsub/view/SongView.java b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
index 84e04a0b..8cb0c21c 100644
--- a/app/src/main/java/github/daneren2005/dsub/view/SongView.java
+++ b/app/src/main/java/github/daneren2005/dsub/view/SongView.java
@@ -71,6 +71,7 @@ public class SongView extends UpdateView2<MusicDirectory.Entry, Boolean> {
private boolean showPodcast = false;
private boolean isPlayed = false;
private boolean isPlayedShown = false;
+ private boolean showAlbum = false;
public SongView(Context context) {
super(context);
@@ -114,7 +115,11 @@ public class SongView extends UpdateView2<MusicDirectory.Entry, Boolean> {
}
}
else if(song.getArtist() != null) {
- artist.append(song.getArtist());
+ if(showAlbum) {
+ artist.append(song.getAlbum());
+ } else {
+ artist.append(song.getArtist());
+ }
}
if(isPodcast) {
@@ -354,4 +359,8 @@ public class SongView extends UpdateView2<MusicDirectory.Entry, Boolean> {
public void setShowPodcast(boolean showPodcast) {
this.showPodcast = showPodcast;
}
+
+ public void setShowAlbum(boolean showAlbum) {
+ this.showAlbum = showAlbum;
+ }
}
diff --git a/app/src/main/res/menu/abstract_top_menu.xml b/app/src/main/res/menu/abstract_top_menu.xml
index 7c8d414d..b768879d 100644
--- a/app/src/main/res/menu/abstract_top_menu.xml
+++ b/app/src/main/res/menu/abstract_top_menu.xml
@@ -5,7 +5,8 @@
android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
- compat:showAsAction="always|withText"/>
+ compat:actionViewClass="android.support.v7.widget.SearchView"
+ compat:showAsAction="always|collapseActionView"/>
<group android:id="@+id/not_touchscreen">
<item
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
index 0970c8ce..4b542668 100644
--- a/app/src/main/res/menu/main.xml
+++ b/app/src/main/res/menu/main.xml
@@ -5,13 +5,14 @@
android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
- compat:showAsAction="always|withText"/>
+ compat:actionViewClass="android.support.v7.widget.SearchView"
+ compat:showAsAction="ifRoom|collapseActionView"/>
<item
android:id="@+id/menu_global_shuffle"
android:icon="?attr/shuffle"
android:title="@string/menu.shuffle"
- compat:showAsAction="always|withText"/>
+ compat:showAsAction="ifRoom|withText"/>
<group android:id="@+id/madsonic">
<item
diff --git a/app/src/main/res/menu/search.xml b/app/src/main/res/menu/search.xml
index e9377d68..b957a1e4 100644
--- a/app/src/main/res/menu/search.xml
+++ b/app/src/main/res/menu/search.xml
@@ -5,7 +5,8 @@
android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
- compat:showAsAction="ifRoom|withText"/>
+ compat:actionViewClass="android.support.v7.widget.SearchView"
+ compat:showAsAction="always|collapseActionView"/>
<item
android:id="@+id/menu_exit"
diff --git a/app/src/main/res/menu/select_artist.xml b/app/src/main/res/menu/select_artist.xml
index f94cda8b..e974c28e 100644
--- a/app/src/main/res/menu/select_artist.xml
+++ b/app/src/main/res/menu/select_artist.xml
@@ -5,13 +5,14 @@
android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
- compat:showAsAction="always|withText"/>
+ compat:actionViewClass="android.support.v7.widget.SearchView"
+ compat:showAsAction="ifRoom|collapseActionView"/>
<item
android:id="@+id/menu_global_shuffle"
android:icon="?attr/shuffle"
android:title="@string/menu.shuffle"
- compat:showAsAction="always|withText"/>
+ compat:showAsAction="ifRoom|withText"/>
<group android:id="@+id/not_touchscreen">
<item
diff --git a/app/src/main/res/menu/select_podcasts.xml b/app/src/main/res/menu/select_podcasts.xml
index 41ad62fa..25bb6188 100644
--- a/app/src/main/res/menu/select_podcasts.xml
+++ b/app/src/main/res/menu/select_podcasts.xml
@@ -5,13 +5,14 @@
android:id="@+id/menu_global_search"
android:icon="?attr/search"
android:title="@string/menu.search"
- compat:showAsAction="always|withText"/>
+ compat:actionViewClass="android.support.v7.widget.SearchView"
+ compat:showAsAction="ifRoom|collapseActionView"/>
<item
android:id="@+id/menu_add_podcast"
android:icon="?attr/add"
android:title="@string/menu.add_podcast"
- compat:showAsAction="always|withText"/>
+ compat:showAsAction="ifRoom|withText"/>
<group android:id="@+id/not_touchscreen">
<item
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 41532874..6b1089c6 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -430,12 +430,12 @@
<string name="admin.change_username_invalid">Saisir un nom d\'utilisateur valide</string>
<string name="admin.update_permissions">Mettre à jour les autorisations</string>
<string name="admin.update_permissions_success">Autorisation mises à jour pour %1$s</string>
- <string name="admin.update_permissions_error">Échec lors de lamise à jour des autorisations de %1$s</string>
- <string name="admin.change_email">Modifier Email</string>
+ <string name="admin.update_permissions_error">Échec lors de la mise à jour des autorisations de %1$s</string>
+ <string name="admin.change_email">Modifier l\'email</string>
<string name="admin.change_email_success">Email remplacé pour %1$s</string>
- <string name="admin.change_email_error">Échec lors du remplacement de l\'Email de %1$s</string>
- <string name="admin.change_email_label">Nouvel Email :</string>
- <string name="admin.change_email_invalid">Saisir un Email valide</string>
+ <string name="admin.change_email_error">Échec lors du remplacement de l\'email de %1$s</string>
+ <string name="admin.change_email_label">Nouvel email :</string>
+ <string name="admin.change_email_invalid">Saisir un email valide</string>
<string name="admin.change_password">Modifier le mot de passe</string>
<string name="admin.change_password_success">Mot de passe modifié pour %1$s</string>
<string name="admin.change_password_error">Échec du remplacement du mot de passe pour %1$s</string>
@@ -478,7 +478,7 @@
<string name="parser.scan_count">%d entrées trouvées</string>
<string name="select_artist.folder">Sélectionner un dossier</string>
- <string name="select_artist.all_folders">Tous les dossier</string>
+ <string name="select_artist.all_folders">Tous les dossiers</string>
<string name="equalizer.label">Équaliseur</string>
<string name="equalizer.enabled">Activé</string>
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 246f697f..6cf7a8d6 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -6,7 +6,7 @@
<string name="common.save">Guardar</string>
<string name="common.cancel">Cancelar</string>
<string name="common.play_now">Reproduzir</string>
- <string name="common.play_shuffled">Reproduzir aleatóriamente</string>
+ <string name="common.play_shuffled">Reproduzir aleatoriamente</string>
<string name="common.play_next">Reproduzir a seguir</string>
<string name="common.play_last">Reproduzir no final</string>
<string name="common.download">Cache</string>
@@ -43,7 +43,7 @@
<string name="button_bar.offline">Offline</string>
<string name="main.welcome_title">Bem-vindo!</string>
- <string name="main.welcome_text">Bem-vindo ao DSub! De momento a aplicação está configurada para usar o servidor de demonstração do Subsonic. Depois de configurar o seu servidor pessoal (disponível em <b>subsonic.org</b>), vá às <b>Definições</b> e altere as configurações de modo a que possa conectar-se.</string>
+ <string name="main.welcome_text">Bem-vindo ao DSub! Atualmente a aplicação está configurada para usar o servidor de demonstração do Subsonic. Depois de configurar o seu servidor pessoal (disponível em <b>subsonic.org</b>), vá às <b>Definições</b> e altere as configurações para que possa conectar-se.</string>
<string name="main.about_title">Sobre o DSub</string>
<string name="main.faq_title">FAQ</string>
<string name="main.faq_text">
@@ -73,8 +73,12 @@
<string name="main.albums_alphabetical">Alfabeticamente</string>
<string name="main.videos">Vídeos</string>
<string name="main.songs_genres">@string/main.albums_genres</string>
+ <string name="main.songs_newest">@string/main.albums_newest</string>
+ <string name="main.songs_top_played">Top de reproduções</string>
+ <string name="main.songs_recent">@string/main.albums_recent</string>
+ <string name="main.songs_frequent">@string/main.albums_frequent</string>
<string name="main.back_confirm">Prima \"voltar\" novamente para sair</string>
- <string name="main.scan_complete">Análise ao servidor completa</string>
+ <string name="main.scan_complete">A análise ao servidor foi concluída</string>
<string name="main.artist">Artista</string>
<string name="main.title">Título</string>
@@ -89,8 +93,8 @@
<string name="menu.about">Sobre</string>
<string name="menu.add_playlist">Adicionar à lista de reprodução</string>
<string name="menu.remove_playlist">Remover da lista de reprodução</string>
- <string name="menu.deleted_playlist">Lista de reprodução eliminada %s</string>
- <string name="menu.deleted_playlist_error">Falha ao eliminar lista de reprodução %s</string>
+ <string name="menu.deleted_playlist">A lista de reprodução %s foi eliminada</string>
+ <string name="menu.deleted_playlist_error">Falha ao eliminar a lista de reprodução %s</string>
<string name="menu.log">Enviar relatório</string>
<string name="menu.set_timer">Definir temporizador</string>
<string name="menu.check_podcasts">Procurar novos episódios</string>
@@ -106,16 +110,17 @@
<string name="menu.add_user">Adicionar utilizador</string>
<string name="menu.rescan">Reanalisar</string>
<string name="menu.rate">Classificar</string>
- <string name="menu.top_tracks">Top faixas do Last.FM</string>
+ <string name="menu.top_tracks">Top de faixas do Last.FM</string>
<string name="menu.similar_artists">Artistas semelhantes</string>
+ <string name="menu.similar_artists.missing">Artistas em falta</string>
<string name="menu.start_radio">Iniciar rádio</string>
<string name="menu.first_level_artist">Artistas no primeiro nível</string>
<string name="playlist.label">Listas de reprodução</string>
<string name="playlist.update_info">Atualizar informação</string>
- <string name="playlist.updated_info">Informação atualizada para a lista de reprodução %s</string>
+ <string name="playlist.updated_info">A informação da lista de reprodução %s foi atualizada</string>
<string name="playlist.updated_info_error">Falha ao atualizar a informação da lista de reprodução %s</string>
- <string name="playlist.overwrite">Substituir lista de reprodução atual</string>
+ <string name="playlist.overwrite">Substituir a lista de reprodução atual</string>
<string name="playlist.add_to">Adicionar à lista de reprodução</string>
<string name="playlist.create_new">Criar nova</string>
<string name="playlist.delete">Eliminar lista de reprodução</string>
@@ -135,18 +140,18 @@
<string name="select_album.offline">Offline</string>
<string name="select_album.no_sdcard">Erro: Cartão SD não disponível.</string>
<string name="select_album.no_network">Aviso: Sem ligação à rede.</string>
- <string name="select_album.no_room">Aviso: apenas tem %s restantes</string>
- <string name="select_album.not_licensed">Servidor sem licença. %d dias de teste restantes.</string>
- <string name="select_album.donate_dialog_message">Obtenha transferências ilimitadas ao doar para o Subsonic.</string>
+ <string name="select_album.no_room">Aviso: Apenas tem %s restantes</string>
+ <string name="select_album.not_licensed">Servidor sem licença. %d dias de experimentação restantes.</string>
+ <string name="select_album.donate_dialog_message">Obtenha transferências ilimitadas fazendo um donativo ao Subsonic.</string>
<string name="select_album.donate_dialog_now">Agora</string>
<string name="select_album.donate_dialog_later">Depois</string>
- <string name="select_album.donate_dialog_0_trial_days_left">Período de teste terminado</string>
+ <string name="select_album.donate_dialog_0_trial_days_left">Período de experimentação terminado</string>
<string name="offline.sync_dialog_title">Músicas offline à espera de serem sincronizadas</string>
<string name="offline.sync_dialog_message">Processar %1$d scrobbles offline?
\nProcessar %2$d estrelas offline?
</string>
- <string name="offline.sync_dialog_default">Usar ação como predefinida</string>
+ <string name="offline.sync_dialog_default">Usar a ação como predefinida</string>
<string name="offline.sync_success">Sincronizadas com sucesso %1$d músicas</string>
<string name="offline.sync_partial">Sincronizadas com sucesso %1$d de %2$d músicas</string>
<string name="offline.sync_error">Falha ao sincronizar músicas</string>
@@ -174,8 +179,9 @@
<string name="download.shuffle_loading">A carregar lista aleatória...</string>
<string name="download.playerstate_downloading">A transferir - %s</string>
<string name="download.playerstate_mobile_disabled">À espera de rede Wi-Fi para transferir</string>
- <string name="download.playerstate_buffering">Buffering</string>
- <string name="download.playerstate_playing_shuffle">A reproduzir aleatóriamente</string>
+ <string name="download.playerstate_buffering">A colocar na memória intermédia</string>
+ <string name="download.playerstate_playing_shuffle">Modo aleatório</string>
+ <string name="download.playerstate_playing_artist_radio">Rádio do artista</string>
<string name="download.menu_show_album">Mostrar álbum</string>
<string name="download.menu_lyrics">Letra</string>
<string name="download.menu_remove_all">Remover tudo</string>
@@ -183,19 +189,19 @@
<string name="download.menu_shuffle">Aleatório</string>
<string name="download.menu_toggle">Alternar</string>
<string name="download.menu_save">Guardar lista de reprodução</string>
- <string name="download.menu_shuffle_notification">Lista de reprodução foi aleatorizada</string>
+ <string name="download.menu_shuffle_notification">A lista de reprodução foi aleatorizada</string>
<string name="download.menu_remove_played_songs">Remover músicas reproduzidas</string>
<string name="download.playlist_title">Guardar lista de reprodução</string>
<string name="download.playlist_name">Introduza o nome da lista de reprodução:</string>
- <string name="download.playlist_saving">A guardar lista de reprodução \"%s\"...</string>
- <string name="download.playlist_done">Lista de reprodução guardada com sucesso.</string>
- <string name="download.playlist_error">Falha ao guardar lista de reprodução, tente novamente mais tarde.</string>
+ <string name="download.playlist_saving">A guardar a lista de reprodução \"%s\"...</string>
+ <string name="download.playlist_done">A lista de reprodução foi guardada com sucesso.</string>
+ <string name="download.playlist_error">Falha ao guardar a lista de reprodução, tente novamente mais tarde.</string>
<string name="download.repeat_off">Repetição desligada</string>
<string name="download.repeat_all">Repetir tudo</string>
<string name="download.repeat_single">Repetir música</string>
- <string name="download.jukebox_server_too_old">Controlo remoto não é suportado. Por favor atualize o seu servidor Subsonic.</string>
- <string name="download.jukebox_offline">Controlo remoto não está disponível em modo offline.</string>
- <string name="download.jukebox_not_authorized">Controlo remoto não é permitido. Por favor ative o modo jukebox em <b>Utilizadores &gt; Definições</b> no seu servidor Subsonic.</string>
+ <string name="download.jukebox_server_too_old">O controlo remoto não é suportado. Por favor atualize o seu servidor Subsonic.</string>
+ <string name="download.jukebox_offline">O controlo remoto não está disponível em modo offline.</string>
+ <string name="download.jukebox_not_authorized">O controlo remoto não é permitido. Por favor ative o modo jukebox em <b>Utilizadores &gt; Definições</b> no seu servidor Subsonic.</string>
<string name="download.start_timer">Iniciar temporizador</string>
<string name="download.stop_time_remaining">Para em %1$s</string>
<string name="download.need_download">O vídeo deve ser transferido primeiro</string>
@@ -212,6 +218,7 @@
<string name="download.restore_play_queue">continuar onde ficou no outro dispositivo em</string>
<string name="download.thumbs_up">Gosto</string>
<string name="download.thumbs_down">Não gosto</string>
+ <string name="download.batch_mode">Modo em série</string>
<string name="sync.new_podcasts">Novos podcasts disponíveis</string>
<string name="sync.new_playlists">Novas músicas nas listas de reprodução</string>
@@ -222,7 +229,7 @@
<string name="starring_content_unstarred">A estrela de \"%s\" foi removida</string>
<string name="starring_content_error">Falha ao atualizar \"%s\", tente novamente mais tarde.</string>
- <string name="playlist.mine">Minhas listas de reprodução</string>
+ <string name="playlist.mine">As minhas listas de reprodução</string>
<string name="playlist.shared">Listas de reprodução partilhadas</string>
<string name="playlist_error">Falha ao obter lista de listas de reprodução</string>
<string name="updated_playlist">Adicionadas %1$s músicas a \"%2$s\"</string>
@@ -230,9 +237,9 @@
<string name="removed_playlist">Removidas %1$s músicas de \"%2$s\"</string>
<string name="bookmark.delete">Remover marcador</string>
- <string name="bookmark.delete_title">Remover o marcador para</string>
- <string name="bookmark.deleted">Removido o marcador para \"%s\"</string>
- <string name="bookmark.deleted_error">Falha ao eliminar o marcador para \"%s\"</string>
+ <string name="bookmark.delete_title">Remover o marcador de</string>
+ <string name="bookmark.deleted">O marcador de \"%s\" foi removido</string>
+ <string name="bookmark.deleted_error">Falha ao remover o marcador de \"%s\"</string>
<string name="bookmark.details_title">Detalhes do marcador</string>
<string name="bookmark.resume_title">Continuar a reprodução?</string>
<string name="bookmark.resume">Continuar a reprodução \'%1$s\' desde %2$s</string>
@@ -242,11 +249,11 @@
<string name="rating.title">Classificar \"%s\"</string>
<string name="rating.set_rating">Classificação de \"%s\" definida com êxito</string>
<string name="rating.set_rating_failed">Falha ao classificar \"%s\"</string>
- <string name="rating.remove_rating">Removida a classificação de \"%s\"</string>
+ <string name="rating.remove_rating">A classificação de \"%s\" foi removida</string>
<string name="rating.remove_rating_failed">Falha ao remover a classificação de \"%s\"</string>
<string name="song_details.error">Erro</string>
- <string name="song_details.skipped">Saltado</string>
+ <string name="song_details.skipped">Avançado</string>
<string name="song_details.downloading">A transferir</string>
<string name="lyrics.nomatch">Não foram encontradas letras</string>
@@ -258,7 +265,7 @@
<string name="settings.servers_add">Adicionar servidor</string>
<string name="settings.servers_remove">Remover servidor</string>
<string name="settings.servers_title">Servidores</string>
- <string name="settings.server_unused">Não usados</string>
+ <string name="settings.server_unused">Não usado</string>
<string name="settings.server_name">Nome</string>
<string name="settings.server_address">Endereço do servidor</string>
<string name="settings.server_local_network_ssid" >SSID da rede local</string>
@@ -271,13 +278,15 @@
<string name="settings.server_sync">Sincronização ativa</string>
<string name="settings.cache_title">Cache de música</string>
<string name="settings.preload_wifi">Músicas para pre-carregar (Wi-Fi)</string>
- <string name="settings.preload_mobile">Músicas para pre-carregar (Dados móveis)</string>
+ <string name="settings.preload_mobile">Músicas para pre-carregar (dados móveis)</string>
<string name="settings.cache_size">Tamanho da cache</string>
<string name="settings.cache_location">Localização da cache</string>
<string name="settings.cache_location_error">Localização da cache inválida. A utilizar predefinição.</string>
<string name="settings.cache_location_reset">Não foi possível escrever na localização da cache que definiu. Se atualizou recentemente o SO do seu dispositivo para o KitKat 4.4, então o modo como as aplicações escrevem no cartão SD mudou e só podem escrever numa localização específica. A localização que o DSub usa já foi alterada para a localização correta. Para eliminar os antigos dados da aplicação, terá que montar o cartão SD no computador e eliminar a pasta manualmente</string>
+ <string name="settings.cache_location_internal">Interna</string>
+ <string name="settings.cache_location_external">Externa</string>
<string name="settings.cache_clear">Limpar cache</string>
- <string name="settings.cache_clear_complete">Limpeza da cache terminada</string>
+ <string name="settings.cache_clear_complete">A limpeza da cache foi concluída</string>
<string name="settings.testing_connection">A testar ligação...</string>
<string name="settings.testing_ok">A ligação está OK</string>
<string name="settings.testing_unlicensed">A ligação está OK. Servidor sem licença.</string>
@@ -293,14 +302,14 @@
<string name="settings.theme_fullscreen">Ecrã inteiro</string>
<string name="settings.theme_fullscreen_summary">Ocultar o maior número de elementos da interface que o Android permita</string>
<string name="settings.track_title">Mostrar número da faixa</string>
- <string name="settings.track_summary">Mostrar número da faixa no ínicio da música se existir</string>
+ <string name="settings.track_summary">Mostrar o número da faixa no início da música se existir</string>
<string name="settings.custom_sort">Ordenar por ano</string>
- <string name="settings.custom_sort_summary">Ordenar álbuns por ano, ou alfabeticamente</string>
+ <string name="settings.custom_sort_summary">Ordenar os álbuns por ano, ou alfabeticamente</string>
<string name="settings.open_to_tab">Abrir para separador</string>
<string name="settings.open_to_tab_summary">Abrir diretamente para este separador</string>
<string name="settings.network_title">Rede</string>
- <string name="settings.max_bitrate_wifi">Bitrate de áudio máximo - Wi-Fi</string>
- <string name="settings.max_bitrate_mobile">Bitrate de áudio máximo - Dados móveis</string>
+ <string name="settings.max_bitrate_wifi">Taxa de bits máxima do áudio - Wi-Fi</string>
+ <string name="settings.max_bitrate_mobile">Taxa de bits máxima do áudio - Dados móveis</string>
<string name="settings.max_bitrate_32">32 Kbps</string>
<string name="settings.max_bitrate_64">64 Kbps</string>
<string name="settings.max_bitrate_80">80 Kbps</string>
@@ -311,8 +320,8 @@
<string name="settings.max_bitrate_192">192 Kbps</string>
<string name="settings.max_bitrate_256">256 Kbps</string>
<string name="settings.max_bitrate_320">320 Kbps</string>
- <string name="settings.max_video_bitrate_wifi">Bitrate de vídeo máximo - Wi-Fi</string>
- <string name="settings.max_video_bitrate_mobile">Bitrate de vídeo máximo - Dados móveis</string>
+ <string name="settings.max_video_bitrate_wifi">Taxa de bits máxima do vídeo - Wi-Fi</string>
+ <string name="settings.max_video_bitrate_mobile">Taxa de bits máxima do vídeo - Dados móveis</string>
<string name="settings.max_video_bitrate_200">200 Kbps</string>
<string name="settings.max_video_bitrate_300">300 Kbps</string>
<string name="settings.max_video_bitrate_400">400 Kbps</string>
@@ -340,17 +349,17 @@
<string name="settings.preload_10">10 músicas</string>
<string name="settings.preload_unlimited">Ilimitado</string>
<string name="settings.clear_search_history">Apagar histórico de pesquisa</string>
- <string name="settings.search_history_cleared">Histório de pesquisa apagado</string>
+ <string name="settings.search_history_cleared">O histório de pesquisa foi apagado</string>
<string name="settings.other_title">Outras definições</string>
<string name="settings.scrobble_title">Scrobble para Last.FM</string>
- <string name="settings.scrobble_summary">Lembrar de configurar o utilizador e palavra-passe do Last.FM no servidor Subsonic.</string>
+ <string name="settings.scrobble_summary">Lembrar de configurar o nome de utilizador e palavra-passe do Last.FM no servidor Subsonic</string>
<string name="settings.hide_media_title">Ocultar do resto</string>
- <string name="settings.hide_media_summary">Ocultar ficheiros de música das outras aplicações.</string>
- <string name="settings.hide_media_toast">As mudanças terão efeito na próxima vez que o Android procure músicas no seu dispositivo móvel.</string>
+ <string name="settings.hide_media_summary">Ocultar ficheiros de música das outras aplicações</string>
+ <string name="settings.hide_media_toast">As mudanças terão efeito na próxima vez que o Android procure músicas no seu dispositivo.</string>
<string name="settings.media_button_title">Botões multimédia</string>
- <string name="settings.media_button_summary">Responder aos botões multimédia do dispositivo móvel, mãos livres e Bluetooth</string>
+ <string name="settings.media_button_summary">Responder aos botões multimédia do dispositivo, mãos livres e Bluetooth</string>
<string name="settings.screen_lit_title">Manter ecrã ligado</string>
- <string name="settings.screen_lit_summary">Manter o ecrã ligado durante as transferências melhora a velocidade de transferência.</string>
+ <string name="settings.screen_lit_summary">Manter o ecrã ligado durante as transferências melhora a velocidade de transferência</string>
<string name="settings.playlist_title">Listas de reprodução</string>
<string name="settings.playlist_random_size_title">Tamanho da lista de reprodução aleatória</string>
<string name="settings.sleep_timer_title">Temporizador</string>
@@ -372,11 +381,11 @@
<string name="settings.disconnect_pause_both">Pausar</string>
<string name="settings.disconnect_pause_neither">Não fazer nada</string>
<string name="settings.persistent_title">Notificação persistente</string>
- <string name="settings.persistent_summary">Mostrar a notificação mesmo depois de pausar. Pressione o botão de parar para a remover.</string>
+ <string name="settings.persistent_summary">Mostrar a notificação mesmo depois de pausar. Pressione o botão de parar para a remover</string>
<string name="settings.gapless_playback">Reprodução sem pausas</string>
- <string name="settings.gapless_playback_summary">Se notar falhas estranhas durante a reprodução, desmarcar esta opção pode ajudar.</string>
- <string name="settings.chat_refresh">Taxa de atualização do Chat (Secs)</string>
- <string name="settings.chat_enabled">Chat ativo</string>
+ <string name="settings.gapless_playback_summary">Se notar falhas estranhas durante a reprodução, desmarcar esta opção pode ajudar</string>
+ <string name="settings.chat_refresh">Taxa de atualização do Chat (s)</string>
+ <string name="settings.chat_enabled">Ativar chat</string>
<string name="settings.chat_enabled_summary">Mostrar ou não a opção \"Chat\" no menu lateral</string>
<string name="settings.video_title">Vídeo</string>
<string name="settings.video_player">Reprodutor de vídeo</string>
@@ -388,15 +397,15 @@
<string name="settings.playback_title">Reprodução</string>
<string name="settings.hide_widget_title">Ocultar widget</string>
<string name="settings.hide_widget_summary">Ocultar widget depois de fechar a aplicação</string>
- <string name="settings.podcasts_enabled">Podcasts ativos</string>
- <string name="settings.podcasts_enabled_summary">Mostrar ou não a opção \"Podcasts\" na barra lateral</string>
- <string name="settings.bookmarks_enabled">Marcadores ativos</string>
- <string name="settings.bookmarks_enabled_summary">Mostrar ou não a opção \"Marcadores\" na barra lateral</string>
- <string name="settings.shares_enabled">Partilhas ativas</string>
- <string name="settings.shares_enabled_summary">Mostrar ou não a opção \"Partilhas\" na barra lateral</string>
+ <string name="settings.podcasts_enabled">Ativar podcasts</string>
+ <string name="settings.podcasts_enabled_summary">Mostrar ou não a opção \"Podcasts\" no menu lateral</string>
+ <string name="settings.bookmarks_enabled">Ativar marcadores</string>
+ <string name="settings.bookmarks_enabled_summary">Mostrar ou não a opção \"Marcadores\" no menu lateral</string>
+ <string name="settings.shares_enabled">Ativar partilhas</string>
+ <string name="settings.shares_enabled_summary">Mostrar ou não a opção \"Partilhas\" no menu lateral</string>
<string name="settings.sync_title">Sincronização</string>
<string name="settings.sync_enabled">Sincronização ativa</string>
- <string name="settings.sync_enabled_summary">Sincronizar periodicamente ou não as listas de reprodução ou podcasts por alterações</string>
+ <string name="settings.sync_enabled_summary">Verificar periodicamente ou não as listas de reprodução ou podcasts por alterações</string>
<string name="settings.sync_interval">Intervalo de sincronização</string>
<string name="settings.sync_interval_15">15 minutos</string>
<string name="settings.sync_interval_30">30 minutos</string>
@@ -416,7 +425,7 @@
<string name="settings.sync_notification_summary">Mostrar uma notificação depois de sincronizados novos conteúdos</string>
<string name="settings.menu_options.title">Opções de menu opcionais</string>
<string name="settings.menu_options.play_now_summary">Mostrar \"Reproduzir agora\" nos menus</string>
- <string name="settings.menu_options.play_shuffled_summary">Mostrar \"Reproduzir aleatóriamente\" nos menus</string>
+ <string name="settings.menu_options.play_shuffled_summary">Mostrar \"Reproduzir aleatoriamente\" nos menus</string>
<string name="settings.menu_options.play_next_summary">Mostrar \"Reproduzir a seguir\" nos menus</string>
<string name="settings.menu_options.play_last_summary">Mostrar \"Reproduzir no final\" nos menus</string>
<string name="settings.menu_options.download_summary">Mostrar \"Cache\" nos menus</string>
@@ -428,16 +437,16 @@
<string name="settings.browse_by_tags">Procurar por tags</string>
<string name="settings.browse_by_tags_summary">Procurar por tags em vez da estrutura das pastas. Requer Subsonic 4.7+</string>
<string name="settings.disable_exit_prompt">Desativar diálogo de saída</string>
- <string name="settings.disable_exit_prompt_summary">Fecha a aplicação imediatamente após pressionar o botão voltar no ecrã inicial</string>
+ <string name="settings.disable_exit_prompt_summary">Fechar a aplicação imediatamente após pressionar o botão voltar no ecrã inicial</string>
<string name="settings.override_system_language">Sobrepor linguagem do sistema</string>
- <string name="settings.override_system_language_summary">Mostra a aplicação em inglês mesmo se o DSub tiver uma tradução disponível para a linguagem do sistema. Talvez seja necessário limpar a aplicação da memória para as alterações terem efeito.</string>
+ <string name="settings.override_system_language_summary">Mostrar a aplicação em inglês mesmo se o DSub tiver uma tradução disponível para a linguagem do sistema. Poderá ser necessário limpar a aplicação da memória para as alterações terem efeito</string>
<string name="settings.drawer_items_title">Separadores laterais</string>
- <string name="settings.play_now_after">Reproduzir agora - Depois</string>
- <string name="settings.play_now_after_summary">A opção \"Reproduzir agora\" do menu de contexto reproduz todos os itens a seguir ao item selecionado (como na interface web do Subsonic)</string>
+ <string name="settings.play_now_after">Premir uma música - Reproduzir tudo</string>
+ <string name="settings.play_now_after_summary">Premir uma música adiciona à fila \"Reproduzir agora\" todas as músicas do álbum a seguir à música selecionada</string>
<string name="settings.large_album_art">Grandes capas de álbum</string>
- <string name="settings.large_album_art_summary">Mostra os álbuns com uma grande capa em vez de em lista</string>
- <string name="settings.admin_enabled">Administração ativa</string>
- <string name="settings.admin_enabled_summary">Mostrar ou não a opção \"Administração\" na barra lateral</string>
+ <string name="settings.large_album_art_summary">Mostrar os álbuns com uma grande capa em vez de em lista</string>
+ <string name="settings.admin_enabled">Ativar administração</string>
+ <string name="settings.admin_enabled_summary">Mostrar ou não a opção \"Administração\" no menu lateral</string>
<string name="settings.replay_gain">Replay Gain</string>
<string name="settings.replay_gain_summary">Escalar ou não o volume da reprodução por tags de replay gain nos álbuns e faixas</string>
<string name="settings.replay_gain_type">Ler pelas tags</string>
@@ -448,16 +457,22 @@
<string name="settings.replay_gain_untagged">Músicas sem Replay Gain</string>
<string name="settings.casting">Transmissão</string>
<string name="settings.casting_proxy">Usar dispositivo como proxy</string>
- <string name="settings.casting_proxy_summary">Transmitir tudo através do dispositivo como um proxy. Isto evita problemas como o uso de certificados auto-assinados.</string>
+ <string name="settings.casting_proxy_summary">Transmitir tudo através do dispositivo como um proxy. Isto evita problemas como o uso de certificados auto-assinados</string>
<string name="settings.rename_duplicates">Renomear faixas duplicadas</string>
- <string name="settings.rename_duplicates_summary">Renomear as faixas duplicadas para o nome do ficheiro original para que as possa distinguir.</string>
+ <string name="settings.rename_duplicates_summary">Renomear as faixas duplicadas para o nome do ficheiro original para que as possa distinguir</string>
<string name="settings.start_on_headphones">Iniciar com os auscultadores</string>
- <string name="settings.start_on_headphones_summary">Iniciar quando os auscultadores são ligados. Isto requer o uso de um serviço que inicia com o arranque para verificar o evento de ligação dos auscultadores mesmo quando o DSub não está a ser executado.</string>
+ <string name="settings.start_on_headphones_summary">Iniciar quando os auscultadores são ligados. Isto requer o uso de um serviço que inicia com o arranque, para verificar o evento de ligação dos auscultadores mesmo quando o DSub não está a ser executado</string>
<string name="settings.color_action_bar">Colorir barra de ações</string>
<string name="settings.color_action_bar.summary">Colorir ou não a barra de ações e barra de estado</string>
<string name="settings.shuffle_by_album">Aleatorizar por álbum</string>
<string name="settings.shuffle_by_album.true">Aleatorizar a ordem dos álbuns</string>
<string name="settings.shuffle_by_album.false">Aleatorizar todas as músicas juntas</string>
+ <string name="settings.casting_stream_original">Transmitir original</string>
+ <string name="settings.casting_stream_original_summary">Transmitir os ficheiros originais se suportado pelo dispositivo de transmissão</string>
+ <string name="settings.heads_up_notification">Notificações Heads Up (5.0+)</string>
+ <string name="settings.heads_up_notification_summary">Mostrar notificações de reprodução como notificações Heads Up (Android Lollipop+ apenas)</string>
+ <string name="settings.casting_cache">Cache durante a transmissão</string>
+ <string name="settings.casting_cache_summary">Adicionar à cache as músicas a reproduzir no momento da transmissão</string>
<string name="shuffle.title">Aleatorizar por</string>
<string name="shuffle.startYear">Ano de início:</string>
@@ -467,7 +482,7 @@
<string name="share.expires">Expira em: %s</string>
<string name="share.expires_never">Nunca expira</string>
- <string name="share.deleted">Partilha %s eliminada</string>
+ <string name="share.deleted">A partilha %s foi eliminada</string>
<string name="share.deleted_error">Falha ao eliminar a partilha %s</string>
<string name="share.no_expiration">Sem expiração</string>
<string name="share.expiration">Expira em:</string>
@@ -483,25 +498,28 @@
<string name="admin.create_user_error">Falha ao criar novo utilizador</string>
<string name="admin.change_username_invalid">Introduza um nome de utilizador válido</string>
<string name="admin.update_permissions">Atualizar permissões</string>
- <string name="admin.update_permissions_success">Permissões atualizadas com sucesso para %1$s</string>
- <string name="admin.update_permissions_error">Falha ao atualizar permissões para %1$s</string>
+ <string name="admin.update_permissions_success">As permissões de %1$s foram atualizadas com sucesso</string>
+ <string name="admin.update_permissions_error">Falha ao atualizar as permissões de %1$s</string>
<string name="admin.change_email">Alterar email</string>
- <string name="admin.change_email_success">Email alterado com sucesso para %1$s</string>
- <string name="admin.change_email_error">Falha ao alterar email para %1$s</string>
+ <string name="admin.change_email_success">O email de %1$s foi alterado com sucesso</string>
+ <string name="admin.change_email_error">Falha ao alterar o email de %1$s</string>
<string name="admin.change_email_label">Novo email:</string>
<string name="admin.change_email_invalid">Introduza um email válido</string>
<string name="admin.change_password">Alterar palavra-passe</string>
- <string name="admin.change_password_success">Palavra-passe alterada com sucesso para %1$s</string>
- <string name="admin.change_password_error">Falha ao alterar palavra-passe para %1$s</string>
+ <string name="admin.change_password_success">A palavra-passe de %1$s foi alterada com sucesso</string>
+ <string name="admin.change_password_error">Falha ao alterar palavra-passe de %1$s</string>
+ <string name="admin.change_password_current_label">Palavra-passe atual:</string>
<string name="admin.change_password_label">Nova palavra-passe:</string>
<string name="admin.change_password_invalid">Introduza uma palavra-passe válida</string>
<string name="admin.delete_user">Eliminar utilizador</string>
- <string name="admin.delete_user_success">Utilizador %1$s eliminado com sucesso</string>
- <string name="admin.delete_user_error">Falha ao eliminar utilizador %1$s</string>
+ <string name="admin.delete_user_success">O utilizador %1$s foi eliminado com sucesso</string>
+ <string name="admin.delete_user_error">Falha ao eliminar o utilizador %1$s</string>
<string name="admin.confirm_password">Confirmar palavra-passe</string>
- <string name="admin.confirm_password_bad">Palavra-passe introduzida está incorreta</string>
+ <string name="admin.confirm_password_bad">A palavra-passe introduzida está incorreta</string>
+ <string name="admin.permissions">Permissões</string>
+ <string name="admin.musicFolders">Pastas de músicas</string>
- <string name="admin.scrobblingEnabled">Scrobbling permitido</string>
+ <string name="admin.scrobblingEnabled">Permitir scrobbling</string>
<string name="admin.role.admin">Administrador</string>
<string name="admin.role.settings">Alterar definições</string>
<string name="admin.role.download">Transferir ficheiros originais</string>
@@ -512,14 +530,15 @@
<string name="admin.role.stream">Transmitir música</string>
<string name="admin.role.jukebox">Controlar jukebox</string>
<string name="admin.role.share">Gerir partilhas</string>
- <string name="admin.role.lastfm">Usar o Last.FM</string>
+ <string name="admin.role.video_conversion">Converter vídeos</string>
+ <string name="admin.role.lastfm">Usar a funcionalidade Last.FM</string>
- <string name="music_service.retry">Ocurreu um erro de ligação. A tentar novamente %1$d de %2$d.</string>
+ <string name="music_service.retry">Ocorreu um erro de ligação. A tentar novamente %1$d de %2$d.</string>
<string name="background_task.no_network">Este programa requer acesso à rede. Por favor ligue o Wi-Fi ou os dados móveis.</string>
- <string name="background_task.network_error">Ocurreu um erro de ligação. Por favor verifique o endereço do servidor ou tente novamente mais tarde.</string>
+ <string name="background_task.network_error">Ocorreu um erro de ligação. Por favor verifique o endereço do servidor ou tente novamente mais tarde.</string>
<string name="background_task.not_found">Recurso não encontrado. Por favor verifique o endereço do servidor.</string>
- <string name="background_task.parse_error">Ocurreu um problema ao comunicar com o servidor. Por favor verifique o endereço do servidor e verifique se consegue conectar-se usando um navegador normal no seu dispositivo.</string>
+ <string name="background_task.parse_error">Ocorreu um problema ao comunicar com o servidor. Por favor verifique o endereço do servidor e verifique se consegue conectar-se usando um navegador normal no seu dispositivo.</string>
<string name="service.connecting">A contactar o servidor, por favor aguarde.</string>
@@ -546,7 +565,7 @@
<string name="widget.4x2">DSub (4x2)</string>
<string name="widget.4x3">DSub (4x3)</string>
<string name="widget.4x4">DSub (4x4)</string>
- <string name="widget.initial_text">Toque para selecionar música</string>
+ <string name="widget.initial_text">Toque para selecionar a música</string>
<string name="widget.sdcard_busy">Cartão SD não disponível</string>
<string name="widget.sdcard_missing">Cartão SD em falta</string>
@@ -587,9 +606,9 @@
<string name="details.genre">Género</string>
<string name="details.year">Ano</string>
<string name="details.server_format">Formato no servidor</string>
- <string name="details.server_bitrate">Bitrate no servidor</string>
+ <string name="details.server_bitrate">Taxa de bits no servidor</string>
<string name="details.cached_format">Formato em cache</string>
- <string name="details.cached_bitrate">Bitrate em cache</string>
+ <string name="details.cached_bitrate">Taxa de bits em cache</string>
<string name="details.size">Tamanho</string>
<string name="details.length">Duração</string>
<string name="details.bookmark_position">Posição do marcador</string>
diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml
index 843c53da..6f617589 100644
--- a/app/src/main/res/xml/changelog.xml
+++ b/app/src/main/res/xml/changelog.xml
@@ -1,5 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
+ <release version="5.1.9" versioncode="181" releasedate="6/13/2016">
+ <change>Fix First level artists option</change>
+ <change>Fix some artist menu items missing</change>
+ </release>
+ <release version="5.1.8" versioncode="179" releasedate="6/9/2016">
+ <change>Improved Search Bar</change>
+ <change>Display songs in root folder</change>
+ <change>Heads Up Setting: Only when out of app</change>
+ <change>Speed up resuming app from notifications/widgets</change>
+ <change>Bluetooth: Double click play/pause button to skip to next some</change>
+ <change>Auto: Previous/Next rewind/fast forward on Podcasts/Audio Books</change>
+ <change>Fix playlist not overwriting when resumed from bookmark</change>
+ <change>Fix some bluetooth devices sending next/previous multiple times</change>
+ <change>Fix reverting to stock Subsonic after using Madsonic 6+ servers</change>
+ <change>Fix Podcast list cache not working with no internet</change>
+ </release>
<release version="5.1.7" versioncode="177" releasedate="4/22/2016">
<change>Audio Books/Podcasts: Replace back/forward with rewind/fast forward buttons</change>
<change>Expandable Search Results</change>