mirror of
https://gitea.mayex.net/mayekkuzu/Audinaut.git
synced 2025-02-03 03:13:46 +03:00
The great whitespace cleanup
This commit is contained in:
parent
75ad0a0239
commit
a72f978001
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.activity;
|
package net.nullsum.audinaut.activity;
|
||||||
@ -46,200 +46,200 @@ import net.nullsum.audinaut.util.LoadingTask;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class EditPlayActionActivity extends SubsonicActivity {
|
public class EditPlayActionActivity extends SubsonicActivity {
|
||||||
private CheckBox shuffleCheckbox;
|
private CheckBox shuffleCheckbox;
|
||||||
private CheckBox startYearCheckbox;
|
private CheckBox startYearCheckbox;
|
||||||
private EditText startYearBox;
|
private EditText startYearBox;
|
||||||
private CheckBox endYearCheckbox;
|
private CheckBox endYearCheckbox;
|
||||||
private EditText endYearBox;
|
private EditText endYearBox;
|
||||||
private Button genreButton;
|
private Button genreButton;
|
||||||
private Spinner offlineSpinner;
|
private Spinner offlineSpinner;
|
||||||
|
|
||||||
private String doNothing;
|
private String doNothing;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setTitle(R.string.tasker_start_playing_title);
|
setTitle(R.string.tasker_start_playing_title);
|
||||||
setContentView(R.layout.edit_play_action);
|
setContentView(R.layout.edit_play_action);
|
||||||
final Activity context = this;
|
final Activity context = this;
|
||||||
doNothing = context.getResources().getString(R.string.tasker_edit_do_nothing);
|
doNothing = context.getResources().getString(R.string.tasker_edit_do_nothing);
|
||||||
|
|
||||||
shuffleCheckbox = (CheckBox) findViewById(R.id.edit_shuffle_checkbox);
|
shuffleCheckbox = (CheckBox) findViewById(R.id.edit_shuffle_checkbox);
|
||||||
shuffleCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
shuffleCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
||||||
startYearCheckbox.setEnabled(isChecked);
|
startYearCheckbox.setEnabled(isChecked);
|
||||||
endYearCheckbox.setEnabled(isChecked);
|
endYearCheckbox.setEnabled(isChecked);
|
||||||
genreButton.setEnabled(isChecked);
|
genreButton.setEnabled(isChecked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
startYearCheckbox = (CheckBox) findViewById(R.id.edit_start_year_checkbox);
|
startYearCheckbox = (CheckBox) findViewById(R.id.edit_start_year_checkbox);
|
||||||
startYearBox = (EditText) findViewById(R.id.edit_start_year);
|
startYearBox = (EditText) findViewById(R.id.edit_start_year);
|
||||||
// Disable/enable number box if checked
|
// Disable/enable number box if checked
|
||||||
startYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
startYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
||||||
startYearBox.setEnabled(isChecked);
|
startYearBox.setEnabled(isChecked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
endYearCheckbox = (CheckBox) findViewById(R.id.edit_end_year_checkbox);
|
endYearCheckbox = (CheckBox) findViewById(R.id.edit_end_year_checkbox);
|
||||||
endYearBox = (EditText) findViewById(R.id.edit_end_year);
|
endYearBox = (EditText) findViewById(R.id.edit_end_year);
|
||||||
endYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
endYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
public void onCheckedChanged(CompoundButton view, boolean isChecked) {
|
||||||
endYearBox.setEnabled(isChecked);
|
endYearBox.setEnabled(isChecked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
genreButton = (Button) findViewById(R.id.edit_genre_spinner);
|
genreButton = (Button) findViewById(R.id.edit_genre_spinner);
|
||||||
genreButton.setOnClickListener(new View.OnClickListener() {
|
genreButton.setOnClickListener(new View.OnClickListener() {
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
new LoadingTask<List<Genre>>(context, true) {
|
new LoadingTask<List<Genre>>(context, true) {
|
||||||
@Override
|
@Override
|
||||||
protected List<Genre> doInBackground() throws Throwable {
|
protected List<Genre> doInBackground() throws Throwable {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
return musicService.getGenres(false, context, this);
|
return musicService.getGenres(false, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(final List<Genre> genres) {
|
protected void done(final List<Genre> genres) {
|
||||||
List<String> names = new ArrayList<String>();
|
List<String> names = new ArrayList<String>();
|
||||||
String blank = context.getResources().getString(R.string.select_genre_blank);
|
String blank = context.getResources().getString(R.string.select_genre_blank);
|
||||||
names.add(doNothing);
|
names.add(doNothing);
|
||||||
names.add(blank);
|
names.add(blank);
|
||||||
for(Genre genre: genres) {
|
for(Genre genre: genres) {
|
||||||
names.add(genre.getName());
|
names.add(genre.getName());
|
||||||
}
|
}
|
||||||
final List<String> finalNames = names;
|
final List<String> finalNames = names;
|
||||||
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
builder.setTitle(R.string.shuffle_pick_genre)
|
builder.setTitle(R.string.shuffle_pick_genre)
|
||||||
.setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
|
.setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
if(which == 1) {
|
if(which == 1) {
|
||||||
genreButton.setText("");
|
genreButton.setText("");
|
||||||
} else {
|
} else {
|
||||||
genreButton.setText(finalNames.get(which));
|
genreButton.setText(finalNames.get(which));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
AlertDialog dialog = builder.create();
|
AlertDialog dialog = builder.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
String msg;
|
String msg;
|
||||||
if (error instanceof OfflineException) {
|
if (error instanceof OfflineException) {
|
||||||
msg = getErrorMessage(error);
|
msg = getErrorMessage(error);
|
||||||
} else {
|
} else {
|
||||||
msg = context.getResources().getString(R.string.playlist_error) + " " + getErrorMessage(error);
|
msg = context.getResources().getString(R.string.playlist_error) + " " + getErrorMessage(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.toast(context, msg, false);
|
Util.toast(context, msg, false);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
genreButton.setText(doNothing);
|
genreButton.setText(doNothing);
|
||||||
|
|
||||||
offlineSpinner = (Spinner) findViewById(R.id.edit_offline_spinner);
|
offlineSpinner = (Spinner) findViewById(R.id.edit_offline_spinner);
|
||||||
ArrayAdapter<CharSequence> offlineAdapter = ArrayAdapter.createFromResource(this, R.array.editServerOptions, android.R.layout.simple_spinner_item);
|
ArrayAdapter<CharSequence> offlineAdapter = ArrayAdapter.createFromResource(this, R.array.editServerOptions, android.R.layout.simple_spinner_item);
|
||||||
offlineAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
offlineAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
offlineSpinner.setAdapter(offlineAdapter);
|
offlineSpinner.setAdapter(offlineAdapter);
|
||||||
|
|
||||||
// Setup default for everything
|
// Setup default for everything
|
||||||
Bundle extras = getIntent().getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
Bundle extras = getIntent().getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||||
if(extras != null) {
|
if(extras != null) {
|
||||||
if(extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) {
|
if(extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) {
|
||||||
shuffleCheckbox.setChecked(true);
|
shuffleCheckbox.setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
String startYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, null);
|
String startYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, null);
|
||||||
if(startYear != null) {
|
if(startYear != null) {
|
||||||
startYearCheckbox.setEnabled(true);
|
startYearCheckbox.setEnabled(true);
|
||||||
startYearBox.setText(startYear);
|
startYearBox.setText(startYear);
|
||||||
}
|
}
|
||||||
String endYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, null);
|
String endYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, null);
|
||||||
if(endYear != null) {
|
if(endYear != null) {
|
||||||
endYearCheckbox.setEnabled(true);
|
endYearCheckbox.setEnabled(true);
|
||||||
endYearBox.setText(endYear);
|
endYearBox.setText(endYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
String genre = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, doNothing);
|
String genre = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, doNothing);
|
||||||
if(genre != null) {
|
if(genre != null) {
|
||||||
genreButton.setText(genre);
|
genreButton.setText(genre);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offline = extras.getInt(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
int offline = extras.getInt(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
||||||
if(offline != 0) {
|
if(offline != 0) {
|
||||||
offlineSpinner.setSelection(offline);
|
offlineSpinner.setSelection(offline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
MenuInflater menuInflater = getMenuInflater();
|
MenuInflater menuInflater = getMenuInflater();
|
||||||
menuInflater.inflate(R.menu.tasker_configuration, menu);
|
menuInflater.inflate(R.menu.tasker_configuration, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(item.getItemId() == android.R.id.home) {
|
if(item.getItemId() == android.R.id.home) {
|
||||||
cancel();
|
cancel();
|
||||||
return true;
|
return true;
|
||||||
} else if(item.getItemId() == R.id.menu_accept) {
|
} else if(item.getItemId() == R.id.menu_accept) {
|
||||||
accept();
|
accept();
|
||||||
return true;
|
return true;
|
||||||
} else if(item.getItemId() == R.id.menu_cancel) {
|
} else if(item.getItemId() == R.id.menu_cancel) {
|
||||||
cancel();
|
cancel();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void accept() {
|
private void accept() {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
|
|
||||||
String blurb = getResources().getString(shuffleCheckbox.isChecked() ? R.string.tasker_start_playing_shuffled : R.string.tasker_start_playing);
|
String blurb = getResources().getString(shuffleCheckbox.isChecked() ? R.string.tasker_start_playing_shuffled : R.string.tasker_start_playing);
|
||||||
intent.putExtra("com.twofortyfouram.locale.intent.extra.BLURB", blurb);
|
intent.putExtra("com.twofortyfouram.locale.intent.extra.BLURB", blurb);
|
||||||
|
|
||||||
// Get settings user specified
|
// Get settings user specified
|
||||||
Bundle data = new Bundle();
|
Bundle data = new Bundle();
|
||||||
boolean shuffle = shuffleCheckbox.isChecked();
|
boolean shuffle = shuffleCheckbox.isChecked();
|
||||||
data.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, shuffle);
|
data.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, shuffle);
|
||||||
if(shuffle) {
|
if(shuffle) {
|
||||||
if(startYearCheckbox.isChecked()) {
|
if(startYearCheckbox.isChecked()) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYearBox.getText().toString());
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYearBox.getText().toString());
|
||||||
}
|
}
|
||||||
if(endYearCheckbox.isChecked()) {
|
if(endYearCheckbox.isChecked()) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYearBox.getText().toString());
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYearBox.getText().toString());
|
||||||
}
|
}
|
||||||
String genre = genreButton.getText().toString();
|
String genre = genreButton.getText().toString();
|
||||||
if(!genre.equals(doNothing)) {
|
if(!genre.equals(doNothing)) {
|
||||||
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
data.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int offline = offlineSpinner.getSelectedItemPosition();
|
int offline = offlineSpinner.getSelectedItemPosition();
|
||||||
if(offline != 0) {
|
if(offline != 0) {
|
||||||
data.putInt(Constants.PREFERENCES_KEY_OFFLINE, offline);
|
data.putInt(Constants.PREFERENCES_KEY_OFFLINE, offline);
|
||||||
}
|
}
|
||||||
|
|
||||||
intent.putExtra(Constants.TASKER_EXTRA_BUNDLE, data);
|
intent.putExtra(Constants.TASKER_EXTRA_BUNDLE, data);
|
||||||
|
|
||||||
setResult(Activity.RESULT_OK, intent);
|
setResult(Activity.RESULT_OK, intent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
private void cancel() {
|
private void cancel() {
|
||||||
setResult(Activity.RESULT_CANCELED);
|
setResult(Activity.RESULT_CANCELED);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,48 +38,48 @@ import net.nullsum.audinaut.provider.AudinautSearchProvider;
|
|||||||
*/
|
*/
|
||||||
public class QueryReceiverActivity extends Activity {
|
public class QueryReceiverActivity extends Activity {
|
||||||
|
|
||||||
private static final String TAG = QueryReceiverActivity.class.getSimpleName();
|
private static final String TAG = QueryReceiverActivity.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||||
doSearch();
|
doSearch();
|
||||||
} else if(Intent.ACTION_VIEW.equals(intent.getAction())) {
|
} else if(Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||||
showResult(intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
|
showResult(intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
Util.disablePendingTransition(this);
|
Util.disablePendingTransition(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSearch() {
|
private void doSearch() {
|
||||||
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
String query = getIntent().getStringExtra(SearchManager.QUERY);
|
||||||
if (query != null) {
|
if (query != null) {
|
||||||
Intent intent = new Intent(QueryReceiverActivity.this, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(QueryReceiverActivity.this, SubsonicFragmentActivity.class);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void showResult(String albumId, String name) {
|
private void showResult(String albumId, String name) {
|
||||||
if (albumId != null) {
|
if (albumId != null) {
|
||||||
Intent intent = new Intent(this, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(this, SubsonicFragmentActivity.class);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
|
||||||
if(albumId.indexOf("ar-") == 0) {
|
if(albumId.indexOf("ar-") == 0) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
albumId = albumId.replace("ar-", "");
|
albumId = albumId.replace("ar-", "");
|
||||||
} else if(albumId.indexOf("so-") == 0) {
|
} else if(albumId.indexOf("so-") == 0) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
|
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
|
||||||
albumId = albumId.replace("so-", "");
|
albumId = albumId.replace("so-", "");
|
||||||
}
|
}
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, albumId);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, albumId);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, name);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, name);
|
||||||
}
|
}
|
||||||
Util.startActivityWithoutTransition(this, intent);
|
Util.startActivityWithoutTransition(this, intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,29 +28,29 @@ import net.nullsum.audinaut.fragments.SettingsFragment;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public class SettingsActivity extends SubsonicActivity {
|
public class SettingsActivity extends SubsonicActivity {
|
||||||
private static final String TAG = SettingsActivity.class.getSimpleName();
|
private static final String TAG = SettingsActivity.class.getSimpleName();
|
||||||
private PreferenceCompatFragment fragment;
|
private PreferenceCompatFragment fragment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
lastSelectedPosition = R.id.drawer_settings;
|
lastSelectedPosition = R.id.drawer_settings;
|
||||||
setContentView(R.layout.settings_activity);
|
setContentView(R.layout.settings_activity);
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
fragment = new SettingsFragment();
|
fragment = new SettingsFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, R.xml.settings);
|
args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, R.xml.settings);
|
||||||
|
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
fragment.setRetainInstance(true);
|
fragment.setRetainInstance(true);
|
||||||
|
|
||||||
currentFragment = fragment;
|
currentFragment = fragment;
|
||||||
currentFragment.setPrimaryFragment(true);
|
currentFragment.setPrimaryFragment(true);
|
||||||
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
||||||
setSupportActionBar(mainToolbar);
|
setSupportActionBar(mainToolbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@ import net.nullsum.audinaut.provider.AudinautSearchProvider;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class VoiceQueryReceiverActivity extends Activity {
|
public class VoiceQueryReceiverActivity extends Activity {
|
||||||
private static final String TAG = VoiceQueryReceiverActivity.class.getSimpleName();
|
private static final String TAG = VoiceQueryReceiverActivity.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@ -53,7 +53,7 @@ public class VoiceQueryReceiverActivity extends Activity {
|
|||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_QUERY, query);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, getIntent().getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS));
|
intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS, getIntent().getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS));
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent);
|
||||||
}
|
}
|
||||||
finish();
|
finish();
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -24,21 +24,21 @@ import net.nullsum.audinaut.util.ImageLoader;
|
|||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
|
|
||||||
public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter {
|
public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter {
|
||||||
public AlphabeticalAlbumAdapter(Context context, List<MusicDirectory.Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
public AlphabeticalAlbumAdapter(Context context, List<MusicDirectory.Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
||||||
super(context, entries, imageLoader, largeCell);
|
super(context, entries, imageLoader, largeCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
// Make sure that we are not trying to get an item for the loading placeholder
|
// Make sure that we are not trying to get an item for the loading placeholder
|
||||||
if(position >= sections.get(0).size()) {
|
if(position >= sections.get(0).size()) {
|
||||||
if(sections.get(0).size() > 0) {
|
if(sections.get(0).size() > 0) {
|
||||||
return getTextToShowInBubble(position - 1);
|
return getTextToShowInBubble(position - 1);
|
||||||
} else {
|
} else {
|
||||||
return "*";
|
return "*";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return getNameIndex(getItemForPosition(position).getAlbum());
|
return getNameIndex(getItemForPosition(position).getAlbum());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -38,125 +38,125 @@ import net.nullsum.audinaut.view.SongView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class ArtistAdapter extends SectionAdapter<Serializable> implements FastScroller.BubbleTextGetter {
|
public class ArtistAdapter extends SectionAdapter<Serializable> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_SONG = 3;
|
public static int VIEW_TYPE_SONG = 3;
|
||||||
public static int VIEW_TYPE_ARTIST = 4;
|
public static int VIEW_TYPE_ARTIST = 4;
|
||||||
|
|
||||||
private List<MusicFolder> musicFolders;
|
private List<MusicFolder> musicFolders;
|
||||||
private OnMusicFolderChanged onMusicFolderChanged;
|
private OnMusicFolderChanged onMusicFolderChanged;
|
||||||
|
|
||||||
public ArtistAdapter(Context context, List<Serializable> artists, OnItemClickedListener listener) {
|
public ArtistAdapter(Context context, List<Serializable> artists, OnItemClickedListener listener) {
|
||||||
this(context, artists, null, listener, null);
|
this(context, artists, null, listener, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtistAdapter(Context context, List<Serializable> 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);
|
super(context, artists);
|
||||||
this.musicFolders = musicFolders;
|
this.musicFolders = musicFolders;
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
this.onMusicFolderChanged = onMusicFolderChanged;
|
this.onMusicFolderChanged = onMusicFolderChanged;
|
||||||
|
|
||||||
if(musicFolders != null) {
|
if(musicFolders != null) {
|
||||||
this.singleSectionHeader = true;
|
this.singleSectionHeader = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false);
|
final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false);
|
||||||
header.setOnClickListener(new View.OnClickListener() {
|
header.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2));
|
PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2));
|
||||||
|
|
||||||
popup.getMenu().add(R.string.select_artist_all_folders);
|
popup.getMenu().add(R.string.select_artist_all_folders);
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
popup.getMenu().add(musicFolder.getName());
|
popup.getMenu().add(musicFolder.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
if(item.getTitle().equals(musicFolder.getName())) {
|
if(item.getTitle().equals(musicFolder.getName())) {
|
||||||
if(onMusicFolderChanged != null) {
|
if(onMusicFolderChanged != null) {
|
||||||
onMusicFolderChanged.onMusicFolderChanged(musicFolder);
|
onMusicFolderChanged.onMusicFolderChanged(musicFolder);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(onMusicFolderChanged != null) {
|
if(onMusicFolderChanged != null) {
|
||||||
onMusicFolderChanged.onMusicFolderChanged(null);
|
onMusicFolderChanged.onMusicFolderChanged(null);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
popup.show();
|
popup.show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return new UpdateView.UpdateViewHolder(header, false);
|
return new UpdateView.UpdateViewHolder(header, false);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
TextView folderName = (TextView) holder.getView().findViewById(R.id.select_artist_folder_2);
|
TextView folderName = (TextView) holder.getView().findViewById(R.id.select_artist_folder_2);
|
||||||
|
|
||||||
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
if(musicFolderId != null) {
|
if(musicFolderId != null) {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
if (musicFolder.getId().equals(musicFolderId)) {
|
if (musicFolder.getId().equals(musicFolderId)) {
|
||||||
folderName.setText(musicFolder.getName());
|
folderName.setText(musicFolder.getName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
folderName.setText(R.string.select_artist_all_folders);
|
folderName.setText(R.string.select_artist_all_folders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ARTIST) {
|
if(viewType == VIEW_TYPE_ARTIST) {
|
||||||
updateView = new ArtistView(context);
|
updateView = new ArtistView(context);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UpdateView.UpdateViewHolder(updateView);
|
return new UpdateView.UpdateViewHolder(updateView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ARTIST) {
|
if(viewType == VIEW_TYPE_ARTIST) {
|
||||||
view.setObject(item);
|
view.setObject(item);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
Entry entry = (Entry) item;
|
Entry entry = (Entry) item;
|
||||||
songView.setObject(entry, checkable);
|
songView.setObject(entry, checkable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Serializable item) {
|
public int getItemViewType(Serializable item) {
|
||||||
if(item instanceof Artist) {
|
if(item instanceof Artist) {
|
||||||
return VIEW_TYPE_ARTIST;
|
return VIEW_TYPE_ARTIST;
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_SONG;
|
return VIEW_TYPE_SONG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
Object item = getItemForPosition(position);
|
Object item = getItemForPosition(position);
|
||||||
if(item instanceof Artist) {
|
if(item instanceof Artist) {
|
||||||
return getNameIndex(((Artist) item).getName(), true);
|
return getNameIndex(((Artist) item).getName(), true);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnMusicFolderChanged {
|
public interface OnMusicFolderChanged {
|
||||||
void onMusicFolderChanged(MusicFolder musicFolder);
|
void onMusicFolderChanged(MusicFolder musicFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -24,25 +24,25 @@ import net.nullsum.audinaut.view.BasicListView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class BasicListAdapter extends SectionAdapter<String> {
|
public class BasicListAdapter extends SectionAdapter<String> {
|
||||||
public static int VIEW_TYPE_LINE = 1;
|
public static int VIEW_TYPE_LINE = 1;
|
||||||
|
|
||||||
public BasicListAdapter(Context context, List<String> strings, OnItemClickedListener listener) {
|
public BasicListAdapter(Context context, List<String> strings, OnItemClickedListener listener) {
|
||||||
super(context, strings);
|
super(context, strings);
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicListView(context));
|
return new UpdateView.UpdateViewHolder(new BasicListView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, String item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, String item, int viewType) {
|
||||||
holder.getUpdateView().setObject(item);
|
holder.getUpdateView().setObject(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(String item) {
|
public int getItemViewType(String item) {
|
||||||
return VIEW_TYPE_LINE;
|
return VIEW_TYPE_LINE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -30,33 +30,33 @@ import java.util.List;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class DetailsAdapter extends ArrayAdapter<String> {
|
public class DetailsAdapter extends ArrayAdapter<String> {
|
||||||
private List<String> headers;
|
private List<String> headers;
|
||||||
private List<String> details;
|
private List<String> details;
|
||||||
|
|
||||||
public DetailsAdapter(Context context, int layout, List<String> headers, List<String> details) {
|
public DetailsAdapter(Context context, int layout, List<String> headers, List<String> details) {
|
||||||
super(context, layout, headers);
|
super(context, layout, headers);
|
||||||
|
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.details = details;
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent){
|
public View getView(int position, View convertView, ViewGroup parent){
|
||||||
View view;
|
View view;
|
||||||
if(convertView == null) {
|
if(convertView == null) {
|
||||||
view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null);
|
view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null);
|
||||||
} else {
|
} else {
|
||||||
view = convertView;
|
view = convertView;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView nameView = (TextView) view.findViewById(R.id.detail_name);
|
TextView nameView = (TextView) view.findViewById(R.id.detail_name);
|
||||||
TextView detailsView = (TextView) view.findViewById(R.id.detail_value);
|
TextView detailsView = (TextView) view.findViewById(R.id.detail_value);
|
||||||
|
|
||||||
nameView.setText(headers.get(position));
|
nameView.setText(headers.get(position));
|
||||||
|
|
||||||
detailsView.setText(details.get(position));
|
detailsView.setText(details.get(position));
|
||||||
Linkify.addLinks(detailsView, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES);
|
Linkify.addLinks(detailsView, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -33,42 +33,42 @@ import net.nullsum.audinaut.view.SongView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements FastScroller.BubbleTextGetter {
|
public class DownloadFileAdapter extends SectionAdapter<DownloadFile> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_DOWNLOAD_FILE = 1;
|
public static int VIEW_TYPE_DOWNLOAD_FILE = 1;
|
||||||
|
|
||||||
public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
|
public DownloadFileAdapter(Context context, List<DownloadFile> entries, OnItemClickedListener onItemClickedListener) {
|
||||||
super(context, entries);
|
super(context, entries);
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
this.checkable = true;
|
this.checkable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new SongView(context));
|
return new UpdateView.UpdateViewHolder(new SongView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, DownloadFile item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, DownloadFile item, int viewType) {
|
||||||
SongView songView = (SongView) holder.getUpdateView();
|
SongView songView = (SongView) holder.getUpdateView();
|
||||||
songView.setObject(item.getSong(), Util.isBatchMode(context));
|
songView.setObject(item.getSong(), Util.isBatchMode(context));
|
||||||
songView.setDownloadFile(item);
|
songView.setDownloadFile(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(DownloadFile item) {
|
public int getItemViewType(DownloadFile item) {
|
||||||
return VIEW_TYPE_DOWNLOAD_FILE;
|
return VIEW_TYPE_DOWNLOAD_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if(Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_nowplaying, menu);
|
menuInflater.inflate(R.menu.multiselect_nowplaying, menu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -35,122 +35,122 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
||||||
|
|
||||||
public class EntryGridAdapter extends SectionAdapter<Entry> {
|
public class EntryGridAdapter extends SectionAdapter<Entry> {
|
||||||
private static String TAG = EntryGridAdapter.class.getSimpleName();
|
private static String TAG = EntryGridAdapter.class.getSimpleName();
|
||||||
|
|
||||||
public static int VIEW_TYPE_ALBUM_CELL = 1;
|
public static int VIEW_TYPE_ALBUM_CELL = 1;
|
||||||
public static int VIEW_TYPE_ALBUM_LINE = 2;
|
public static int VIEW_TYPE_ALBUM_LINE = 2;
|
||||||
public static int VIEW_TYPE_SONG = 3;
|
public static int VIEW_TYPE_SONG = 3;
|
||||||
|
|
||||||
private ImageLoader imageLoader;
|
private ImageLoader imageLoader;
|
||||||
private boolean largeAlbums;
|
private boolean largeAlbums;
|
||||||
private boolean showArtist = false;
|
private boolean showArtist = false;
|
||||||
private boolean showAlbum = false;
|
private boolean showAlbum = false;
|
||||||
private boolean removeFromPlaylist = false;
|
private boolean removeFromPlaylist = false;
|
||||||
private View header;
|
private View header;
|
||||||
|
|
||||||
public EntryGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
public EntryGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
||||||
super(context, entries);
|
super(context, entries);
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
this.largeAlbums = largeCell;
|
this.largeAlbums = largeCell;
|
||||||
|
|
||||||
// Always show artist if they aren't all the same
|
// Always show artist if they aren't all the same
|
||||||
String artist = null;
|
String artist = null;
|
||||||
for(MusicDirectory.Entry entry: entries) {
|
for(MusicDirectory.Entry entry: entries) {
|
||||||
if(artist == null) {
|
if(artist == null) {
|
||||||
artist = entry.getArtist();
|
artist = entry.getArtist();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(artist != null && !artist.equals(entry.getArtist())) {
|
if(artist != null && !artist.equals(entry.getArtist())) {
|
||||||
showArtist = true;
|
showArtist = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkable = true;
|
checkable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) {
|
if(viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) {
|
||||||
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UpdateViewHolder(updateView);
|
return new UpdateViewHolder(updateView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) {
|
public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
AlbumView albumView = (AlbumView) view;
|
AlbumView albumView = (AlbumView) view;
|
||||||
albumView.setShowArtist(showArtist);
|
albumView.setShowArtist(showArtist);
|
||||||
albumView.setObject(entry, imageLoader);
|
albumView.setObject(entry, imageLoader);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
songView.setShowAlbum(showAlbum);
|
songView.setShowAlbum(showAlbum);
|
||||||
songView.setObject(entry, checkable);
|
songView.setObject(entry, checkable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateViewHolder(header, false);
|
return new UpdateViewHolder(header, false);
|
||||||
}
|
}
|
||||||
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Entry entry) {
|
public int getItemViewType(Entry entry) {
|
||||||
if(entry.isDirectory()) {
|
if(entry.isDirectory()) {
|
||||||
if (largeAlbums) {
|
if (largeAlbums) {
|
||||||
return VIEW_TYPE_ALBUM_CELL;
|
return VIEW_TYPE_ALBUM_CELL;
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_ALBUM_LINE;
|
return VIEW_TYPE_ALBUM_LINE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_SONG;
|
return VIEW_TYPE_SONG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeader(View header) {
|
public void setHeader(View header) {
|
||||||
this.header = header;
|
this.header = header;
|
||||||
this.singleSectionHeader = true;
|
this.singleSectionHeader = true;
|
||||||
}
|
}
|
||||||
public View getHeader() {
|
public View getHeader() {
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowArtist(boolean showArtist) {
|
public void setShowArtist(boolean showArtist) {
|
||||||
this.showArtist = showArtist;
|
this.showArtist = showArtist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowAlbum(boolean showAlbum) {
|
public void setShowAlbum(boolean showAlbum) {
|
||||||
this.showAlbum = showAlbum;
|
this.showAlbum = showAlbum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAt(int index) {
|
public void removeAt(int index) {
|
||||||
sections.get(0).remove(index);
|
sections.get(0).remove(index);
|
||||||
if(header != null) {
|
if(header != null) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
notifyItemRemoved(index);
|
notifyItemRemoved(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRemoveFromPlaylist(boolean removeFromPlaylist) {
|
public void setRemoveFromPlaylist(boolean removeFromPlaylist) {
|
||||||
this.removeFromPlaylist = removeFromPlaylist;
|
this.removeFromPlaylist = removeFromPlaylist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if(Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_media, menu);
|
menuInflater.inflate(R.menu.multiselect_media, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!removeFromPlaylist) {
|
if(!removeFromPlaylist) {
|
||||||
menu.removeItem(R.id.menu_remove_playlist);
|
menu.removeItem(R.id.menu_remove_playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -33,120 +33,120 @@ import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
public class EntryInfiniteGridAdapter extends EntryGridAdapter {
|
||||||
public static int VIEW_TYPE_LOADING = 4;
|
public static int VIEW_TYPE_LOADING = 4;
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
private String extra;
|
private String extra;
|
||||||
private int size;
|
private int size;
|
||||||
|
|
||||||
private boolean loading = false;
|
private boolean loading = false;
|
||||||
private boolean allLoaded = false;
|
private boolean allLoaded = false;
|
||||||
|
|
||||||
public EntryInfiniteGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
public EntryInfiniteGridAdapter(Context context, List<Entry> entries, ImageLoader imageLoader, boolean largeCell) {
|
||||||
super(context, entries, imageLoader, largeCell);
|
super(context, entries, imageLoader, largeCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if(viewType == VIEW_TYPE_LOADING) {
|
if(viewType == VIEW_TYPE_LOADING) {
|
||||||
View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null);
|
View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null);
|
||||||
progress.setVisibility(View.VISIBLE);
|
progress.setVisibility(View.VISIBLE);
|
||||||
return new UpdateView.UpdateViewHolder(progress, false);
|
return new UpdateView.UpdateViewHolder(progress, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onCreateViewHolder(parent, viewType);
|
return super.onCreateViewHolder(parent, viewType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if(isLoadingView(position)) {
|
if(isLoadingView(position)) {
|
||||||
return VIEW_TYPE_LOADING;
|
return VIEW_TYPE_LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.getItemViewType(position);
|
return super.getItemViewType(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) {
|
||||||
if(!isLoadingView(position)) {
|
if(!isLoadingView(position)) {
|
||||||
super.onBindViewHolder(holder, position);
|
super.onBindViewHolder(holder, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
int size = super.getItemCount();
|
int size = super.getItemCount();
|
||||||
|
|
||||||
if(!allLoaded) {
|
if(!allLoaded) {
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(String type, String extra, int size) {
|
public void setData(String type, String extra, int size) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.extra = extra;
|
this.extra = extra;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|
||||||
if(super.getItemCount() < size) {
|
if(super.getItemCount() < size) {
|
||||||
allLoaded = true;
|
allLoaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMore() {
|
public void loadMore() {
|
||||||
if(loading || allLoaded) {
|
if(loading || allLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
private List<Entry> newData;
|
private List<Entry> newData;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
newData = cacheInBackground();
|
newData = cacheInBackground();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
appendCachedData(newData);
|
appendCachedData(newData);
|
||||||
loading = false;
|
loading = false;
|
||||||
|
|
||||||
if(newData.size() < size) {
|
if(newData.size() < size) {
|
||||||
allLoaded = true;
|
allLoaded = true;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Entry> cacheInBackground() throws Exception {
|
protected List<Entry> cacheInBackground() throws Exception {
|
||||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||||
MusicDirectory result;
|
MusicDirectory result;
|
||||||
int offset = sections.get(0).size();
|
int offset = sections.get(0).size();
|
||||||
if("genres".equals(type) || "years".equals(type)) {
|
if("genres".equals(type) || "years".equals(type)) {
|
||||||
result = service.getAlbumList(type, extra, size, offset, false, context, null);
|
result = service.getAlbumList(type, extra, size, offset, false, context, null);
|
||||||
} else if("genres".equals(type) || "genres-songs".equals(type)) {
|
} else if("genres".equals(type) || "genres-songs".equals(type)) {
|
||||||
result = service.getSongsByGenre(extra, size, offset, context, null);
|
result = service.getSongsByGenre(extra, size, offset, context, null);
|
||||||
}else if(type.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
|
}else if(type.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) {
|
||||||
result = service.getSongList(type, size, offset, context, null);
|
result = service.getSongList(type, size, offset, context, null);
|
||||||
} else {
|
} else {
|
||||||
result = service.getAlbumList(type, size, offset, false, context, null);
|
result = service.getAlbumList(type, size, offset, false, context, null);
|
||||||
}
|
}
|
||||||
return result.getChildren();
|
return result.getChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void appendCachedData(List<Entry> newData) {
|
protected void appendCachedData(List<Entry> newData) {
|
||||||
if(newData.size() > 0) {
|
if(newData.size() > 0) {
|
||||||
int start = sections.get(0).size();
|
int start = sections.get(0).size();
|
||||||
sections.get(0).addAll(newData);
|
sections.get(0).addAll(newData);
|
||||||
this.notifyItemRangeInserted(start, newData.size());
|
this.notifyItemRangeInserted(start, newData.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isLoadingView(int position) {
|
protected boolean isLoadingView(int position) {
|
||||||
return !allLoaded && position >= sections.get(0).size();
|
return !allLoaded && position >= sections.get(0).size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -31,120 +31,120 @@ import net.nullsum.audinaut.view.BasicHeaderView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
public abstract class ExpandableSectionAdapter<T> extends SectionAdapter<T> {
|
||||||
private static final String TAG = ExpandableSectionAdapter.class.getSimpleName();
|
private static final String TAG = ExpandableSectionAdapter.class.getSimpleName();
|
||||||
private static final int DEFAULT_VISIBLE = 4;
|
private static final int DEFAULT_VISIBLE = 4;
|
||||||
private static final int EXPAND_TOGGLE = R.attr.select_server;
|
private static final int EXPAND_TOGGLE = R.attr.select_server;
|
||||||
private static final int COLLAPSE_TOGGLE = R.attr.select_tabs;
|
private static final int COLLAPSE_TOGGLE = R.attr.select_tabs;
|
||||||
|
|
||||||
protected List<Integer> sectionsDefaultVisible;
|
protected List<Integer> sectionsDefaultVisible;
|
||||||
protected List<List<T>> sectionsExtras;
|
protected List<List<T>> sectionsExtras;
|
||||||
protected int expandToggleRes;
|
protected int expandToggleRes;
|
||||||
protected int collapseToggleRes;
|
protected int collapseToggleRes;
|
||||||
|
|
||||||
protected ExpandableSectionAdapter() {}
|
protected ExpandableSectionAdapter() {}
|
||||||
public ExpandableSectionAdapter(Context context, List<T> section) {
|
public ExpandableSectionAdapter(Context context, List<T> section) {
|
||||||
List<List<T>> sections = new ArrayList<>();
|
List<List<T>> sections = new ArrayList<>();
|
||||||
sections.add(section);
|
sections.add(section);
|
||||||
|
|
||||||
init(context, Arrays.asList("Section"), sections, Arrays.asList((Integer) null));
|
init(context, Arrays.asList("Section"), sections, Arrays.asList((Integer) null));
|
||||||
}
|
}
|
||||||
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
||||||
init(context, headers, sections, null);
|
init(context, headers, sections, null);
|
||||||
}
|
}
|
||||||
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections, List<Integer> sectionsDefaultVisible) {
|
public ExpandableSectionAdapter(Context context, List<String> headers, List<List<T>> sections, List<Integer> sectionsDefaultVisible) {
|
||||||
init(context, headers, sections, sectionsDefaultVisible);
|
init(context, headers, sections, sectionsDefaultVisible);
|
||||||
}
|
}
|
||||||
protected void init(Context context, List<String> headers, List<List<T>> fullSections, List<Integer> sectionsDefaultVisible) {
|
protected void init(Context context, List<String> headers, List<List<T>> fullSections, List<Integer> sectionsDefaultVisible) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.sectionsDefaultVisible = sectionsDefaultVisible;
|
this.sectionsDefaultVisible = sectionsDefaultVisible;
|
||||||
if(sectionsDefaultVisible == null) {
|
if(sectionsDefaultVisible == null) {
|
||||||
sectionsDefaultVisible = new ArrayList<>(fullSections.size());
|
sectionsDefaultVisible = new ArrayList<>(fullSections.size());
|
||||||
for(int i = 0; i < fullSections.size(); i++) {
|
for(int i = 0; i < fullSections.size(); i++) {
|
||||||
sectionsDefaultVisible.add(DEFAULT_VISIBLE);
|
sectionsDefaultVisible.add(DEFAULT_VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sections = new ArrayList<>();
|
this.sections = new ArrayList<>();
|
||||||
this.sectionsExtras = new ArrayList<>();
|
this.sectionsExtras = new ArrayList<>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(List<T> fullSection: fullSections) {
|
for(List<T> fullSection: fullSections) {
|
||||||
List<T> visibleSection = new ArrayList<>();
|
List<T> visibleSection = new ArrayList<>();
|
||||||
|
|
||||||
Integer defaultVisible = sectionsDefaultVisible.get(i);
|
Integer defaultVisible = sectionsDefaultVisible.get(i);
|
||||||
if(defaultVisible == null || defaultVisible >= fullSection.size()) {
|
if(defaultVisible == null || defaultVisible >= fullSection.size()) {
|
||||||
visibleSection.addAll(fullSection);
|
visibleSection.addAll(fullSection);
|
||||||
this.sectionsExtras.add(null);
|
this.sectionsExtras.add(null);
|
||||||
} else {
|
} else {
|
||||||
visibleSection.addAll(fullSection.subList(0, defaultVisible));
|
visibleSection.addAll(fullSection.subList(0, defaultVisible));
|
||||||
this.sectionsExtras.add(fullSection.subList(defaultVisible, fullSection.size()));
|
this.sectionsExtras.add(fullSection.subList(defaultVisible, fullSection.size()));
|
||||||
}
|
}
|
||||||
this.sections.add(visibleSection);
|
this.sections.add(visibleSection);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
expandToggleRes = DrawableTint.getDrawableRes(context, EXPAND_TOGGLE);
|
expandToggleRes = DrawableTint.getDrawableRes(context, EXPAND_TOGGLE);
|
||||||
collapseToggleRes = DrawableTint.getDrawableRes(context, COLLAPSE_TOGGLE);
|
collapseToggleRes = DrawableTint.getDrawableRes(context, COLLAPSE_TOGGLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.expandable_header));
|
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.expandable_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, final int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, final int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
ImageView toggleSelectionView = (ImageView) view.findViewById(R.id.item_select);
|
ImageView toggleSelectionView = (ImageView) view.findViewById(R.id.item_select);
|
||||||
|
|
||||||
List<T> visibleSelection = sections.get(sectionIndex);
|
List<T> visibleSelection = sections.get(sectionIndex);
|
||||||
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
||||||
|
|
||||||
if(sectionExtras != null && !sectionExtras.isEmpty()) {
|
if(sectionExtras != null && !sectionExtras.isEmpty()) {
|
||||||
toggleSelectionView.setVisibility(View.VISIBLE);
|
toggleSelectionView.setVisibility(View.VISIBLE);
|
||||||
toggleSelectionView.setOnClickListener(new View.OnClickListener() {
|
toggleSelectionView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
List<T> visibleSelection = sections.get(sectionIndex);
|
List<T> visibleSelection = sections.get(sectionIndex);
|
||||||
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
List<T> sectionExtras = sectionsExtras.get(sectionIndex);
|
||||||
|
|
||||||
// Update icon
|
// Update icon
|
||||||
int selectToggleAttr;
|
int selectToggleAttr;
|
||||||
if (!visibleSelection.contains(sectionExtras.get(0))) {
|
if (!visibleSelection.contains(sectionExtras.get(0))) {
|
||||||
selectToggleAttr = COLLAPSE_TOGGLE;
|
selectToggleAttr = COLLAPSE_TOGGLE;
|
||||||
|
|
||||||
// Update how many are displayed
|
// Update how many are displayed
|
||||||
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
||||||
visibleSelection.addAll(sectionExtras);
|
visibleSelection.addAll(sectionExtras);
|
||||||
notifyItemRangeInserted(lastIndex, sectionExtras.size());
|
notifyItemRangeInserted(lastIndex, sectionExtras.size());
|
||||||
} else {
|
} else {
|
||||||
selectToggleAttr = EXPAND_TOGGLE;
|
selectToggleAttr = EXPAND_TOGGLE;
|
||||||
|
|
||||||
// Update how many are displayed
|
// Update how many are displayed
|
||||||
visibleSelection.removeAll(sectionExtras);
|
visibleSelection.removeAll(sectionExtras);
|
||||||
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1));
|
||||||
notifyItemRangeRemoved(lastIndex, sectionExtras.size());
|
notifyItemRangeRemoved(lastIndex, sectionExtras.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
int selectToggleAttr;
|
int selectToggleAttr;
|
||||||
if (!visibleSelection.contains(sectionExtras.get(0))) {
|
if (!visibleSelection.contains(sectionExtras.get(0))) {
|
||||||
selectToggleAttr = EXPAND_TOGGLE;
|
selectToggleAttr = EXPAND_TOGGLE;
|
||||||
} else {
|
} else {
|
||||||
selectToggleAttr = COLLAPSE_TOGGLE;
|
selectToggleAttr = COLLAPSE_TOGGLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleSelectionView.setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
toggleSelectionView.setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr));
|
||||||
} else {
|
} else {
|
||||||
toggleSelectionView.setVisibility(View.GONE);
|
toggleSelectionView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(view != null) {
|
if(view != null) {
|
||||||
view.setObject(header);
|
view.setObject(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -25,30 +25,30 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GenreAdapter extends SectionAdapter<Genre> implements FastScroller.BubbleTextGetter{
|
public class GenreAdapter extends SectionAdapter<Genre> implements FastScroller.BubbleTextGetter{
|
||||||
public static int VIEW_TYPE_GENRE = 1;
|
public static int VIEW_TYPE_GENRE = 1;
|
||||||
|
|
||||||
public GenreAdapter(Context context, List<Genre> genres, OnItemClickedListener listener) {
|
public GenreAdapter(Context context, List<Genre> genres, OnItemClickedListener listener) {
|
||||||
super(context, genres);
|
super(context, genres);
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new GenreView(context));
|
return new UpdateView.UpdateViewHolder(new GenreView(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Genre item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Genre item, int viewType) {
|
||||||
holder.getUpdateView().setObject(item);
|
holder.getUpdateView().setObject(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Genre item) {
|
public int getItemViewType(Genre item) {
|
||||||
return VIEW_TYPE_GENRE;
|
return VIEW_TYPE_GENRE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
return getNameIndex(getItemForPosition(position).getName());
|
return getNameIndex(getItemForPosition(position).getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -30,55 +30,55 @@ import net.nullsum.audinaut.view.BasicListView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class MainAdapter extends SectionAdapter<Integer> {
|
public class MainAdapter extends SectionAdapter<Integer> {
|
||||||
public static final int VIEW_TYPE_ALBUM_LIST = 1;
|
public static final int VIEW_TYPE_ALBUM_LIST = 1;
|
||||||
|
|
||||||
public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) {
|
public MainAdapter(Context context, List<String> headers, List<List<Integer>> sections, OnItemClickedListener onItemClickedListener) {
|
||||||
super(context, headers, sections);
|
super(context, headers, sections);
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
UpdateView updateView = new BasicListView(context);
|
UpdateView updateView = new BasicListView(context);
|
||||||
return new UpdateView.UpdateViewHolder(updateView);
|
return new UpdateView.UpdateViewHolder(updateView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) {
|
||||||
UpdateView updateView = holder.getUpdateView();
|
UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(viewType == VIEW_TYPE_ALBUM_LIST) {
|
if(viewType == VIEW_TYPE_ALBUM_LIST) {
|
||||||
updateView.setObject(context.getResources().getString(item));
|
updateView.setObject(context.getResources().getString(item));
|
||||||
} else {
|
} else {
|
||||||
updateView.setObject(item);
|
updateView.setObject(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Integer item) {
|
public int getItemViewType(Integer item) {
|
||||||
return VIEW_TYPE_ALBUM_LIST;
|
return VIEW_TYPE_ALBUM_LIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header));
|
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox);
|
CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox);
|
||||||
|
|
||||||
String display;
|
String display;
|
||||||
if("songs".equals(header)) {
|
if("songs".equals(header)) {
|
||||||
display = context.getResources().getString(R.string.search_songs);
|
display = context.getResources().getString(R.string.search_songs);
|
||||||
checkBox.setVisibility(View.GONE);
|
checkBox.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
display = header;
|
display = header;
|
||||||
checkBox.setVisibility(View.GONE);
|
checkBox.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(view != null) {
|
if(view != null) {
|
||||||
view.setObject(display);
|
view.setObject(display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
|
|
||||||
@ -26,47 +26,47 @@ import net.nullsum.audinaut.view.PlaylistView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScroller.BubbleTextGetter {
|
public class PlaylistAdapter extends SectionAdapter<Playlist> implements FastScroller.BubbleTextGetter {
|
||||||
public static int VIEW_TYPE_PLAYLIST = 1;
|
public static int VIEW_TYPE_PLAYLIST = 1;
|
||||||
|
|
||||||
private ImageLoader imageLoader;
|
private ImageLoader imageLoader;
|
||||||
private boolean largeCell;
|
private boolean largeCell;
|
||||||
|
|
||||||
public PlaylistAdapter(Context context, List<Playlist> playlists, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
public PlaylistAdapter(Context context, List<Playlist> playlists, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
||||||
super(context, playlists);
|
super(context, playlists);
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
this.largeCell = largeCell;
|
this.largeCell = largeCell;
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
}
|
}
|
||||||
public PlaylistAdapter(Context context, List<String> headers, List<List<Playlist>> sections, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
public PlaylistAdapter(Context context, List<String> headers, List<List<Playlist>> sections, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) {
|
||||||
super(context, headers, sections);
|
super(context, headers, sections);
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
this.largeCell = largeCell;
|
this.largeCell = largeCell;
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
return new UpdateView.UpdateViewHolder(new PlaylistView(context, imageLoader, largeCell));
|
return new UpdateView.UpdateViewHolder(new PlaylistView(context, imageLoader, largeCell));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Playlist playlist, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Playlist playlist, int viewType) {
|
||||||
holder.getUpdateView().setObject(playlist);
|
holder.getUpdateView().setObject(playlist);
|
||||||
holder.setItem(playlist);
|
holder.setItem(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Playlist playlist) {
|
public int getItemViewType(Playlist playlist) {
|
||||||
return VIEW_TYPE_PLAYLIST;
|
return VIEW_TYPE_PLAYLIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTextToShowInBubble(int position) {
|
public String getTextToShowInBubble(int position) {
|
||||||
Object item = getItemForPosition(position);
|
Object item = getItemForPosition(position);
|
||||||
if(item instanceof Playlist) {
|
if(item instanceof Playlist) {
|
||||||
return getNameIndex(((Playlist) item).getName());
|
return getNameIndex(((Playlist) item).getName());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -45,96 +45,96 @@ import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_LINE
|
|||||||
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_SONG;
|
import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_SONG;
|
||||||
|
|
||||||
public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
public class SearchAdapter extends ExpandableSectionAdapter<Serializable> {
|
||||||
private ImageLoader imageLoader;
|
private ImageLoader imageLoader;
|
||||||
private boolean largeAlbums;
|
private boolean largeAlbums;
|
||||||
|
|
||||||
private static final int MAX_ARTISTS = 10;
|
private static final int MAX_ARTISTS = 10;
|
||||||
private static final int MAX_ALBUMS = 4;
|
private static final int MAX_ALBUMS = 4;
|
||||||
private static final int MAX_SONGS = 10;
|
private static final int MAX_SONGS = 10;
|
||||||
|
|
||||||
public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) {
|
public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) {
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
this.largeAlbums = largeAlbums;
|
this.largeAlbums = largeAlbums;
|
||||||
|
|
||||||
List<List<Serializable>> sections = new ArrayList<>();
|
List<List<Serializable>> sections = new ArrayList<>();
|
||||||
List<String> headers = new ArrayList<>();
|
List<String> headers = new ArrayList<>();
|
||||||
List<Integer> defaultVisible = new ArrayList<>();
|
List<Integer> defaultVisible = new ArrayList<>();
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
if(!searchResult.getArtists().isEmpty()) {
|
if(!searchResult.getArtists().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getArtists());
|
sections.add((List<Serializable>) (List<?>) searchResult.getArtists());
|
||||||
headers.add(res.getString(R.string.search_artists));
|
headers.add(res.getString(R.string.search_artists));
|
||||||
defaultVisible.add(MAX_ARTISTS);
|
defaultVisible.add(MAX_ARTISTS);
|
||||||
}
|
}
|
||||||
if(!searchResult.getAlbums().isEmpty()) {
|
if(!searchResult.getAlbums().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getAlbums());
|
sections.add((List<Serializable>) (List<?>) searchResult.getAlbums());
|
||||||
headers.add(res.getString(R.string.search_albums));
|
headers.add(res.getString(R.string.search_albums));
|
||||||
defaultVisible.add(MAX_ALBUMS);
|
defaultVisible.add(MAX_ALBUMS);
|
||||||
}
|
}
|
||||||
if(!searchResult.getSongs().isEmpty()) {
|
if(!searchResult.getSongs().isEmpty()) {
|
||||||
sections.add((List<Serializable>) (List<?>) searchResult.getSongs());
|
sections.add((List<Serializable>) (List<?>) searchResult.getSongs());
|
||||||
headers.add(res.getString(R.string.search_songs));
|
headers.add(res.getString(R.string.search_songs));
|
||||||
defaultVisible.add(MAX_SONGS);
|
defaultVisible.add(MAX_SONGS);
|
||||||
}
|
}
|
||||||
init(context, headers, sections, defaultVisible);
|
init(context, headers, sections, defaultVisible);
|
||||||
|
|
||||||
this.onItemClickedListener = listener;
|
this.onItemClickedListener = listener;
|
||||||
checkable = true;
|
checkable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
UpdateView updateView = null;
|
UpdateView updateView = null;
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
updateView = new SongView(context);
|
updateView = new SongView(context);
|
||||||
} else if(viewType == VIEW_TYPE_ARTIST) {
|
} else if(viewType == VIEW_TYPE_ARTIST) {
|
||||||
updateView = new ArtistView(context);
|
updateView = new ArtistView(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UpdateView.UpdateViewHolder(updateView);
|
return new UpdateView.UpdateViewHolder(updateView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) {
|
||||||
AlbumView albumView = (AlbumView) view;
|
AlbumView albumView = (AlbumView) view;
|
||||||
albumView.setObject((Entry) item, imageLoader);
|
albumView.setObject((Entry) item, imageLoader);
|
||||||
} else if(viewType == VIEW_TYPE_SONG) {
|
} else if(viewType == VIEW_TYPE_SONG) {
|
||||||
SongView songView = (SongView) view;
|
SongView songView = (SongView) view;
|
||||||
songView.setObject((Entry) item, true);
|
songView.setObject((Entry) item, true);
|
||||||
} else if(viewType == VIEW_TYPE_ARTIST) {
|
} else if(viewType == VIEW_TYPE_ARTIST) {
|
||||||
view.setObject(item);
|
view.setObject(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Serializable item) {
|
public int getItemViewType(Serializable item) {
|
||||||
if(item instanceof Entry) {
|
if(item instanceof Entry) {
|
||||||
Entry entry = (Entry) item;
|
Entry entry = (Entry) item;
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
if (largeAlbums) {
|
if (largeAlbums) {
|
||||||
return VIEW_TYPE_ALBUM_CELL;
|
return VIEW_TYPE_ALBUM_CELL;
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_ALBUM_LINE;
|
return VIEW_TYPE_ALBUM_LINE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_SONG;
|
return VIEW_TYPE_SONG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_ARTIST;
|
return VIEW_TYPE_ARTIST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(Util.isOffline(context)) {
|
if(Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
menuInflater.inflate(R.menu.multiselect_media_offline, menu);
|
||||||
} else {
|
} else {
|
||||||
menuInflater.inflate(R.menu.multiselect_media, menu);
|
menuInflater.inflate(R.menu.multiselect_media, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.removeItem(R.id.menu_remove_playlist);
|
menu.removeItem(R.id.menu_remove_playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -46,471 +46,471 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder;
|
||||||
|
|
||||||
public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewHolder<T>> {
|
public abstract class SectionAdapter<T> extends RecyclerView.Adapter<UpdateViewHolder<T>> {
|
||||||
private static String TAG = SectionAdapter.class.getSimpleName();
|
private static String TAG = SectionAdapter.class.getSimpleName();
|
||||||
public static int VIEW_TYPE_HEADER = 0;
|
public static int VIEW_TYPE_HEADER = 0;
|
||||||
public static String[] ignoredArticles;
|
public static String[] ignoredArticles;
|
||||||
|
|
||||||
protected Context context;
|
protected Context context;
|
||||||
protected List<String> headers;
|
protected List<String> headers;
|
||||||
protected List<List<T>> sections;
|
protected List<List<T>> sections;
|
||||||
protected boolean singleSectionHeader;
|
protected boolean singleSectionHeader;
|
||||||
protected OnItemClickedListener<T> onItemClickedListener;
|
protected OnItemClickedListener<T> onItemClickedListener;
|
||||||
protected List<T> selected = new ArrayList<>();
|
protected List<T> selected = new ArrayList<>();
|
||||||
protected List<UpdateView> selectedViews = new ArrayList<>();
|
protected List<UpdateView> selectedViews = new ArrayList<>();
|
||||||
protected ActionMode currentActionMode;
|
protected ActionMode currentActionMode;
|
||||||
protected boolean checkable = false;
|
protected boolean checkable = false;
|
||||||
|
|
||||||
protected SectionAdapter() {}
|
protected SectionAdapter() {}
|
||||||
public SectionAdapter(Context context, List<T> section) {
|
public SectionAdapter(Context context, List<T> section) {
|
||||||
this(context, section, false);
|
this(context, section, false);
|
||||||
}
|
}
|
||||||
public SectionAdapter(Context context, List<T> section, boolean singleSectionHeader) {
|
public SectionAdapter(Context context, List<T> section, boolean singleSectionHeader) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = Arrays.asList("Section");
|
this.headers = Arrays.asList("Section");
|
||||||
this.sections = new ArrayList<>();
|
this.sections = new ArrayList<>();
|
||||||
this.sections.add(section);
|
this.sections.add(section);
|
||||||
this.singleSectionHeader = singleSectionHeader;
|
this.singleSectionHeader = singleSectionHeader;
|
||||||
}
|
}
|
||||||
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections) {
|
||||||
this(context, headers, sections, true);
|
this(context, headers, sections, true);
|
||||||
}
|
}
|
||||||
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections, boolean singleSectionHeader){
|
public SectionAdapter(Context context, List<String> headers, List<List<T>> sections, boolean singleSectionHeader){
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.sections = sections;
|
this.sections = sections;
|
||||||
this.singleSectionHeader = singleSectionHeader;
|
this.singleSectionHeader = singleSectionHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceExistingData(List<T> section) {
|
public void replaceExistingData(List<T> section) {
|
||||||
this.sections = new ArrayList<>();
|
this.sections = new ArrayList<>();
|
||||||
this.sections.add(section);
|
this.sections.add(section);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
public void replaceExistingData(List<String> headers, List<List<T>> sections) {
|
public void replaceExistingData(List<String> headers, List<List<T>> sections) {
|
||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.sections = sections;
|
this.sections = sections;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
if(viewType == VIEW_TYPE_HEADER) {
|
if(viewType == VIEW_TYPE_HEADER) {
|
||||||
return onCreateHeaderHolder(parent);
|
return onCreateHeaderHolder(parent);
|
||||||
} else {
|
} else {
|
||||||
final UpdateViewHolder<T> holder = onCreateSectionViewHolder(parent, viewType);
|
final UpdateViewHolder<T> holder = onCreateSectionViewHolder(parent, viewType);
|
||||||
final UpdateView updateView = holder.getUpdateView();
|
final UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(updateView != null) {
|
if(updateView != null) {
|
||||||
updateView.getChildAt(0).setOnClickListener(new View.OnClickListener() {
|
updateView.getChildAt(0).setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
T item = holder.getItem();
|
T item = holder.getItem();
|
||||||
updateView.onClick();
|
updateView.onClick();
|
||||||
if (currentActionMode != null) {
|
if (currentActionMode != null) {
|
||||||
if(updateView.isCheckable()) {
|
if(updateView.isCheckable()) {
|
||||||
if (selected.contains(item)) {
|
if (selected.contains(item)) {
|
||||||
selected.remove(item);
|
selected.remove(item);
|
||||||
selectedViews.remove(updateView);
|
selectedViews.remove(updateView);
|
||||||
setChecked(updateView, false);
|
setChecked(updateView, false);
|
||||||
} else {
|
} else {
|
||||||
selected.add(item);
|
selected.add(item);
|
||||||
selectedViews.add(updateView);
|
selectedViews.add(updateView);
|
||||||
setChecked(updateView, true);
|
setChecked(updateView, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected.isEmpty()) {
|
if (selected.isEmpty()) {
|
||||||
currentActionMode.finish();
|
currentActionMode.finish();
|
||||||
} else {
|
} else {
|
||||||
currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (onItemClickedListener != null) {
|
} else if (onItemClickedListener != null) {
|
||||||
onItemClickedListener.onItemClicked(updateView, item);
|
onItemClickedListener.onItemClicked(updateView, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
View moreButton = updateView.findViewById(R.id.item_more);
|
View moreButton = updateView.findViewById(R.id.item_more);
|
||||||
if (moreButton != null) {
|
if (moreButton != null) {
|
||||||
moreButton.setOnClickListener(new View.OnClickListener() {
|
moreButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
try {
|
try {
|
||||||
final T item = holder.getItem();
|
final T item = holder.getItem();
|
||||||
if (onItemClickedListener != null) {
|
if (onItemClickedListener != null) {
|
||||||
PopupMenu popup = new PopupMenu(context, v);
|
PopupMenu popup = new PopupMenu(context, v);
|
||||||
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
||||||
|
|
||||||
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||||
return onItemClickedListener.onContextItemSelected(menuItem, updateView, item);
|
return onItemClickedListener.onContextItemSelected(menuItem, updateView, item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
popup.show();
|
popup.show();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to show popup", e);
|
Log.w(TAG, "Failed to show popup", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(checkable) {
|
if(checkable) {
|
||||||
updateView.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() {
|
updateView.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View v) {
|
public boolean onLongClick(View v) {
|
||||||
if(updateView.isCheckable()) {
|
if(updateView.isCheckable()) {
|
||||||
if (currentActionMode == null) {
|
if (currentActionMode == null) {
|
||||||
startActionMode(holder);
|
startActionMode(holder);
|
||||||
} else {
|
} else {
|
||||||
updateView.getChildAt(0).performClick();
|
updateView.getChildAt(0).performClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateViewHolder holder, int position) {
|
public void onBindViewHolder(UpdateViewHolder holder, int position) {
|
||||||
UpdateView updateView = holder.getUpdateView();
|
UpdateView updateView = holder.getUpdateView();
|
||||||
|
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if(sections.size() == 1 && !singleSectionHeader) {
|
||||||
T item = sections.get(0).get(position);
|
T item = sections.get(0).get(position);
|
||||||
onBindViewHolder(holder, item, getItemViewType(position));
|
onBindViewHolder(holder, item, getItemViewType(position));
|
||||||
postBindView(updateView, item);
|
postBindView(updateView, item);
|
||||||
holder.setItem(item);
|
holder.setItem(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
int subHeader = 0;
|
int subHeader = 0;
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
boolean validHeader = headers.get(subHeader) != null;
|
boolean validHeader = headers.get(subHeader) != null;
|
||||||
if(position == subPosition && validHeader) {
|
if(position == subPosition && validHeader) {
|
||||||
onBindHeaderHolder(holder, headers.get(subHeader), subHeader);
|
onBindHeaderHolder(holder, headers.get(subHeader), subHeader);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int headerOffset = validHeader ? 1 : 0;
|
int headerOffset = validHeader ? 1 : 0;
|
||||||
if(position < (subPosition + section.size() + headerOffset)) {
|
if(position < (subPosition + section.size() + headerOffset)) {
|
||||||
T item = section.get(position - subPosition - headerOffset);
|
T item = section.get(position - subPosition - headerOffset);
|
||||||
onBindViewHolder(holder, item, getItemViewType(item));
|
onBindViewHolder(holder, item, getItemViewType(item));
|
||||||
|
|
||||||
postBindView(updateView, item);
|
postBindView(updateView, item);
|
||||||
holder.setItem(item);
|
holder.setItem(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size();
|
subPosition += section.size();
|
||||||
if(validHeader) {
|
if(validHeader) {
|
||||||
subPosition += 1;
|
subPosition += 1;
|
||||||
}
|
}
|
||||||
subHeader++;
|
subHeader++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postBindView(UpdateView updateView, T item) {
|
private void postBindView(UpdateView updateView, T item) {
|
||||||
if(updateView.isCheckable()) {
|
if(updateView.isCheckable()) {
|
||||||
setChecked(updateView, selected.contains(item));
|
setChecked(updateView, selected.contains(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
View moreButton = updateView.findViewById(R.id.item_more);
|
View moreButton = updateView.findViewById(R.id.item_more);
|
||||||
if(moreButton != null) {
|
if(moreButton != null) {
|
||||||
if(onItemClickedListener != null) {
|
if(onItemClickedListener != null) {
|
||||||
PopupMenu popup = new PopupMenu(context, moreButton);
|
PopupMenu popup = new PopupMenu(context, moreButton);
|
||||||
Menu menu = popup.getMenu();
|
Menu menu = popup.getMenu();
|
||||||
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item);
|
||||||
if (menu.size() == 0) {
|
if (menu.size() == 0) {
|
||||||
moreButton.setVisibility(View.GONE);
|
moreButton.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
moreButton.setVisibility(View.VISIBLE);
|
moreButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
moreButton.setVisibility(View.VISIBLE);
|
moreButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if(sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).size();
|
return sections.get(0).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for(String header: headers) {
|
for(String header: headers) {
|
||||||
if(header != null) {
|
if(header != null) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
count += section.size();
|
count += section.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if(sections.size() == 1 && !singleSectionHeader) {
|
||||||
return getItemViewType(sections.get(0).get(position));
|
return getItemViewType(sections.get(0).get(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
int subHeader = 0;
|
int subHeader = 0;
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
boolean validHeader = headers.get(subHeader) != null;
|
boolean validHeader = headers.get(subHeader) != null;
|
||||||
if(position == subPosition && validHeader) {
|
if(position == subPosition && validHeader) {
|
||||||
return VIEW_TYPE_HEADER;
|
return VIEW_TYPE_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
int headerOffset = validHeader ? 1 : 0;
|
int headerOffset = validHeader ? 1 : 0;
|
||||||
if(position < (subPosition + section.size() + headerOffset)) {
|
if(position < (subPosition + section.size() + headerOffset)) {
|
||||||
return getItemViewType(section.get(position - subPosition - headerOffset));
|
return getItemViewType(section.get(position - subPosition - headerOffset));
|
||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size();
|
subPosition += section.size();
|
||||||
if(validHeader) {
|
if(validHeader) {
|
||||||
subPosition += 1;
|
subPosition += 1;
|
||||||
}
|
}
|
||||||
subHeader++;
|
subHeader++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) {
|
||||||
return new UpdateViewHolder(new BasicHeaderView(context));
|
return new UpdateViewHolder(new BasicHeaderView(context));
|
||||||
}
|
}
|
||||||
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) {
|
||||||
UpdateView view = holder.getUpdateView();
|
UpdateView view = holder.getUpdateView();
|
||||||
if(view != null) {
|
if(view != null) {
|
||||||
view.setObject(header);
|
view.setObject(header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public T getItemForPosition(int position) {
|
public T getItemForPosition(int position) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if(sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).get(position);
|
return sections.get(0).get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
if(position == subPosition) {
|
if(position == subPosition) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(position <= (subPosition + section.size())) {
|
if(position <= (subPosition + section.size())) {
|
||||||
return section.get(position - subPosition - 1);
|
return section.get(position - subPosition - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size() + 1;
|
subPosition += section.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public int getItemPosition(T item) {
|
public int getItemPosition(T item) {
|
||||||
if(sections.size() == 1 && !singleSectionHeader) {
|
if(sections.size() == 1 && !singleSectionHeader) {
|
||||||
return sections.get(0).indexOf(item);
|
return sections.get(0).indexOf(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
subPosition += section.size() + 1;
|
subPosition += section.size() + 1;
|
||||||
|
|
||||||
int position = section.indexOf(item);
|
int position = section.indexOf(item);
|
||||||
if(position != -1) {
|
if(position != -1) {
|
||||||
return position + subPosition;
|
return position + subPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnItemClickedListener(OnItemClickedListener<T> onItemClickedListener) {
|
public void setOnItemClickedListener(OnItemClickedListener<T> onItemClickedListener) {
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSelected(T item) {
|
public void addSelected(T item) {
|
||||||
selected.add(item);
|
selected.add(item);
|
||||||
}
|
}
|
||||||
public List<T> getSelected() {
|
public List<T> getSelected() {
|
||||||
List<T> selected = new ArrayList<>();
|
List<T> selected = new ArrayList<>();
|
||||||
selected.addAll(this.selected);
|
selected.addAll(this.selected);
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearSelected() {
|
public void clearSelected() {
|
||||||
// TODO: This needs to work with multiple sections
|
// TODO: This needs to work with multiple sections
|
||||||
for(T item: selected) {
|
for(T item: selected) {
|
||||||
int index = sections.get(0).indexOf(item);
|
int index = sections.get(0).indexOf(item);
|
||||||
|
|
||||||
if(singleSectionHeader) {
|
if(singleSectionHeader) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selected.clear();
|
selected.clear();
|
||||||
|
|
||||||
for(UpdateView updateView: selectedViews) {
|
for(UpdateView updateView: selectedViews) {
|
||||||
updateView.setChecked(false);
|
updateView.setChecked(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveItem(int from, int to) {
|
public void moveItem(int from, int to) {
|
||||||
List<T> section = sections.get(0);
|
List<T> section = sections.get(0);
|
||||||
int max = section.size();
|
int max = section.size();
|
||||||
if(to >= max) {
|
if(to >= max) {
|
||||||
to = max - 1;
|
to = max - 1;
|
||||||
} else if(to < 0) {
|
} else if(to < 0) {
|
||||||
to = 0;
|
to = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
T moved = section.remove(from);
|
T moved = section.remove(from);
|
||||||
section.add(to, moved);
|
section.add(to, moved);
|
||||||
|
|
||||||
notifyItemMoved(from, to);
|
notifyItemMoved(from, to);
|
||||||
}
|
}
|
||||||
public void removeItem(T item) {
|
public void removeItem(T item) {
|
||||||
int subPosition = 0;
|
int subPosition = 0;
|
||||||
for(List<T> section: sections) {
|
for(List<T> section: sections) {
|
||||||
if(sections.size() > 1 || singleSectionHeader) {
|
if(sections.size() > 1 || singleSectionHeader) {
|
||||||
subPosition++;
|
subPosition++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = section.indexOf(item);
|
int index = section.indexOf(item);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
section.remove(item);
|
section.remove(item);
|
||||||
notifyItemRemoved(subPosition + index);
|
notifyItemRemoved(subPosition + index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
subPosition += section.size();
|
subPosition += section.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType);
|
public abstract UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType);
|
||||||
public abstract void onBindViewHolder(UpdateViewHolder holder, T item, int viewType);
|
public abstract void onBindViewHolder(UpdateViewHolder holder, T item, int viewType);
|
||||||
public abstract int getItemViewType(T item);
|
public abstract int getItemViewType(T item);
|
||||||
public void setCheckable(boolean checkable) {
|
public void setCheckable(boolean checkable) {
|
||||||
this.checkable = checkable;
|
this.checkable = checkable;
|
||||||
}
|
}
|
||||||
public void setChecked(UpdateView updateView, boolean checked) {
|
public void setChecked(UpdateView updateView, boolean checked) {
|
||||||
updateView.setChecked(checked);
|
updateView.setChecked(checked);
|
||||||
}
|
}
|
||||||
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {}
|
public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) {}
|
||||||
|
|
||||||
private void startActionMode(final UpdateView.UpdateViewHolder<T> holder) {
|
private void startActionMode(final UpdateView.UpdateViewHolder<T> holder) {
|
||||||
final UpdateView<T> updateView = holder.getUpdateView();
|
final UpdateView<T> updateView = holder.getUpdateView();
|
||||||
if (context instanceof SubsonicFragmentActivity && currentActionMode == null) {
|
if (context instanceof SubsonicFragmentActivity && currentActionMode == null) {
|
||||||
final SubsonicFragmentActivity fragmentActivity = (SubsonicFragmentActivity) context;
|
final SubsonicFragmentActivity fragmentActivity = (SubsonicFragmentActivity) context;
|
||||||
fragmentActivity.startSupportActionMode(new ActionMode.Callback() {
|
fragmentActivity.startSupportActionMode(new ActionMode.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||||
currentActionMode = mode;
|
currentActionMode = mode;
|
||||||
|
|
||||||
T item = holder.getItem();
|
T item = holder.getItem();
|
||||||
selected.add(item);
|
selected.add(item);
|
||||||
selectedViews.add(updateView);
|
selectedViews.add(updateView);
|
||||||
setChecked(updateView, true);
|
setChecked(updateView, true);
|
||||||
|
|
||||||
onCreateActionModeMenu(menu, mode.getMenuInflater());
|
onCreateActionModeMenu(menu, mode.getMenuInflater());
|
||||||
MenuUtil.hideMenuItems(context, menu, updateView);
|
MenuUtil.hideMenuItems(context, menu, updateView);
|
||||||
|
|
||||||
mode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
mode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size()));
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
||||||
TypedValue typedValue = new TypedValue();
|
TypedValue typedValue = new TypedValue();
|
||||||
Resources.Theme theme = context.getTheme();
|
Resources.Theme theme = context.getTheme();
|
||||||
theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true);
|
theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true);
|
||||||
int colorPrimaryDark = typedValue.data;
|
int colorPrimaryDark = typedValue.data;
|
||||||
|
|
||||||
Window window = ((SubsonicFragmentActivity) context).getWindow();
|
Window window = ((SubsonicFragmentActivity) context).getWindow();
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
window.setStatusBarColor(colorPrimaryDark);
|
window.setStatusBarColor(colorPrimaryDark);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||||
if (fragmentActivity.onOptionsItemSelected(item)) {
|
if (fragmentActivity.onOptionsItemSelected(item)) {
|
||||||
currentActionMode.finish();
|
currentActionMode.finish();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyActionMode(ActionMode mode) {
|
public void onDestroyActionMode(ActionMode mode) {
|
||||||
currentActionMode = null;
|
currentActionMode = null;
|
||||||
selected.clear();
|
selected.clear();
|
||||||
for (UpdateView<T> updateView : selectedViews) {
|
for (UpdateView<T> updateView : selectedViews) {
|
||||||
updateView.setChecked(false);
|
updateView.setChecked(false);
|
||||||
}
|
}
|
||||||
selectedViews.clear();
|
selectedViews.clear();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
||||||
Window window = ((SubsonicFragmentActivity) context).getWindow();
|
Window window = ((SubsonicFragmentActivity) context).getWindow();
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void stopActionMode() {
|
public void stopActionMode() {
|
||||||
if(currentActionMode != null) {
|
if(currentActionMode != null) {
|
||||||
currentActionMode.finish();
|
currentActionMode.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNameIndex(String name) {
|
public String getNameIndex(String name) {
|
||||||
return getNameIndex(name, false);
|
return getNameIndex(name, false);
|
||||||
}
|
}
|
||||||
public String getNameIndex(String name, boolean removeIgnoredArticles) {
|
public String getNameIndex(String name, boolean removeIgnoredArticles) {
|
||||||
if(name == null) {
|
if(name == null) {
|
||||||
return "*";
|
return "*";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(removeIgnoredArticles) {
|
if(removeIgnoredArticles) {
|
||||||
if (ignoredArticles == null) {
|
if (ignoredArticles == null) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String ignoredArticlesString = prefs.getString(Constants.CACHE_KEY_IGNORE, "The El La Los Las Le Les");
|
String ignoredArticlesString = prefs.getString(Constants.CACHE_KEY_IGNORE, "The El La Los Las Le Les");
|
||||||
ignoredArticles = ignoredArticlesString.split(" ");
|
ignoredArticles = ignoredArticlesString.split(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
name = name.toLowerCase();
|
name = name.toLowerCase();
|
||||||
for (String article : ignoredArticles) {
|
for (String article : ignoredArticles) {
|
||||||
int index = name.indexOf(article.toLowerCase() + " ");
|
int index = name.indexOf(article.toLowerCase() + " ");
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
name = name.substring(article.length() + 1);
|
name = name.substring(article.length() + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String index = name.substring(0, 1).toUpperCase();
|
String index = name.substring(0, 1).toUpperCase();
|
||||||
if (!Character.isLetter(index.charAt(0))) {
|
if (!Character.isLetter(index.charAt(0))) {
|
||||||
index = "#";
|
index = "#";
|
||||||
}
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface OnItemClickedListener<T> {
|
public interface OnItemClickedListener<T> {
|
||||||
void onItemClicked(UpdateView<T> updateView, T item);
|
void onItemClicked(UpdateView<T> updateView, T item);
|
||||||
void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<T> updateView, T item);
|
void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<T> updateView, T item);
|
||||||
boolean onContextItemSelected(MenuItem menuItem, UpdateView<T> updateView, T item);
|
boolean onContextItemSelected(MenuItem menuItem, UpdateView<T> updateView, T item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.adapter;
|
package net.nullsum.audinaut.adapter;
|
||||||
@ -36,86 +36,86 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
import static net.nullsum.audinaut.domain.User.Setting;
|
import static net.nullsum.audinaut.domain.User.Setting;
|
||||||
|
|
||||||
public class SettingsAdapter extends SectionAdapter<Setting> {
|
public class SettingsAdapter extends SectionAdapter<Setting> {
|
||||||
private static final String TAG = SettingsAdapter.class.getSimpleName();
|
private static final String TAG = SettingsAdapter.class.getSimpleName();
|
||||||
public final int VIEW_TYPE_SETTING = 1;
|
public final int VIEW_TYPE_SETTING = 1;
|
||||||
public final int VIEW_TYPE_SETTING_HEADER = 2;
|
public final int VIEW_TYPE_SETTING_HEADER = 2;
|
||||||
|
|
||||||
private final User user;
|
private final User user;
|
||||||
private final boolean editable;
|
private final boolean editable;
|
||||||
private final ImageLoader imageLoader;
|
private final ImageLoader imageLoader;
|
||||||
|
|
||||||
public SettingsAdapter(Context context, User user, List<String> headers, List<List<User.Setting>> settingSections, ImageLoader imageLoader, boolean editable, OnItemClickedListener<Setting> onItemClickedListener) {
|
public SettingsAdapter(Context context, User user, List<String> headers, List<List<User.Setting>> settingSections, ImageLoader imageLoader, boolean editable, OnItemClickedListener<Setting> onItemClickedListener) {
|
||||||
super(context, headers, settingSections, imageLoader != null);
|
super(context, headers, settingSections, imageLoader != null);
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.imageLoader = imageLoader;
|
this.imageLoader = imageLoader;
|
||||||
this.editable = editable;
|
this.editable = editable;
|
||||||
this.onItemClickedListener = onItemClickedListener;
|
this.onItemClickedListener = onItemClickedListener;
|
||||||
|
|
||||||
for(List<Setting> settings: sections) {
|
for(List<Setting> settings: sections) {
|
||||||
for (Setting setting : settings) {
|
for (Setting setting : settings) {
|
||||||
if (setting.getValue()) {
|
if (setting.getValue()) {
|
||||||
addSelected(setting);
|
addSelected(setting);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
int viewType = super.getItemViewType(position);
|
int viewType = super.getItemViewType(position);
|
||||||
if(viewType == SectionAdapter.VIEW_TYPE_HEADER) {
|
if(viewType == SectionAdapter.VIEW_TYPE_HEADER) {
|
||||||
if(position == 0 && imageLoader != null) {
|
if(position == 0 && imageLoader != null) {
|
||||||
return VIEW_TYPE_HEADER;
|
return VIEW_TYPE_HEADER;
|
||||||
} else {
|
} else {
|
||||||
return VIEW_TYPE_SETTING_HEADER;
|
return VIEW_TYPE_SETTING_HEADER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return viewType;
|
return viewType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description, int sectionIndex) {
|
public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description, int sectionIndex) {
|
||||||
View header = holder.getView();
|
View header = holder.getView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) {
|
||||||
if(viewType == VIEW_TYPE_SETTING_HEADER) {
|
if(viewType == VIEW_TYPE_SETTING_HEADER) {
|
||||||
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context));
|
return new UpdateView.UpdateViewHolder(new BasicHeaderView(context));
|
||||||
} else {
|
} else {
|
||||||
return new UpdateView.UpdateViewHolder(new SettingView(context));
|
return new UpdateView.UpdateViewHolder(new SettingView(context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) {
|
public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) {
|
||||||
holder.getUpdateView().setObject(item, editable);
|
holder.getUpdateView().setObject(item, editable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(Setting item) {
|
public int getItemViewType(Setting item) {
|
||||||
return VIEW_TYPE_SETTING;
|
return VIEW_TYPE_SETTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setChecked(UpdateView updateView, boolean checked) {
|
public void setChecked(UpdateView updateView, boolean checked) {
|
||||||
if(updateView instanceof SettingView) {
|
if(updateView instanceof SettingView) {
|
||||||
updateView.setChecked(checked);
|
updateView.setChecked(checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, OnItemClickedListener<Setting> onItemClickedListener) {
|
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, OnItemClickedListener<Setting> onItemClickedListener) {
|
||||||
return getSettingsAdapter(context, user, imageLoader, true, onItemClickedListener);
|
return getSettingsAdapter(context, user, imageLoader, true, onItemClickedListener);
|
||||||
}
|
}
|
||||||
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean isEditable, OnItemClickedListener<Setting> onItemClickedListener) {
|
public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean isEditable, OnItemClickedListener<Setting> onItemClickedListener) {
|
||||||
List<String> headers = new ArrayList<>();
|
List<String> headers = new ArrayList<>();
|
||||||
List<List<User.Setting>> settingsSections = new ArrayList<>();
|
List<List<User.Setting>> settingsSections = new ArrayList<>();
|
||||||
settingsSections.add(user.getSettings());
|
settingsSections.add(user.getSettings());
|
||||||
|
|
||||||
if(user.getMusicFolderSettings() != null) {
|
if(user.getMusicFolderSettings() != null) {
|
||||||
settingsSections.add(user.getMusicFolderSettings());
|
settingsSections.add(user.getMusicFolderSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SettingsAdapter(context, user, headers, settingsSections, imageLoader, isEditable, onItemClickedListener);
|
return new SettingsAdapter(context, user, headers, settingsSections, imageLoader, isEditable, onItemClickedListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,27 +29,27 @@ public class AudioEffectsController {
|
|||||||
private static final String TAG = AudioEffectsController.class.getSimpleName();
|
private static final String TAG = AudioEffectsController.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private int audioSessionId = 0;
|
private int audioSessionId = 0;
|
||||||
|
|
||||||
private EqualizerController equalizerController;
|
private EqualizerController equalizerController;
|
||||||
|
|
||||||
public AudioEffectsController(Context context, int audioSessionId) {
|
public AudioEffectsController(Context context, int audioSessionId) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.audioSessionId = audioSessionId;
|
this.audioSessionId = audioSessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
if(equalizerController != null) {
|
if(equalizerController != null) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EqualizerController getEqualizerController() {
|
public EqualizerController getEqualizerController() {
|
||||||
if (equalizerController == null) {
|
if (equalizerController == null) {
|
||||||
equalizerController = new EqualizerController(context, audioSessionId);
|
equalizerController = new EqualizerController(context, audioSessionId);
|
||||||
equalizerController.loadSettings();
|
equalizerController.loadSettings();
|
||||||
}
|
}
|
||||||
return equalizerController;
|
return equalizerController;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.audiofx;
|
package net.nullsum.audinaut.audiofx;
|
||||||
|
|
||||||
@ -23,55 +23,55 @@ import android.media.audiofx.LoudnessEnhancer;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class LoudnessEnhancerController {
|
public class LoudnessEnhancerController {
|
||||||
private static final String TAG = LoudnessEnhancerController.class.getSimpleName();
|
private static final String TAG = LoudnessEnhancerController.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private LoudnessEnhancer enhancer;
|
private LoudnessEnhancer enhancer;
|
||||||
private boolean released = false;
|
private boolean released = false;
|
||||||
private int audioSessionId = 0;
|
private int audioSessionId = 0;
|
||||||
|
|
||||||
public LoudnessEnhancerController(Context context, int audioSessionId) {
|
public LoudnessEnhancerController(Context context, int audioSessionId) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
try {
|
try {
|
||||||
this.audioSessionId = audioSessionId;
|
this.audioSessionId = audioSessionId;
|
||||||
enhancer = new LoudnessEnhancer(audioSessionId);
|
enhancer = new LoudnessEnhancer(audioSessionId);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.w(TAG, "Failed to create enhancer", x);
|
Log.w(TAG, "Failed to create enhancer", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAvailable() {
|
public boolean isAvailable() {
|
||||||
return enhancer != null;
|
return enhancer != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
try {
|
try {
|
||||||
return isAvailable() && enhancer.getEnabled();
|
return isAvailable() && enhancer.getEnabled();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enable() {
|
public void enable() {
|
||||||
enhancer.setEnabled(true);
|
enhancer.setEnabled(true);
|
||||||
}
|
}
|
||||||
public void disable() {
|
public void disable() {
|
||||||
enhancer.setEnabled(false);
|
enhancer.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getGain() {
|
public float getGain() {
|
||||||
return enhancer.getTargetGain();
|
return enhancer.getTargetGain();
|
||||||
}
|
}
|
||||||
public void setGain(int gain) {
|
public void setGain(int gain) {
|
||||||
enhancer.setTargetGain(gain);
|
enhancer.setTargetGain(gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
if (isAvailable()) {
|
if (isAvailable()) {
|
||||||
enhancer.release();
|
enhancer.release();
|
||||||
released = true;
|
released = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,19 +43,19 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class MusicDirectory implements Serializable {
|
public class MusicDirectory implements Serializable {
|
||||||
private static final String TAG = MusicDirectory.class.getSimpleName();
|
private static final String TAG = MusicDirectory.class.getSimpleName();
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String id;
|
private String id;
|
||||||
private String parent;
|
private String parent;
|
||||||
private List<Entry> children;
|
private List<Entry> children;
|
||||||
|
|
||||||
public MusicDirectory() {
|
public MusicDirectory() {
|
||||||
children = new ArrayList<Entry>();
|
children = new ArrayList<Entry>();
|
||||||
}
|
}
|
||||||
public MusicDirectory(List<Entry> children) {
|
public MusicDirectory(List<Entry> children) {
|
||||||
this.children = children;
|
this.children = children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@ -65,34 +65,34 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setId(String id) {
|
public void setId(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getParent() {
|
public String getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParent(String parent) {
|
public void setParent(String parent) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addChild(Entry child) {
|
public void addChild(Entry child) {
|
||||||
if(child != null) {
|
if(child != null) {
|
||||||
children.add(child);
|
children.add(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void addChildren(List<Entry> children) {
|
public void addChildren(List<Entry> children) {
|
||||||
this.children.addAll(children);
|
this.children.addAll(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceChildren(List<Entry> children) {
|
public void replaceChildren(List<Entry> children) {
|
||||||
this.children = children;
|
this.children = children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized List<Entry> getChildren() {
|
public synchronized List<Entry> getChildren() {
|
||||||
return getChildren(true, true);
|
return getChildren(true, true);
|
||||||
@ -111,209 +111,209 @@ public class MusicDirectory implements Serializable {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public synchronized List<Entry> getSongs() {
|
public synchronized List<Entry> getSongs() {
|
||||||
List<Entry> result = new ArrayList<Entry>();
|
List<Entry> result = new ArrayList<Entry>();
|
||||||
for (Entry child : children) {
|
for (Entry child : children) {
|
||||||
if (child != null && !child.isDirectory()) {
|
if (child != null && !child.isDirectory()) {
|
||||||
result.add(child);
|
result.add(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized int getChildrenSize() {
|
public synchronized int getChildrenSize() {
|
||||||
return children.size();
|
return children.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shuffleChildren() {
|
public void shuffleChildren() {
|
||||||
Collections.shuffle(this.children);
|
Collections.shuffle(this.children);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sortChildren(Context context, int instance) {
|
public void sortChildren(Context context, int instance) {
|
||||||
sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
||||||
}
|
}
|
||||||
public void sortChildren(boolean byYear) {
|
public void sortChildren(boolean byYear) {
|
||||||
EntryComparator.sort(children, byYear);
|
EntryComparator.sort(children, byYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean updateMetadata(MusicDirectory refreshedDirectory) {
|
public synchronized boolean updateMetadata(MusicDirectory refreshedDirectory) {
|
||||||
boolean metadataUpdated = false;
|
boolean metadataUpdated = false;
|
||||||
Iterator<Entry> it = children.iterator();
|
Iterator<Entry> it = children.iterator();
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
Entry entry = it.next();
|
Entry entry = it.next();
|
||||||
int index = refreshedDirectory.children.indexOf(entry);
|
int index = refreshedDirectory.children.indexOf(entry);
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
final Entry refreshed = refreshedDirectory.children.get(index);
|
final Entry refreshed = refreshedDirectory.children.get(index);
|
||||||
|
|
||||||
entry.setTitle(refreshed.getTitle());
|
entry.setTitle(refreshed.getTitle());
|
||||||
entry.setAlbum(refreshed.getAlbum());
|
entry.setAlbum(refreshed.getAlbum());
|
||||||
entry.setArtist(refreshed.getArtist());
|
entry.setArtist(refreshed.getArtist());
|
||||||
entry.setTrack(refreshed.getTrack());
|
entry.setTrack(refreshed.getTrack());
|
||||||
entry.setYear(refreshed.getYear());
|
entry.setYear(refreshed.getYear());
|
||||||
entry.setGenre(refreshed.getGenre());
|
entry.setGenre(refreshed.getGenre());
|
||||||
entry.setTranscodedContentType(refreshed.getTranscodedContentType());
|
entry.setTranscodedContentType(refreshed.getTranscodedContentType());
|
||||||
entry.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
entry.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
||||||
entry.setDiscNumber(refreshed.getDiscNumber());
|
entry.setDiscNumber(refreshed.getDiscNumber());
|
||||||
entry.setType(refreshed.getType());
|
entry.setType(refreshed.getType());
|
||||||
if(!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) {
|
if(!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) {
|
||||||
metadataUpdated = true;
|
metadataUpdated = true;
|
||||||
entry.setCoverArt(refreshed.getCoverArt());
|
entry.setCoverArt(refreshed.getCoverArt());
|
||||||
}
|
}
|
||||||
|
|
||||||
new UpdateHelper.EntryInstanceUpdater(entry) {
|
new UpdateHelper.EntryInstanceUpdater(entry) {
|
||||||
@Override
|
@Override
|
||||||
public void update(Entry found) {
|
public void update(Entry found) {
|
||||||
found.setTitle(refreshed.getTitle());
|
found.setTitle(refreshed.getTitle());
|
||||||
found.setAlbum(refreshed.getAlbum());
|
found.setAlbum(refreshed.getAlbum());
|
||||||
found.setArtist(refreshed.getArtist());
|
found.setArtist(refreshed.getArtist());
|
||||||
found.setTrack(refreshed.getTrack());
|
found.setTrack(refreshed.getTrack());
|
||||||
found.setYear(refreshed.getYear());
|
found.setYear(refreshed.getYear());
|
||||||
found.setGenre(refreshed.getGenre());
|
found.setGenre(refreshed.getGenre());
|
||||||
found.setTranscodedContentType(refreshed.getTranscodedContentType());
|
found.setTranscodedContentType(refreshed.getTranscodedContentType());
|
||||||
found.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
found.setTranscodedSuffix(refreshed.getTranscodedSuffix());
|
||||||
found.setDiscNumber(refreshed.getDiscNumber());
|
found.setDiscNumber(refreshed.getDiscNumber());
|
||||||
found.setType(refreshed.getType());
|
found.setType(refreshed.getType());
|
||||||
if(!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) {
|
if(!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) {
|
||||||
found.setCoverArt(refreshed.getCoverArt());
|
found.setCoverArt(refreshed.getCoverArt());
|
||||||
metadataUpdate = DownloadService.METADATA_UPDATED_COVER_ART;
|
metadataUpdate = DownloadService.METADATA_UPDATED_COVER_ART;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return metadataUpdated;
|
return metadataUpdated;
|
||||||
}
|
}
|
||||||
public synchronized boolean updateEntriesList(Context context, int instance, MusicDirectory refreshedDirectory) {
|
public synchronized boolean updateEntriesList(Context context, int instance, MusicDirectory refreshedDirectory) {
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
Iterator<Entry> it = children.iterator();
|
Iterator<Entry> it = children.iterator();
|
||||||
while(it.hasNext()) {
|
while(it.hasNext()) {
|
||||||
Entry entry = it.next();
|
Entry entry = it.next();
|
||||||
// No longer exists in here
|
// No longer exists in here
|
||||||
if(refreshedDirectory.children.indexOf(entry) == -1) {
|
if(refreshedDirectory.children.indexOf(entry) == -1) {
|
||||||
it.remove();
|
it.remove();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we contain all children from refreshed set
|
// Make sure we contain all children from refreshed set
|
||||||
boolean resort = false;
|
boolean resort = false;
|
||||||
for(Entry refreshed: refreshedDirectory.children) {
|
for(Entry refreshed: refreshedDirectory.children) {
|
||||||
if(!this.children.contains(refreshed)) {
|
if(!this.children.contains(refreshed)) {
|
||||||
this.children.add(refreshed);
|
this.children.add(refreshed);
|
||||||
resort = true;
|
resort = true;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resort) {
|
if(resort) {
|
||||||
this.sortChildren(context, instance);
|
this.sortChildren(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Entry implements Serializable {
|
public static class Entry implements Serializable {
|
||||||
public static final int TYPE_SONG = 0;
|
public static final int TYPE_SONG = 0;
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String parent;
|
private String parent;
|
||||||
private String grandParent;
|
private String grandParent;
|
||||||
private String albumId;
|
private String albumId;
|
||||||
private String artistId;
|
private String artistId;
|
||||||
private boolean directory;
|
private boolean directory;
|
||||||
private String title;
|
private String title;
|
||||||
private String album;
|
private String album;
|
||||||
private String artist;
|
private String artist;
|
||||||
private Integer track;
|
private Integer track;
|
||||||
private Integer year;
|
private Integer year;
|
||||||
private String genre;
|
private String genre;
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private String suffix;
|
private String suffix;
|
||||||
private String transcodedContentType;
|
private String transcodedContentType;
|
||||||
private String transcodedSuffix;
|
private String transcodedSuffix;
|
||||||
private String coverArt;
|
private String coverArt;
|
||||||
private Long size;
|
private Long size;
|
||||||
private Integer duration;
|
private Integer duration;
|
||||||
private Integer bitRate;
|
private Integer bitRate;
|
||||||
private String path;
|
private String path;
|
||||||
private Integer discNumber;
|
private Integer discNumber;
|
||||||
private int type = 0;
|
private int type = 0;
|
||||||
private int closeness;
|
private int closeness;
|
||||||
private transient Artist linkedArtist;
|
private transient Artist linkedArtist;
|
||||||
|
|
||||||
public Entry() {
|
public Entry() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public Entry(String id) {
|
public Entry(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
public Entry(Artist artist) {
|
public Entry(Artist artist) {
|
||||||
this.id = artist.getId();
|
this.id = artist.getId();
|
||||||
this.title = artist.getName();
|
this.title = artist.getName();
|
||||||
this.directory = true;
|
this.directory = true;
|
||||||
this.linkedArtist = artist;
|
this.linkedArtist = artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadMetadata(File file) {
|
public void loadMetadata(File file) {
|
||||||
try {
|
try {
|
||||||
MediaMetadataRetriever metadata = new MediaMetadataRetriever();
|
MediaMetadataRetriever metadata = new MediaMetadataRetriever();
|
||||||
metadata.setDataSource(file.getAbsolutePath());
|
metadata.setDataSource(file.getAbsolutePath());
|
||||||
String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER);
|
String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER);
|
||||||
if(discNumber == null) {
|
if(discNumber == null) {
|
||||||
discNumber = "1/1";
|
discNumber = "1/1";
|
||||||
}
|
}
|
||||||
int slashIndex = discNumber.indexOf("/");
|
int slashIndex = discNumber.indexOf("/");
|
||||||
if(slashIndex > 0) {
|
if(slashIndex > 0) {
|
||||||
discNumber = discNumber.substring(0, slashIndex);
|
discNumber = discNumber.substring(0, slashIndex);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
setDiscNumber(Integer.parseInt(discNumber));
|
setDiscNumber(Integer.parseInt(discNumber));
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Non numbers in disc field!");
|
Log.w(TAG, "Non numbers in disc field!");
|
||||||
}
|
}
|
||||||
String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
|
String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE);
|
||||||
setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000);
|
setBitRate(Integer.parseInt((bitrate != null) ? bitrate : "0") / 1000);
|
||||||
String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
|
||||||
setDuration(Integer.parseInt(length) / 1000);
|
setDuration(Integer.parseInt(length) / 1000);
|
||||||
String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
|
String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
|
||||||
if(artist != null) {
|
if(artist != null) {
|
||||||
setArtist(artist);
|
setArtist(artist);
|
||||||
}
|
}
|
||||||
String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
|
||||||
if(album != null) {
|
if(album != null) {
|
||||||
setAlbum(album);
|
setAlbum(album);
|
||||||
}
|
}
|
||||||
metadata.release();
|
metadata.release();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver", e);
|
Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void rebaseTitleOffPath() {
|
public void rebaseTitleOffPath() {
|
||||||
try {
|
try {
|
||||||
String filename = getPath();
|
String filename = getPath();
|
||||||
if(filename == null) {
|
if(filename == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = filename.lastIndexOf('/');
|
int index = filename.lastIndexOf('/');
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
filename = filename.substring(index + 1);
|
filename = filename.substring(index + 1);
|
||||||
if (getTrack() != null) {
|
if (getTrack() != null) {
|
||||||
filename = filename.replace(String.format("%02d ", getTrack()), "");
|
filename = filename.replace(String.format("%02d ", getTrack()), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
index = filename.lastIndexOf('.');
|
index = filename.lastIndexOf('.');
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
filename = filename.substring(0, index);
|
filename = filename.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle(filename);
|
setTitle(filename);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to update title based off of path", e);
|
Log.w(TAG, "Failed to update title based off of path", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@ -331,7 +331,7 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getGrandParent() {
|
public String getGrandParent() {
|
||||||
return grandParent;
|
return grandParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,21 +339,21 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.grandParent = grandParent;
|
this.grandParent = grandParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlbumId() {
|
public String getAlbumId() {
|
||||||
return albumId;
|
return albumId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlbumId(String albumId) {
|
public void setAlbumId(String albumId) {
|
||||||
this.albumId = albumId;
|
this.albumId = albumId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getArtistId() {
|
public String getArtistId() {
|
||||||
return artistId;
|
return artistId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setArtistId(String artistId) {
|
public void setArtistId(String artistId) {
|
||||||
this.artistId = artistId;
|
this.artistId = artistId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirectory() {
|
public boolean isDirectory() {
|
||||||
return directory;
|
return directory;
|
||||||
@ -375,17 +375,17 @@ public class MusicDirectory implements Serializable {
|
|||||||
return album;
|
return album;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAlbum() {
|
public boolean isAlbum() {
|
||||||
return getParent() != null || getArtist() != null;
|
return getParent() != null || getArtist() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAlbumDisplay() {
|
public String getAlbumDisplay() {
|
||||||
if(album != null && title.startsWith("Disc ")) {
|
if(album != null && title.startsWith("Disc ")) {
|
||||||
return album;
|
return album;
|
||||||
} else {
|
} else {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlbum(String album) {
|
public void setAlbum(String album) {
|
||||||
this.album = album;
|
this.album = album;
|
||||||
@ -495,43 +495,43 @@ public class MusicDirectory implements Serializable {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getDiscNumber() {
|
public Integer getDiscNumber() {
|
||||||
return discNumber;
|
return discNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDiscNumber(Integer discNumber) {
|
public void setDiscNumber(Integer discNumber) {
|
||||||
this.discNumber = discNumber;
|
this.discNumber = discNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
public void setType(int type) {
|
public void setType(int type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
public boolean isSong() {
|
public boolean isSong() {
|
||||||
return type == TYPE_SONG;
|
return type == TYPE_SONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCloseness() {
|
public int getCloseness() {
|
||||||
return closeness;
|
return closeness;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCloseness(int closeness) {
|
public void setCloseness(int closeness) {
|
||||||
this.closeness = closeness;
|
this.closeness = closeness;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnlineId(Context context) {
|
public boolean isOnlineId(Context context) {
|
||||||
try {
|
try {
|
||||||
String cacheLocation = Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
String cacheLocation = Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
return cacheLocation == null || id == null || id.indexOf(cacheLocation) == -1;
|
return cacheLocation == null || id == null || id.indexOf(cacheLocation) == -1;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to check online id validity");
|
Log.w(TAG, "Failed to check online id validity");
|
||||||
|
|
||||||
// Err on the side of default functionality
|
// Err on the side of default functionality
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
@ -555,72 +555,72 @@ public class MusicDirectory implements Serializable {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class EntryComparator implements Comparator<Entry> {
|
public static class EntryComparator implements Comparator<Entry> {
|
||||||
private boolean byYear;
|
private boolean byYear;
|
||||||
private Collator collator;
|
private Collator collator;
|
||||||
|
|
||||||
public EntryComparator(boolean byYear) {
|
public EntryComparator(boolean byYear) {
|
||||||
this.byYear = byYear;
|
this.byYear = byYear;
|
||||||
this.collator = Collator.getInstance(Locale.US);
|
this.collator = Collator.getInstance(Locale.US);
|
||||||
this.collator.setStrength(Collator.PRIMARY);
|
this.collator.setStrength(Collator.PRIMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
public int compare(Entry lhs, Entry rhs) {
|
||||||
if(lhs.isDirectory() && !rhs.isDirectory()) {
|
if(lhs.isDirectory() && !rhs.isDirectory()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(!lhs.isDirectory() && rhs.isDirectory()) {
|
} else if(!lhs.isDirectory() && rhs.isDirectory()) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if(lhs.isDirectory() && rhs.isDirectory()) {
|
} else if(lhs.isDirectory() && rhs.isDirectory()) {
|
||||||
if(byYear) {
|
if(byYear) {
|
||||||
Integer lhsYear = lhs.getYear();
|
Integer lhsYear = lhs.getYear();
|
||||||
Integer rhsYear = rhs.getYear();
|
Integer rhsYear = rhs.getYear();
|
||||||
if(lhsYear != null && rhsYear != null) {
|
if(lhsYear != null && rhsYear != null) {
|
||||||
return lhsYear.compareTo(rhsYear);
|
return lhsYear.compareTo(rhsYear);
|
||||||
} else if(lhsYear != null) {
|
} else if(lhsYear != null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rhsYear != null) {
|
} else if(rhsYear != null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return collator.compare(lhs.getAlbumDisplay(), rhs.getAlbumDisplay());
|
return collator.compare(lhs.getAlbumDisplay(), rhs.getAlbumDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer lhsDisc = lhs.getDiscNumber();
|
Integer lhsDisc = lhs.getDiscNumber();
|
||||||
Integer rhsDisc = rhs.getDiscNumber();
|
Integer rhsDisc = rhs.getDiscNumber();
|
||||||
|
|
||||||
if(lhsDisc != null && rhsDisc != null) {
|
if(lhsDisc != null && rhsDisc != null) {
|
||||||
if(lhsDisc < rhsDisc) {
|
if(lhsDisc < rhsDisc) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(lhsDisc > rhsDisc) {
|
} else if(lhsDisc > rhsDisc) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer lhsTrack = lhs.getTrack();
|
Integer lhsTrack = lhs.getTrack();
|
||||||
Integer rhsTrack = rhs.getTrack();
|
Integer rhsTrack = rhs.getTrack();
|
||||||
if(lhsTrack != null && rhsTrack != null && lhsTrack != rhsTrack) {
|
if(lhsTrack != null && rhsTrack != null && lhsTrack != rhsTrack) {
|
||||||
return lhsTrack.compareTo(rhsTrack);
|
return lhsTrack.compareTo(rhsTrack);
|
||||||
} else if(lhsTrack != null) {
|
} else if(lhsTrack != null) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rhsTrack != null) {
|
} else if(rhsTrack != null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return collator.compare(lhs.getTitle(), rhs.getTitle());
|
return collator.compare(lhs.getTitle(), rhs.getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(List<Entry> entries) {
|
public static void sort(List<Entry> entries) {
|
||||||
sort(entries, true);
|
sort(entries, true);
|
||||||
}
|
}
|
||||||
public static void sort(List<Entry> entries, boolean byYear) {
|
public static void sort(List<Entry> entries, boolean byYear) {
|
||||||
try {
|
try {
|
||||||
Collections.sort(entries, new EntryComparator(byYear));
|
Collections.sort(entries, new EntryComparator(byYear));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to sort MusicDirectory");
|
Log.w(TAG, "Failed to sort MusicDirectory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,49 +32,49 @@ import java.util.List;
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class MusicFolder implements Serializable {
|
public class MusicFolder implements Serializable {
|
||||||
private static final String TAG = MusicFolder.class.getSimpleName();
|
private static final String TAG = MusicFolder.class.getSimpleName();
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
public MusicFolder() {
|
public MusicFolder() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public MusicFolder(String id, String name) {
|
public MusicFolder(String id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
public boolean getEnabled() {
|
public boolean getEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MusicFolderComparator implements Comparator<MusicFolder> {
|
public static class MusicFolderComparator implements Comparator<MusicFolder> {
|
||||||
public int compare(MusicFolder lhsMusicFolder, MusicFolder rhsMusicFolder) {
|
public int compare(MusicFolder lhsMusicFolder, MusicFolder rhsMusicFolder) {
|
||||||
if(lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) {
|
if(lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return lhsMusicFolder.getName().compareToIgnoreCase(rhsMusicFolder.getName());
|
return lhsMusicFolder.getName().compareToIgnoreCase(rhsMusicFolder.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(List<MusicFolder> musicFolders) {
|
public static void sort(List<MusicFolder> musicFolders) {
|
||||||
try {
|
try {
|
||||||
Collections.sort(musicFolders, new MusicFolderComparator());
|
Collections.sort(musicFolders, new MusicFolderComparator());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to sort music folders", e);
|
Log.w(TAG, "Failed to sort music folders", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.domain;
|
package net.nullsum.audinaut.domain;
|
||||||
@ -21,10 +21,10 @@ import java.util.Date;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PlayerQueue implements Serializable {
|
public class PlayerQueue implements Serializable {
|
||||||
public List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
public List<MusicDirectory.Entry> songs = new ArrayList<MusicDirectory.Entry>();
|
||||||
public List<MusicDirectory.Entry> toDelete = new ArrayList<MusicDirectory.Entry>();
|
public List<MusicDirectory.Entry> toDelete = new ArrayList<MusicDirectory.Entry>();
|
||||||
public int currentPlayingIndex;
|
public int currentPlayingIndex;
|
||||||
public int currentPlayingPosition;
|
public int currentPlayingPosition;
|
||||||
public boolean renameCurrent = false;
|
public boolean renameCurrent = false;
|
||||||
public Date changed = null;
|
public Date changed = null;
|
||||||
}
|
}
|
||||||
|
@ -34,31 +34,31 @@ public class Playlist implements Serializable {
|
|||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String name;
|
private String name;
|
||||||
private String owner;
|
private String owner;
|
||||||
private String comment;
|
private String comment;
|
||||||
private String songCount;
|
private String songCount;
|
||||||
private Boolean pub;
|
private Boolean pub;
|
||||||
private Date created;
|
private Date created;
|
||||||
private Date changed;
|
private Date changed;
|
||||||
private Integer duration;
|
private Integer duration;
|
||||||
|
|
||||||
public Playlist() {
|
public Playlist() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public Playlist(String id, String name) {
|
public Playlist(String id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
public Playlist(String id, String name, String owner, String comment, String songCount, String pub, String created, String changed, Integer duration) {
|
public Playlist(String id, String name, String owner, String comment, String songCount, String pub, String created, String changed, Integer duration) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.owner = (owner == null) ? "" : owner;
|
this.owner = (owner == null) ? "" : owner;
|
||||||
this.comment = (comment == null) ? "" : comment;
|
this.comment = (comment == null) ? "" : comment;
|
||||||
this.songCount = (songCount == null) ? "" : songCount;
|
this.songCount = (songCount == null) ? "" : songCount;
|
||||||
this.pub = (pub == null) ? null : (pub.equals("true"));
|
this.pub = (pub == null) ? null : (pub.equals("true"));
|
||||||
setCreated(created);
|
setCreated(created);
|
||||||
setChanged(changed);
|
setChanged(changed);
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
@ -77,111 +77,111 @@ public class Playlist implements Serializable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOwner() {
|
public String getOwner() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOwner(String owner) {
|
public void setOwner(String owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getComment() {
|
public String getComment() {
|
||||||
return this.comment;
|
return this.comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComment(String comment) {
|
public void setComment(String comment) {
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSongCount() {
|
public String getSongCount() {
|
||||||
return this.songCount;
|
return this.songCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSongCount(String songCount) {
|
public void setSongCount(String songCount) {
|
||||||
this.songCount = songCount;
|
this.songCount = songCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getPublic() {
|
public Boolean getPublic() {
|
||||||
return this.pub;
|
return this.pub;
|
||||||
}
|
}
|
||||||
public void setPublic(Boolean pub) {
|
public void setPublic(Boolean pub) {
|
||||||
this.pub = pub;
|
this.pub = pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getCreated() {
|
public Date getCreated() {
|
||||||
return created;
|
return created;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCreated(String created) {
|
public void setCreated(String created) {
|
||||||
if (created != null) {
|
if (created != null) {
|
||||||
try {
|
try {
|
||||||
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
this.created = null;
|
this.created = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.created = null;
|
this.created = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void setCreated(Date created) {
|
public void setCreated(Date created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getChanged() {
|
public Date getChanged() {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
public void setChanged(String changed) {
|
public void setChanged(String changed) {
|
||||||
if (changed != null) {
|
if (changed != null) {
|
||||||
try {
|
try {
|
||||||
this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
|
this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
this.changed = null;
|
this.changed = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.changed = null;
|
this.changed = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void setChanged(Date changed) {
|
public void setChanged(Date changed) {
|
||||||
this.changed = changed;
|
this.changed = changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getDuration() {
|
public Integer getDuration() {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
public void setDuration(Integer duration) {
|
public void setDuration(Integer duration) {
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if(o == this) {
|
if(o == this) {
|
||||||
return true;
|
return true;
|
||||||
} else if(o == null) {
|
} else if(o == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if(o instanceof String) {
|
} else if(o instanceof String) {
|
||||||
return o.equals(this.id);
|
return o.equals(this.id);
|
||||||
} else if(o.getClass() != getClass()) {
|
} else if(o.getClass() != getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Playlist playlist = (Playlist) o;
|
Playlist playlist = (Playlist) o;
|
||||||
return playlist.id.equals(this.id);
|
return playlist.id.equals(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PlaylistComparator implements Comparator<Playlist> {
|
public static class PlaylistComparator implements Comparator<Playlist> {
|
||||||
@Override
|
@Override
|
||||||
public int compare(Playlist playlist1, Playlist playlist2) {
|
public int compare(Playlist playlist1, Playlist playlist2) {
|
||||||
return playlist1.getName().compareToIgnoreCase(playlist2.getName());
|
return playlist1.getName().compareToIgnoreCase(playlist2.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Playlist> sort(List<Playlist> playlists) {
|
public static List<Playlist> sort(List<Playlist> playlists) {
|
||||||
Collections.sort(playlists, new PlaylistComparator());
|
Collections.sort(playlists, new PlaylistComparator());
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,67 +27,67 @@ import java.util.regex.Pattern;
|
|||||||
*/
|
*/
|
||||||
public class SearchCritera {
|
public class SearchCritera {
|
||||||
|
|
||||||
private final String query;
|
private final String query;
|
||||||
private final int artistCount;
|
private final int artistCount;
|
||||||
private final int albumCount;
|
private final int albumCount;
|
||||||
private final int songCount;
|
private final int songCount;
|
||||||
private Pattern pattern;
|
private Pattern pattern;
|
||||||
|
|
||||||
public SearchCritera(String query, int artistCount, int albumCount, int songCount) {
|
public SearchCritera(String query, int artistCount, int albumCount, int songCount) {
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.artistCount = artistCount;
|
this.artistCount = artistCount;
|
||||||
this.albumCount = albumCount;
|
this.albumCount = albumCount;
|
||||||
this.songCount = songCount;
|
this.songCount = songCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getQuery() {
|
public String getQuery() {
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getArtistCount() {
|
public int getArtistCount() {
|
||||||
return artistCount;
|
return artistCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAlbumCount() {
|
public int getAlbumCount() {
|
||||||
return albumCount;
|
return albumCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSongCount() {
|
public int getSongCount() {
|
||||||
return songCount;
|
return songCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns and caches a pattern instance that can be used to check if a
|
* Returns and caches a pattern instance that can be used to check if a
|
||||||
* string matches the query.
|
* string matches the query.
|
||||||
*/
|
*/
|
||||||
public Pattern getPattern() {
|
public Pattern getPattern() {
|
||||||
|
|
||||||
// If the pattern wasn't already cached, create a new regular expression
|
// If the pattern wasn't already cached, create a new regular expression
|
||||||
// from the search string :
|
// from the search string :
|
||||||
// * Surround the search string with ".*" (match anything)
|
// * Surround the search string with ".*" (match anything)
|
||||||
// * Replace spaces and wildcard '*' characters with ".*"
|
// * Replace spaces and wildcard '*' characters with ".*"
|
||||||
// * All other characters are properly quoted
|
// * All other characters are properly quoted
|
||||||
if (this.pattern == null) {
|
if (this.pattern == null) {
|
||||||
String regex = ".*";
|
String regex = ".*";
|
||||||
String currentPart = "";
|
String currentPart = "";
|
||||||
for (int i = 0; i < query.length(); i++) {
|
for (int i = 0; i < query.length(); i++) {
|
||||||
char c = query.charAt(i);
|
char c = query.charAt(i);
|
||||||
if (c == '*' || c == ' ') {
|
if (c == '*' || c == ' ') {
|
||||||
regex += Pattern.quote(currentPart);
|
regex += Pattern.quote(currentPart);
|
||||||
regex += ".*";
|
regex += ".*";
|
||||||
currentPart = "";
|
currentPart = "";
|
||||||
} else {
|
} else {
|
||||||
currentPart += c;
|
currentPart += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentPart.length() > 0) {
|
if (currentPart.length() > 0) {
|
||||||
regex += Pattern.quote(currentPart);
|
regex += Pattern.quote(currentPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
regex += ".*";
|
regex += ".*";
|
||||||
this.pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
this.pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.pattern;
|
return this.pattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +50,13 @@ public class SearchResult implements Serializable {
|
|||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasArtists() {
|
public boolean hasArtists() {
|
||||||
return !artists.isEmpty();
|
return !artists.isEmpty();
|
||||||
}
|
}
|
||||||
public boolean hasAlbums() {
|
public boolean hasAlbums() {
|
||||||
return !albums.isEmpty();
|
return !albums.isEmpty();
|
||||||
}
|
}
|
||||||
public boolean hasSongs() {
|
public boolean hasSongs() {
|
||||||
return !songs.isEmpty();
|
return !songs.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.domain;
|
package net.nullsum.audinaut.domain;
|
||||||
@ -22,125 +22,125 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class User implements Serializable {
|
public class User implements Serializable {
|
||||||
public static final String ADMIN = "adminRole";
|
public static final String ADMIN = "adminRole";
|
||||||
public static final String SETTINGS = "settingsRole";
|
public static final String SETTINGS = "settingsRole";
|
||||||
public static final String DOWNLOAD = "downloadRole";
|
public static final String DOWNLOAD = "downloadRole";
|
||||||
public static final String UPLOAD = "uploadRole";
|
public static final String UPLOAD = "uploadRole";
|
||||||
public static final String COVERART = "coverArtRole";
|
public static final String COVERART = "coverArtRole";
|
||||||
public static final String COMMENT = "commentRole";
|
public static final String COMMENT = "commentRole";
|
||||||
public static final String STREAM = "streamRole";
|
public static final String STREAM = "streamRole";
|
||||||
public static final List<String> ROLES = new ArrayList<>();
|
public static final List<String> ROLES = new ArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ROLES.add(ADMIN);
|
ROLES.add(ADMIN);
|
||||||
ROLES.add(SETTINGS);
|
ROLES.add(SETTINGS);
|
||||||
ROLES.add(STREAM);
|
ROLES.add(STREAM);
|
||||||
ROLES.add(DOWNLOAD);
|
ROLES.add(DOWNLOAD);
|
||||||
ROLES.add(UPLOAD);
|
ROLES.add(UPLOAD);
|
||||||
ROLES.add(COVERART);
|
ROLES.add(COVERART);
|
||||||
ROLES.add(COMMENT);
|
ROLES.add(COMMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String username;
|
private String username;
|
||||||
private String password;
|
private String password;
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
private List<Setting> settings = new ArrayList<Setting>();
|
private List<Setting> settings = new ArrayList<Setting>();
|
||||||
private List<Setting> musicFolders;
|
private List<Setting> musicFolders;
|
||||||
|
|
||||||
public User() {
|
public User() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsername(String username) {
|
public void setUsername(String username) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Setting> getSettings() {
|
public List<Setting> getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
public void setSettings(List<Setting> settings) {
|
public void setSettings(List<Setting> settings) {
|
||||||
this.settings.clear();
|
this.settings.clear();
|
||||||
this.settings.addAll(settings);
|
this.settings.addAll(settings);
|
||||||
}
|
}
|
||||||
public void addSetting(String name, Boolean value) {
|
public void addSetting(String name, Boolean value) {
|
||||||
settings.add(new Setting(name, value));
|
settings.add(new Setting(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addMusicFolder(MusicFolder musicFolder) {
|
public void addMusicFolder(MusicFolder musicFolder) {
|
||||||
if(musicFolders == null) {
|
if(musicFolders == null) {
|
||||||
musicFolders = new ArrayList<>();
|
musicFolders = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName(), false));
|
musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName(), false));
|
||||||
}
|
}
|
||||||
public void addMusicFolder(MusicFolderSetting musicFolderSetting, boolean defaultValue) {
|
public void addMusicFolder(MusicFolderSetting musicFolderSetting, boolean defaultValue) {
|
||||||
if(musicFolders == null) {
|
if(musicFolders == null) {
|
||||||
musicFolders = new ArrayList<>();
|
musicFolders = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
musicFolders.add(new MusicFolderSetting(musicFolderSetting.getName(), musicFolderSetting.getLabel(), defaultValue));
|
musicFolders.add(new MusicFolderSetting(musicFolderSetting.getName(), musicFolderSetting.getLabel(), defaultValue));
|
||||||
}
|
}
|
||||||
public List<Setting> getMusicFolderSettings() {
|
public List<Setting> getMusicFolderSettings() {
|
||||||
return musicFolders;
|
return musicFolders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Setting implements Serializable {
|
public static class Setting implements Serializable {
|
||||||
private String name;
|
private String name;
|
||||||
private Boolean value;
|
private Boolean value;
|
||||||
|
|
||||||
public Setting() {
|
public Setting() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public Setting(String name, Boolean value) {
|
public Setting(String name, Boolean value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
public Boolean getValue() {
|
public Boolean getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
public void setValue(Boolean value) {
|
public void setValue(Boolean value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MusicFolderSetting extends Setting {
|
public static class MusicFolderSetting extends Setting {
|
||||||
private String label;
|
private String label;
|
||||||
|
|
||||||
public MusicFolderSetting() {
|
public MusicFolderSetting() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public MusicFolderSetting(String name, String label, Boolean value) {
|
public MusicFolderSetting(String name, String label, Boolean value) {
|
||||||
super(name, value);
|
super(name, value);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
@ -46,145 +46,145 @@ import net.nullsum.audinaut.adapter.DownloadFileAdapter;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> implements SectionAdapter.OnItemClickedListener<DownloadFile> {
|
public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> implements SectionAdapter.OnItemClickedListener<DownloadFile> {
|
||||||
private long currentRevision;
|
private long currentRevision;
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
|
|
||||||
public DownloadFragment() {
|
public DownloadFragment() {
|
||||||
serialize = false;
|
serialize = false;
|
||||||
pullToRefresh = false;
|
pullToRefresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
super.onCreateView(inflater, container, bundle);
|
super.onCreateView(inflater, container, bundle);
|
||||||
|
|
||||||
ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, false));
|
ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, false));
|
||||||
touchHelper.attachToRecyclerView(recyclerView);
|
touchHelper.attachToRecyclerView(recyclerView);
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
final Handler handler = new Handler();
|
final Handler handler = new Handler();
|
||||||
Runnable runnable = new Runnable() {
|
Runnable runnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS);
|
executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return R.menu.downloading;
|
return R.menu.downloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter getAdapter(List<DownloadFile> objs) {
|
public SectionAdapter getAdapter(List<DownloadFile> objs) {
|
||||||
return new DownloadFileAdapter(context, objs, this);
|
return new DownloadFileAdapter(context, objs, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DownloadFile> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<DownloadFile> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService == null) {
|
if(downloadService == null) {
|
||||||
return new ArrayList<DownloadFile>();
|
return new ArrayList<DownloadFile>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DownloadFile> songList = new ArrayList<DownloadFile>();
|
List<DownloadFile> songList = new ArrayList<DownloadFile>();
|
||||||
songList.addAll(downloadService.getBackgroundDownloads());
|
songList.addAll(downloadService.getBackgroundDownloads());
|
||||||
currentRevision = downloadService.getDownloadListUpdateRevision();
|
currentRevision = downloadService.getDownloadListUpdateRevision();
|
||||||
return songList;
|
return songList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return R.string.button_bar_downloading;
|
return R.string.button_bar_downloading;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<DownloadFile> updateView, DownloadFile item) {
|
public void onItemClicked(UpdateView<DownloadFile> updateView, DownloadFile item) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
||||||
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, selectedItem);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, selectedItem);
|
||||||
if(!Util.isOffline(context)) {
|
if(!Util.isOffline(context)) {
|
||||||
menu.removeItem(R.id.song_menu_remove_playlist);
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<DownloadFile> updateView, DownloadFile downloadFile) {
|
||||||
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
MusicDirectory.Entry selectedItem = downloadFile.getSong();
|
||||||
return onContextItemSelected(menuItem, selectedItem);
|
return onContextItemSelected(menuItem, selectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
public boolean onOptionsItemSelected(MenuItem menuItem) {
|
||||||
if(super.onOptionsItemSelected(menuItem)) {
|
if(super.onOptionsItemSelected(menuItem)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.menu_remove_all:
|
case R.id.menu_remove_all:
|
||||||
Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() {
|
Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
getDownloadService().clearBackground();
|
getDownloadService().clearBackground();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update() {
|
private void update() {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if (downloadService == null || objects == null || adapter == null) {
|
if (downloadService == null || objects == null || adapter == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRevision != downloadService.getDownloadListUpdateRevision()) {
|
if (currentRevision != downloadService.getDownloadListUpdateRevision()) {
|
||||||
List<DownloadFile> downloadFileList = downloadService.getBackgroundDownloads();
|
List<DownloadFile> downloadFileList = downloadService.getBackgroundDownloads();
|
||||||
objects.clear();
|
objects.clear();
|
||||||
objects.addAll(downloadFileList);
|
objects.addAll(downloadFileList);
|
||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
|
|
||||||
currentRevision = downloadService.getDownloadListUpdateRevision();
|
currentRevision = downloadService.getDownloadListUpdateRevision();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,412 +48,412 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
* Created by Scott on 10/27/13.
|
* Created by Scott on 10/27/13.
|
||||||
*/
|
*/
|
||||||
public class EqualizerFragment extends SubsonicFragment {
|
public class EqualizerFragment extends SubsonicFragment {
|
||||||
private static final String TAG = EqualizerFragment.class.getSimpleName();
|
private static final String TAG = EqualizerFragment.class.getSimpleName();
|
||||||
|
|
||||||
private static final int MENU_GROUP_PRESET = 100;
|
private static final int MENU_GROUP_PRESET = 100;
|
||||||
|
|
||||||
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
private final Map<Short, SeekBar> bars = new HashMap<Short, SeekBar>();
|
||||||
private SeekBar bassBar;
|
private SeekBar bassBar;
|
||||||
private SeekBar loudnessBar;
|
private SeekBar loudnessBar;
|
||||||
private EqualizerController equalizerController;
|
private EqualizerController equalizerController;
|
||||||
private Equalizer equalizer;
|
private Equalizer equalizer;
|
||||||
private BassBoost bass;
|
private BassBoost bass;
|
||||||
private LoudnessEnhancerController loudnessEnhancer;
|
private LoudnessEnhancerController loudnessEnhancer;
|
||||||
private short masterLevel = 0;
|
private short masterLevel = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
rootView = inflater.inflate(R.layout.equalizer, container, false);
|
rootView = inflater.inflate(R.layout.equalizer, container, false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DownloadService service = DownloadService.getInstance();
|
DownloadService service = DownloadService.getInstance();
|
||||||
equalizerController = service.getEqualizerController();
|
equalizerController = service.getEqualizerController();
|
||||||
equalizer = equalizerController.getEqualizer();
|
equalizer = equalizerController.getEqualizer();
|
||||||
bass = equalizerController.getBassBoost();
|
bass = equalizerController.getBassBoost();
|
||||||
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
||||||
|
|
||||||
initEqualizer();
|
initEqualizer();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to initialize EQ", e);
|
Log.e(TAG, "Failed to initialize EQ", e);
|
||||||
Util.toast(context, "Failed to initialize EQ");
|
Util.toast(context, "Failed to initialize EQ");
|
||||||
context.onBackPressed();
|
context.onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
final View presetButton = rootView.findViewById(R.id.equalizer_preset);
|
final View presetButton = rootView.findViewById(R.id.equalizer_preset);
|
||||||
registerForContextMenu(presetButton);
|
registerForContextMenu(presetButton);
|
||||||
presetButton.setOnClickListener(new View.OnClickListener() {
|
presetButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
presetButton.showContextMenu();
|
presetButton.showContextMenu();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CheckBox enabledCheckBox = (CheckBox) rootView.findViewById(R.id.equalizer_enabled);
|
CheckBox enabledCheckBox = (CheckBox) rootView.findViewById(R.id.equalizer_enabled);
|
||||||
enabledCheckBox.setChecked(equalizer.getEnabled());
|
enabledCheckBox.setChecked(equalizer.getEnabled());
|
||||||
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
||||||
try {
|
try {
|
||||||
setEqualizerEnabled(b);
|
setEqualizerEnabled(b);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to set EQ enabled", e);
|
Log.e(TAG, "Failed to set EQ enabled", e);
|
||||||
Util.toast(context, "Failed to set EQ enabled");
|
Util.toast(context, "Failed to set EQ enabled");
|
||||||
context.onBackPressed();
|
context.onBackPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setTitle(R.string.equalizer_label);
|
setTitle(R.string.equalizer_label);
|
||||||
setSubtitle(null);
|
setSubtitle(null);
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
equalizerController.saveSettings();
|
equalizerController.saveSettings();
|
||||||
|
|
||||||
if (!equalizer.getEnabled()) {
|
if (!equalizer.getEnabled()) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to release controller", e);
|
Log.w(TAG, "Failed to release controller", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
equalizerController = DownloadService.getInstance().getEqualizerController();
|
equalizerController = DownloadService.getInstance().getEqualizerController();
|
||||||
equalizer = equalizerController.getEqualizer();
|
equalizer = equalizerController.getEqualizer();
|
||||||
bass = equalizerController.getBassBoost();
|
bass = equalizerController.getBassBoost();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
super.onCreateContextMenu(menu, view, menuInfo);
|
super.onCreateContextMenu(menu, view, menuInfo);
|
||||||
if(!primaryFragment) {
|
if(!primaryFragment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
short currentPreset;
|
short currentPreset;
|
||||||
try {
|
try {
|
||||||
currentPreset = equalizer.getCurrentPreset();
|
currentPreset = equalizer.getCurrentPreset();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
currentPreset = -1;
|
currentPreset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++) {
|
for (short preset = 0; preset < equalizer.getNumberOfPresets(); preset++) {
|
||||||
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
MenuItem menuItem = menu.add(MENU_GROUP_PRESET, preset, preset, equalizer.getPresetName(preset));
|
||||||
if (preset == currentPreset) {
|
if (preset == currentPreset) {
|
||||||
menuItem.setChecked(true);
|
menuItem.setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
menu.setGroupCheckable(MENU_GROUP_PRESET, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem) {
|
public boolean onContextItemSelected(MenuItem menuItem) {
|
||||||
short preset = (short) menuItem.getItemId();
|
short preset = (short) menuItem.getItemId();
|
||||||
for(int i = 0; i < 10; i++) {
|
for(int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
equalizer.usePreset(preset);
|
equalizer.usePreset(preset);
|
||||||
i = 10;
|
i = 10;
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
equalizer = equalizerController.getEqualizer();
|
equalizer = equalizerController.getEqualizer();
|
||||||
bass = equalizerController.getBassBoost();
|
bass = equalizerController.getBassBoost();
|
||||||
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateBars(false);
|
updateBars(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEqualizerEnabled(boolean enabled) {
|
private void setEqualizerEnabled(boolean enabled) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled);
|
editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
for(int i = 0; i < 10; i++) {
|
for(int i = 0; i < 10; i++) {
|
||||||
try {
|
try {
|
||||||
equalizer.setEnabled(enabled);
|
equalizer.setEnabled(enabled);
|
||||||
updateBars(true);
|
updateBars(true);
|
||||||
i = 10;
|
i = 10;
|
||||||
} catch (UnsupportedOperationException e) {
|
} catch (UnsupportedOperationException e) {
|
||||||
equalizerController.release();
|
equalizerController.release();
|
||||||
equalizer = equalizerController.getEqualizer();
|
equalizer = equalizerController.getEqualizer();
|
||||||
bass = equalizerController.getBassBoost();
|
bass = equalizerController.getBassBoost();
|
||||||
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
loudnessEnhancer = equalizerController.getLoudnessEnhancerController();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBars(boolean changedEnabled) {
|
private void updateBars(boolean changedEnabled) {
|
||||||
try {
|
try {
|
||||||
boolean isEnabled = equalizer.getEnabled();
|
boolean isEnabled = equalizer.getEnabled();
|
||||||
short minEQLevel = equalizer.getBandLevelRange()[0];
|
short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||||
short maxEQLevel = equalizer.getBandLevelRange()[1];
|
short maxEQLevel = equalizer.getBandLevelRange()[1];
|
||||||
for (Map.Entry<Short, SeekBar> entry : bars.entrySet()) {
|
for (Map.Entry<Short, SeekBar> entry : bars.entrySet()) {
|
||||||
short band = entry.getKey();
|
short band = entry.getKey();
|
||||||
SeekBar bar = entry.getValue();
|
SeekBar bar = entry.getValue();
|
||||||
bar.setEnabled(isEnabled);
|
bar.setEnabled(isEnabled);
|
||||||
if (band >= (short) 0) {
|
if (band >= (short) 0) {
|
||||||
short setLevel;
|
short setLevel;
|
||||||
if (changedEnabled) {
|
if (changedEnabled) {
|
||||||
setLevel = (short) (equalizer.getBandLevel(band) - masterLevel);
|
setLevel = (short) (equalizer.getBandLevel(band) - masterLevel);
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||||
} else {
|
} else {
|
||||||
bar.setProgress(-minEQLevel);
|
bar.setProgress(-minEQLevel);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
bar.setProgress(equalizer.getBandLevel(band) - minEQLevel);
|
||||||
setLevel = (short) (equalizer.getBandLevel(band) + masterLevel);
|
setLevel = (short) (equalizer.getBandLevel(band) + masterLevel);
|
||||||
}
|
}
|
||||||
if (setLevel < minEQLevel) {
|
if (setLevel < minEQLevel) {
|
||||||
setLevel = minEQLevel;
|
setLevel = minEQLevel;
|
||||||
} else if (setLevel > maxEQLevel) {
|
} else if (setLevel > maxEQLevel) {
|
||||||
setLevel = maxEQLevel;
|
setLevel = maxEQLevel;
|
||||||
}
|
}
|
||||||
equalizer.setBandLevel(band, setLevel);
|
equalizer.setBandLevel(band, setLevel);
|
||||||
} else if (!isEnabled) {
|
} else if (!isEnabled) {
|
||||||
bar.setProgress(-minEQLevel);
|
bar.setProgress(-minEQLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bassBar.setEnabled(isEnabled);
|
bassBar.setEnabled(isEnabled);
|
||||||
if (loudnessBar != null) {
|
if (loudnessBar != null) {
|
||||||
loudnessBar.setEnabled(isEnabled);
|
loudnessBar.setEnabled(isEnabled);
|
||||||
}
|
}
|
||||||
if (changedEnabled && !isEnabled) {
|
if (changedEnabled && !isEnabled) {
|
||||||
bass.setStrength((short) 0);
|
bass.setStrength((short) 0);
|
||||||
bassBar.setProgress(0);
|
bassBar.setProgress(0);
|
||||||
if (loudnessBar != null) {
|
if (loudnessBar != null) {
|
||||||
loudnessEnhancer.setGain(0);
|
loudnessEnhancer.setGain(0);
|
||||||
loudnessBar.setProgress(0);
|
loudnessBar.setProgress(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
masterLevel = 0;
|
masterLevel = 0;
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to update bars");
|
Log.e(TAG, "Failed to update bars");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initEqualizer() {
|
private void initEqualizer() {
|
||||||
LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.equalizer_layout);
|
LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.equalizer_layout);
|
||||||
|
|
||||||
final short minEQLevel = equalizer.getBandLevelRange()[0];
|
final short minEQLevel = equalizer.getBandLevelRange()[0];
|
||||||
final short maxEQLevel = equalizer.getBandLevelRange()[1];
|
final short maxEQLevel = equalizer.getBandLevelRange()[1];
|
||||||
|
|
||||||
// Setup Pregain
|
// Setup Pregain
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0);
|
masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0);
|
||||||
initPregain(layout, minEQLevel, maxEQLevel);
|
initPregain(layout, minEQLevel, maxEQLevel);
|
||||||
|
|
||||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
||||||
final short band = i;
|
final short band = i;
|
||||||
|
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz");
|
||||||
|
|
||||||
bars.put(band, bar);
|
bars.put(band, bar);
|
||||||
bar.setMax(maxEQLevel - minEQLevel);
|
bar.setMax(maxEQLevel - minEQLevel);
|
||||||
short level = equalizer.getBandLevel(band);
|
short level = equalizer.getBandLevel(band);
|
||||||
if(equalizer.getEnabled()) {
|
if(equalizer.getEnabled()) {
|
||||||
level = (short) (level - masterLevel);
|
level = (short) (level - masterLevel);
|
||||||
}
|
}
|
||||||
bar.setProgress(level - minEQLevel);
|
bar.setProgress(level - minEQLevel);
|
||||||
bar.setEnabled(equalizer.getEnabled());
|
bar.setEnabled(equalizer.getEnabled());
|
||||||
updateLevelText(levelTextView, level);
|
updateLevelText(levelTextView, level);
|
||||||
|
|
||||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
try {
|
try {
|
||||||
short level = (short) (progress + minEQLevel);
|
short level = (short) (progress + minEQLevel);
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
equalizer.setBandLevel(band, (short) (level + masterLevel));
|
equalizer.setBandLevel(band, (short) (level + masterLevel));
|
||||||
}
|
}
|
||||||
updateLevelText(levelTextView, level);
|
updateLevelText(levelTextView, level);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to change equalizer", e);
|
Log.e(TAG, "Failed to change equalizer", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
layout.addView(bandBar);
|
layout.addView(bandBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearLayout specialLayout = (LinearLayout) rootView.findViewById(R.id.special_effects_layout);
|
LinearLayout specialLayout = (LinearLayout) rootView.findViewById(R.id.special_effects_layout);
|
||||||
|
|
||||||
// Setup bass booster
|
// Setup bass booster
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView bassTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView bassTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||||
bassBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
bassBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText(R.string.equalizer_bass_booster);
|
freqTextView.setText(R.string.equalizer_bass_booster);
|
||||||
bassBar.setEnabled(equalizer.getEnabled());
|
bassBar.setEnabled(equalizer.getEnabled());
|
||||||
short bassLevel = 0;
|
short bassLevel = 0;
|
||||||
if(bass.getEnabled()) {
|
if(bass.getEnabled()) {
|
||||||
bassLevel = bass.getRoundedStrength();
|
bassLevel = bass.getRoundedStrength();
|
||||||
}
|
}
|
||||||
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel));
|
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel));
|
||||||
bassBar.setMax(1000);
|
bassBar.setMax(1000);
|
||||||
bassBar.setProgress(bassLevel);
|
bassBar.setProgress(bassLevel);
|
||||||
bassBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
bassBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
try {
|
try {
|
||||||
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, progress));
|
bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, progress));
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
if (progress > 0) {
|
if (progress > 0) {
|
||||||
if (!bass.getEnabled()) {
|
if (!bass.getEnabled()) {
|
||||||
bass.setEnabled(true);
|
bass.setEnabled(true);
|
||||||
}
|
}
|
||||||
bass.setStrength((short) progress);
|
bass.setStrength((short) progress);
|
||||||
} else if (progress == 0 && bass.getEnabled()) {
|
} else if (progress == 0 && bass.getEnabled()) {
|
||||||
bass.setStrength((short) progress);
|
bass.setStrength((short) progress);
|
||||||
bass.setEnabled(false);
|
bass.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Error on changing bass: ", e);
|
Log.w(TAG, "Error on changing bass: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
specialLayout.addView(bandBar);
|
specialLayout.addView(bandBar);
|
||||||
|
|
||||||
if(loudnessEnhancer != null && loudnessEnhancer.isAvailable()) {
|
if(loudnessEnhancer != null && loudnessEnhancer.isAvailable()) {
|
||||||
// Setup loudness enhancer
|
// Setup loudness enhancer
|
||||||
bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView loudnessTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView loudnessTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||||
loudnessBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
loudnessBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText(R.string.equalizer_voice_booster);
|
freqTextView.setText(R.string.equalizer_voice_booster);
|
||||||
loudnessBar.setEnabled(equalizer.getEnabled());
|
loudnessBar.setEnabled(equalizer.getEnabled());
|
||||||
int loudnessLevel = 0;
|
int loudnessLevel = 0;
|
||||||
if(loudnessEnhancer.isEnabled()) {
|
if(loudnessEnhancer.isEnabled()) {
|
||||||
loudnessLevel = (int) loudnessEnhancer.getGain();
|
loudnessLevel = (int) loudnessEnhancer.getGain();
|
||||||
}
|
}
|
||||||
loudnessBar.setProgress(loudnessLevel / 100);
|
loudnessBar.setProgress(loudnessLevel / 100);
|
||||||
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, loudnessLevel / 100));
|
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, loudnessLevel / 100));
|
||||||
loudnessBar.setMax(15);
|
loudnessBar.setMax(15);
|
||||||
loudnessBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
loudnessBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
try {
|
try {
|
||||||
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress));
|
loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress));
|
||||||
if(fromUser) {
|
if(fromUser) {
|
||||||
if(progress > 0) {
|
if(progress > 0) {
|
||||||
if(!loudnessEnhancer.isEnabled()) {
|
if(!loudnessEnhancer.isEnabled()) {
|
||||||
loudnessEnhancer.enable();
|
loudnessEnhancer.enable();
|
||||||
}
|
}
|
||||||
loudnessEnhancer.setGain(progress * 100);
|
loudnessEnhancer.setGain(progress * 100);
|
||||||
} else if(progress == 0 && loudnessEnhancer.isEnabled()) {
|
} else if(progress == 0 && loudnessEnhancer.isEnabled()) {
|
||||||
loudnessEnhancer.setGain(progress * 100);
|
loudnessEnhancer.setGain(progress * 100);
|
||||||
loudnessEnhancer.disable();
|
loudnessEnhancer.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Error on changing loudness: ", e);
|
Log.w(TAG, "Error on changing loudness: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
specialLayout.addView(bandBar);
|
specialLayout.addView(bandBar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
|
private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) {
|
||||||
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null);
|
||||||
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency);
|
||||||
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level);
|
||||||
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar);
|
||||||
|
|
||||||
freqTextView.setText("Master");
|
freqTextView.setText("Master");
|
||||||
|
|
||||||
bars.put((short)-1, bar);
|
bars.put((short)-1, bar);
|
||||||
bar.setMax(maxEQLevel - minEQLevel);
|
bar.setMax(maxEQLevel - minEQLevel);
|
||||||
bar.setProgress(masterLevel - minEQLevel);
|
bar.setProgress(masterLevel - minEQLevel);
|
||||||
bar.setEnabled(equalizer.getEnabled());
|
bar.setEnabled(equalizer.getEnabled());
|
||||||
updateLevelText(levelTextView, masterLevel);
|
updateLevelText(levelTextView, masterLevel);
|
||||||
|
|
||||||
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
bar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
try {
|
try {
|
||||||
masterLevel = (short) (progress + minEQLevel);
|
masterLevel = (short) (progress + minEQLevel);
|
||||||
if (fromUser) {
|
if (fromUser) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
for (short i = 0; i < equalizer.getNumberOfBands(); i++) {
|
||||||
short level = (short) ((bars.get(i).getProgress() + minEQLevel) + masterLevel);
|
short level = (short) ((bars.get(i).getProgress() + minEQLevel) + masterLevel);
|
||||||
equalizer.setBandLevel(i, level);
|
equalizer.setBandLevel(i, level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateLevelText(levelTextView, masterLevel);
|
updateLevelText(levelTextView, masterLevel);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.e(TAG, "Failed to change equalizer", e);
|
Log.e(TAG, "Failed to change equalizer", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
layout.addView(bandBar);
|
layout.addView(bandBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLevelText(TextView levelTextView, short level) {
|
private void updateLevelText(TextView levelTextView, short level) {
|
||||||
levelTextView.setText((level > 0 ? "+" : "") + context.getResources().getString(R.string.equalizer_db_size, level / 100));
|
levelTextView.setText((level > 0 ? "+" : "") + context.getResources().getString(R.string.equalizer_db_size, level / 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,179 +42,179 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class MainFragment extends SelectRecyclerFragment<Integer> {
|
public class MainFragment extends SelectRecyclerFragment<Integer> {
|
||||||
private static final String TAG = MainFragment.class.getSimpleName();
|
private static final String TAG = MainFragment.class.getSimpleName();
|
||||||
public static final String SONGS_LIST_PREFIX = "songs-";
|
public static final String SONGS_LIST_PREFIX = "songs-";
|
||||||
public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest";
|
public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest";
|
||||||
public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed";
|
public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed";
|
||||||
public static final String SONGS_RECENT = SONGS_LIST_PREFIX + "recent";
|
public static final String SONGS_RECENT = SONGS_LIST_PREFIX + "recent";
|
||||||
public static final String SONGS_FREQUENT = SONGS_LIST_PREFIX + "frequent";
|
public static final String SONGS_FREQUENT = SONGS_LIST_PREFIX + "frequent";
|
||||||
|
|
||||||
public MainFragment() {
|
public MainFragment() {
|
||||||
super();
|
super();
|
||||||
pullToRefresh = false;
|
pullToRefresh = false;
|
||||||
serialize = false;
|
serialize = false;
|
||||||
backgroundUpdate = false;
|
backgroundUpdate = false;
|
||||||
alwaysFullscreen = true;
|
alwaysFullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
menuInflater.inflate(R.menu.main, menu);
|
menuInflater.inflate(R.menu.main, menu);
|
||||||
onFinishSetupOptionsMenu(menu);
|
onFinishSetupOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(super.onOptionsItemSelected(item)) {
|
if(super.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter getAdapter(List objs) {
|
public SectionAdapter getAdapter(List objs) {
|
||||||
List<List<Integer>> sections = new ArrayList<>();
|
List<List<Integer>> sections = new ArrayList<>();
|
||||||
List<String> headers = new ArrayList<>();
|
List<String> headers = new ArrayList<>();
|
||||||
|
|
||||||
List<Integer> albums = new ArrayList<>();
|
List<Integer> albums = new ArrayList<>();
|
||||||
albums.add(R.string.main_albums_random);
|
albums.add(R.string.main_albums_random);
|
||||||
albums.add(R.string.main_albums_alphabetical);
|
albums.add(R.string.main_albums_alphabetical);
|
||||||
albums.add(R.string.main_albums_genres);
|
albums.add(R.string.main_albums_genres);
|
||||||
albums.add(R.string.main_albums_year);
|
albums.add(R.string.main_albums_year);
|
||||||
albums.add(R.string.main_albums_recent);
|
albums.add(R.string.main_albums_recent);
|
||||||
albums.add(R.string.main_albums_frequent);
|
albums.add(R.string.main_albums_frequent);
|
||||||
|
|
||||||
sections.add(albums);
|
sections.add(albums);
|
||||||
headers.add("albums");
|
headers.add("albums");
|
||||||
|
|
||||||
return new MainAdapter(context, headers, sections, this);
|
return new MainAdapter(context, headers, sections, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Integer> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
return Arrays.asList(0);
|
return Arrays.asList(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return R.string.common_appname;
|
return R.string.common_appname;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showAlbumList(String type) {
|
private void showAlbumList(String type) {
|
||||||
if("genres".equals(type)) {
|
if("genres".equals(type)) {
|
||||||
SubsonicFragment fragment = new SelectGenreFragment();
|
SubsonicFragment fragment = new SelectGenreFragment();
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
} else if("years".equals(type)) {
|
} else if("years".equals(type)) {
|
||||||
SubsonicFragment fragment = new SelectYearFragment();
|
SubsonicFragment fragment = new SelectYearFragment();
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
} else {
|
} else {
|
||||||
// Clear out recently added count when viewing
|
// Clear out recently added count when viewing
|
||||||
if("newest".equals(type)) {
|
if("newest".equals(type)) {
|
||||||
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
||||||
editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
|
editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, type);
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showAboutDialog() {
|
private void showAboutDialog() {
|
||||||
new LoadingTask<Void>(context) {
|
new LoadingTask<Void>(context) {
|
||||||
Long[] used;
|
Long[] used;
|
||||||
long bytesTotalFs;
|
long bytesTotalFs;
|
||||||
long bytesAvailableFs;
|
long bytesAvailableFs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
File rootFolder = FileUtil.getMusicDirectory(context);
|
File rootFolder = FileUtil.getMusicDirectory(context);
|
||||||
StatFs stat = new StatFs(rootFolder.getPath());
|
StatFs stat = new StatFs(rootFolder.getPath());
|
||||||
bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
||||||
bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
||||||
|
|
||||||
used = FileUtil.getUsedSize(context, rootFolder);
|
used = FileUtil.getUsedSize(context, rootFolder);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
List<Integer> headers = new ArrayList<>();
|
List<Integer> headers = new ArrayList<>();
|
||||||
List<String> details = new ArrayList<>();
|
List<String> details = new ArrayList<>();
|
||||||
|
|
||||||
headers.add(R.string.details_author);
|
headers.add(R.string.details_author);
|
||||||
details.add("Andrew Rabert");
|
details.add("Andrew Rabert");
|
||||||
|
|
||||||
headers.add(R.string.details_email);
|
headers.add(R.string.details_email);
|
||||||
details.add("ar@nullsum.net");
|
details.add("ar@nullsum.net");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
headers.add(R.string.details_version);
|
headers.add(R.string.details_version);
|
||||||
details.add(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName);
|
details.add(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
details.add("");
|
details.add("");
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
headers.add(R.string.details_files_cached);
|
headers.add(R.string.details_files_cached);
|
||||||
details.add(Long.toString(used[0]));
|
details.add(Long.toString(used[0]));
|
||||||
|
|
||||||
headers.add(R.string.details_files_permanent);
|
headers.add(R.string.details_files_permanent);
|
||||||
details.add(Long.toString(used[1]));
|
details.add(Long.toString(used[1]));
|
||||||
|
|
||||||
headers.add(R.string.details_used_space);
|
headers.add(R.string.details_used_space);
|
||||||
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(used[2], context), Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context)));
|
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(used[2], context), Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context)));
|
||||||
|
|
||||||
headers.add(R.string.details_available_space);
|
headers.add(R.string.details_available_space);
|
||||||
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(bytesAvailableFs, context), Util.formatLocalizedBytes(bytesTotalFs, context)));
|
details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(bytesAvailableFs, context), Util.formatLocalizedBytes(bytesTotalFs, context)));
|
||||||
|
|
||||||
Util.showDetailsDialog(context, R.string.main_about_title, headers, details);
|
Util.showDetailsDialog(context, R.string.main_about_title, headers, details);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Integer> updateView, Integer item) {
|
public void onItemClicked(UpdateView<Integer> updateView, Integer item) {
|
||||||
if (item == R.string.main_albums_random) {
|
if (item == R.string.main_albums_random) {
|
||||||
showAlbumList("random");
|
showAlbumList("random");
|
||||||
} else if (item == R.string.main_albums_recent) {
|
} else if (item == R.string.main_albums_recent) {
|
||||||
showAlbumList("recent");
|
showAlbumList("recent");
|
||||||
} else if (item == R.string.main_albums_frequent) {
|
} else if (item == R.string.main_albums_frequent) {
|
||||||
showAlbumList("frequent");
|
showAlbumList("frequent");
|
||||||
} else if(item == R.string.main_albums_genres) {
|
} else if(item == R.string.main_albums_genres) {
|
||||||
showAlbumList("genres");
|
showAlbumList("genres");
|
||||||
} else if(item == R.string.main_albums_year) {
|
} else if(item == R.string.main_albums_year) {
|
||||||
showAlbumList("years");
|
showAlbumList("years");
|
||||||
} else if(item == R.string.main_albums_alphabetical) {
|
} else if(item == R.string.main_albums_alphabetical) {
|
||||||
showAlbumList("alphabeticalByName");
|
showAlbumList("alphabeticalByName");
|
||||||
} else if (item == R.string.main_songs_newest) {
|
} else if (item == R.string.main_songs_newest) {
|
||||||
showAlbumList(SONGS_NEWEST);
|
showAlbumList(SONGS_NEWEST);
|
||||||
} else if (item == R.string.main_songs_top_played) {
|
} else if (item == R.string.main_songs_top_played) {
|
||||||
showAlbumList(SONGS_TOP_PLAYED);
|
showAlbumList(SONGS_TOP_PLAYED);
|
||||||
} else if (item == R.string.main_songs_recent) {
|
} else if (item == R.string.main_songs_recent) {
|
||||||
showAlbumList(SONGS_RECENT);
|
showAlbumList(SONGS_RECENT);
|
||||||
} else if (item == R.string.main_songs_frequent) {
|
} else if (item == R.string.main_songs_frequent) {
|
||||||
showAlbumList(SONGS_FREQUENT);
|
showAlbumList(SONGS_FREQUENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Integer> updateView, Integer item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Integer> updateView, Integer item) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Integer> updateView, Integer item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Integer> updateView, Integer item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
@ -42,293 +42,293 @@ import net.nullsum.audinaut.R;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
||||||
private static final String TAG = PreferenceCompatFragment.class.getSimpleName();
|
private static final String TAG = PreferenceCompatFragment.class.getSimpleName();
|
||||||
private static final int FIRST_REQUEST_CODE = 100;
|
private static final int FIRST_REQUEST_CODE = 100;
|
||||||
private static final int MSG_BIND_PREFERENCES = 1;
|
private static final int MSG_BIND_PREFERENCES = 1;
|
||||||
private static final String PREFERENCES_TAG = "android:preferences";
|
private static final String PREFERENCES_TAG = "android:preferences";
|
||||||
private boolean mHavePrefs;
|
private boolean mHavePrefs;
|
||||||
private boolean mInitDone;
|
private boolean mInitDone;
|
||||||
private ListView mList;
|
private ListView mList;
|
||||||
private PreferenceManager mPreferenceManager;
|
private PreferenceManager mPreferenceManager;
|
||||||
|
|
||||||
private Handler mHandler = new Handler() {
|
private Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
|
||||||
case MSG_BIND_PREFERENCES:
|
case MSG_BIND_PREFERENCES:
|
||||||
bindPreferences();
|
bindPreferences();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final private Runnable mRequestFocus = new Runnable() {
|
final private Runnable mRequestFocus = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
mList.focusableViewAvailable(mList);
|
mList.focusableViewAvailable(mList);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private void bindPreferences() {
|
private void bindPreferences() {
|
||||||
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
|
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
|
||||||
if (localPreferenceScreen != null) {
|
if (localPreferenceScreen != null) {
|
||||||
ListView localListView = getListView();
|
ListView localListView = getListView();
|
||||||
localPreferenceScreen.bind(localListView);
|
localPreferenceScreen.bind(localListView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureList() {
|
private void ensureList() {
|
||||||
if (mList == null) {
|
if (mList == null) {
|
||||||
View view = getView();
|
View view = getView();
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
throw new IllegalStateException("Content view not yet created");
|
throw new IllegalStateException("Content view not yet created");
|
||||||
}
|
}
|
||||||
|
|
||||||
View listView = view.findViewById(android.R.id.list);
|
View listView = view.findViewById(android.R.id.list);
|
||||||
if (!(listView instanceof ListView)) {
|
if (!(listView instanceof ListView)) {
|
||||||
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
|
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
|
||||||
}
|
}
|
||||||
|
|
||||||
mList = (ListView)listView;
|
mList = (ListView)listView;
|
||||||
if (mList == null) {
|
if (mList == null) {
|
||||||
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
|
throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'");
|
||||||
}
|
}
|
||||||
|
|
||||||
mHandler.post(mRequestFocus);
|
mHandler.post(mRequestFocus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postBindPreferences() {
|
private void postBindPreferences() {
|
||||||
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
|
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
|
||||||
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
|
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requirePreferenceManager() {
|
private void requirePreferenceManager() {
|
||||||
if (this.mPreferenceManager == null) {
|
if (this.mPreferenceManager == null) {
|
||||||
throw new RuntimeException("This should be called after super.onCreate.");
|
throw new RuntimeException("This should be called after super.onCreate.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPreferencesFromIntent(Intent intent) {
|
public void addPreferencesFromIntent(Intent intent) {
|
||||||
requirePreferenceManager();
|
requirePreferenceManager();
|
||||||
PreferenceScreen screen = inflateFromIntent(intent, getPreferenceScreen());
|
PreferenceScreen screen = inflateFromIntent(intent, getPreferenceScreen());
|
||||||
setPreferenceScreen(screen);
|
setPreferenceScreen(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceScreen addPreferencesFromResource(int resId) {
|
public PreferenceScreen addPreferencesFromResource(int resId) {
|
||||||
requirePreferenceManager();
|
requirePreferenceManager();
|
||||||
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
|
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
|
||||||
setPreferenceScreen(screen);
|
setPreferenceScreen(screen);
|
||||||
|
|
||||||
for(int i = 0; i < screen.getPreferenceCount(); i++) {
|
for(int i = 0; i < screen.getPreferenceCount(); i++) {
|
||||||
Preference preference = screen.getPreference(i);
|
Preference preference = screen.getPreference(i);
|
||||||
if(preference instanceof PreferenceScreen && preference.getKey() != null) {
|
if(preference instanceof PreferenceScreen && preference.getKey() != null) {
|
||||||
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
onStartNewFragment(preference.getKey());
|
onStartNewFragment(preference.getKey());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Preference findPreference(CharSequence key) {
|
public Preference findPreference(CharSequence key) {
|
||||||
if (mPreferenceManager == null) {
|
if (mPreferenceManager == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mPreferenceManager.findPreference(key);
|
return mPreferenceManager.findPreference(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListView getListView() {
|
public ListView getListView() {
|
||||||
ensureList();
|
ensureList();
|
||||||
return mList;
|
return mList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceManager getPreferenceManager() {
|
public PreferenceManager getPreferenceManager() {
|
||||||
return mPreferenceManager;
|
return mPreferenceManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
public void onActivityCreated(Bundle savedInstanceState) {
|
||||||
super.onActivityCreated(savedInstanceState);
|
super.onActivityCreated(savedInstanceState);
|
||||||
getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
|
getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
|
||||||
if (mHavePrefs) {
|
if (mHavePrefs) {
|
||||||
bindPreferences();
|
bindPreferences();
|
||||||
}
|
}
|
||||||
mInitDone = true;
|
mInitDone = true;
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
Bundle localBundle = savedInstanceState.getBundle(PREFERENCES_TAG);
|
Bundle localBundle = savedInstanceState.getBundle(PREFERENCES_TAG);
|
||||||
if (localBundle != null) {
|
if (localBundle != null) {
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
if (screen != null) {
|
if (screen != null) {
|
||||||
screen.restoreHierarchyState(localBundle);
|
screen.restoreHierarchyState(localBundle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
dispatchActivityResult(requestCode, resultCode, data);
|
dispatchActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle paramBundle) {
|
public void onCreate(Bundle paramBundle) {
|
||||||
super.onCreate(paramBundle);
|
super.onCreate(paramBundle);
|
||||||
mPreferenceManager = createPreferenceManager();
|
mPreferenceManager = createPreferenceManager();
|
||||||
|
|
||||||
int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0);
|
int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0);
|
||||||
if(res != 0) {
|
if(res != 0) {
|
||||||
PreferenceScreen preferenceScreen = addPreferencesFromResource(res);
|
PreferenceScreen preferenceScreen = addPreferencesFromResource(res);
|
||||||
onInitPreferences(preferenceScreen);
|
onInitPreferences(preferenceScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
|
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
|
||||||
return paramLayoutInflater.inflate(R.layout.preferences, paramViewGroup, false);
|
return paramLayoutInflater.inflate(R.layout.preferences, paramViewGroup, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
dispatchActivityDestroy();
|
dispatchActivityDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
mList = null;
|
mList = null;
|
||||||
mHandler.removeCallbacks(mRequestFocus);
|
mHandler.removeCallbacks(mRequestFocus);
|
||||||
mHandler.removeMessages(MSG_BIND_PREFERENCES);
|
mHandler.removeMessages(MSG_BIND_PREFERENCES);
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle bundle) {
|
public void onSaveInstanceState(Bundle bundle) {
|
||||||
super.onSaveInstanceState(bundle);
|
super.onSaveInstanceState(bundle);
|
||||||
PreferenceScreen screen = getPreferenceScreen();
|
PreferenceScreen screen = getPreferenceScreen();
|
||||||
if (screen != null) {
|
if (screen != null) {
|
||||||
Bundle localBundle = new Bundle();
|
Bundle localBundle = new Bundle();
|
||||||
screen.saveHierarchyState(localBundle);
|
screen.saveHierarchyState(localBundle);
|
||||||
bundle.putBundle(PREFERENCES_TAG, localBundle);
|
bundle.putBundle(PREFERENCES_TAG, localBundle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
dispatchActivityStop();
|
dispatchActivityStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access methods with visibility private **/
|
/** Access methods with visibility private **/
|
||||||
|
|
||||||
private PreferenceManager createPreferenceManager() {
|
private PreferenceManager createPreferenceManager() {
|
||||||
try {
|
try {
|
||||||
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
|
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class);
|
||||||
c.setAccessible(true);
|
c.setAccessible(true);
|
||||||
return c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
|
return c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PreferenceScreen getPreferenceScreen() {
|
private PreferenceScreen getPreferenceScreen() {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
|
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
return (PreferenceScreen) m.invoke(mPreferenceManager);
|
return (PreferenceScreen) m.invoke(mPreferenceManager);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPreferenceScreen(PreferenceScreen preferenceScreen) {
|
protected void setPreferenceScreen(PreferenceScreen preferenceScreen) {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
|
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
|
||||||
if (result && preferenceScreen != null) {
|
if (result && preferenceScreen != null) {
|
||||||
mHavePrefs = true;
|
mHavePrefs = true;
|
||||||
if (mInitDone) {
|
if (mInitDone) {
|
||||||
postBindPreferences();
|
postBindPreferences();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
|
private void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
m.invoke(mPreferenceManager, requestCode, resultCode, data);
|
m.invoke(mPreferenceManager, requestCode, resultCode, data);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchActivityDestroy() {
|
private void dispatchActivityDestroy() {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
m.invoke(mPreferenceManager);
|
m.invoke(mPreferenceManager);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchActivityStop() {
|
private void dispatchActivityStop() {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
m.invoke(mPreferenceManager);
|
m.invoke(mPreferenceManager);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setFragment(PreferenceFragment preferenceFragment) {
|
private void setFragment(PreferenceFragment preferenceFragment) {
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("setFragment", PreferenceFragment.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("setFragment", PreferenceFragment.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
m.invoke(mPreferenceManager, preferenceFragment);
|
m.invoke(mPreferenceManager, preferenceFragment);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
|
public PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
|
||||||
PreferenceScreen preferenceScreen ;
|
PreferenceScreen preferenceScreen ;
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, context, resId, rootPreferences);
|
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, context, resId, rootPreferences);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return preferenceScreen;
|
return preferenceScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
|
public PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
|
||||||
PreferenceScreen preferenceScreen ;
|
PreferenceScreen preferenceScreen ;
|
||||||
try {
|
try {
|
||||||
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
|
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class);
|
||||||
m.setAccessible(true);
|
m.setAccessible(true);
|
||||||
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, queryIntent, rootPreferences);
|
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, queryIntent, rootPreferences);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return preferenceScreen;
|
return preferenceScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void onInitPreferences(PreferenceScreen preferenceScreen);
|
protected abstract void onInitPreferences(PreferenceScreen preferenceScreen);
|
||||||
protected abstract void onStartNewFragment(String name);
|
protected abstract void onStartNewFragment(String name);
|
||||||
}
|
}
|
||||||
|
@ -38,254 +38,254 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
|
public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<Serializable> {
|
||||||
private static final String TAG = SearchFragment.class.getSimpleName();
|
private static final String TAG = SearchFragment.class.getSimpleName();
|
||||||
|
|
||||||
private static final int MAX_ARTISTS = 20;
|
private static final int MAX_ARTISTS = 20;
|
||||||
private static final int MAX_ALBUMS = 20;
|
private static final int MAX_ALBUMS = 20;
|
||||||
private static final int MAX_SONGS = 50;
|
private static final int MAX_SONGS = 50;
|
||||||
private static final int MIN_CLOSENESS = 1;
|
private static final int MIN_CLOSENESS = 1;
|
||||||
|
|
||||||
protected RecyclerView recyclerView;
|
protected RecyclerView recyclerView;
|
||||||
protected SearchAdapter adapter;
|
protected SearchAdapter adapter;
|
||||||
protected boolean largeAlbums = false;
|
protected boolean largeAlbums = false;
|
||||||
|
|
||||||
private SearchResult searchResult;
|
private SearchResult searchResult;
|
||||||
private boolean skipSearch = false;
|
private boolean skipSearch = false;
|
||||||
private String currentQuery;
|
private String currentQuery;
|
||||||
|
|
||||||
public SearchFragment() {
|
public SearchFragment() {
|
||||||
super();
|
super();
|
||||||
alwaysStartFullscreen = true;
|
alwaysStartFullscreen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if(savedInstanceState != null) {
|
if(savedInstanceState != null) {
|
||||||
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
|
searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
}
|
}
|
||||||
largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
|
largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putSerializable(Constants.FRAGMENT_LIST, searchResult);
|
outState.putSerializable(Constants.FRAGMENT_LIST, searchResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
||||||
setTitle(R.string.search_title);
|
setTitle(R.string.search_title);
|
||||||
|
|
||||||
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
||||||
refreshLayout.setEnabled(false);
|
refreshLayout.setEnabled(false);
|
||||||
|
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
||||||
setupLayoutManager(recyclerView, largeAlbums);
|
setupLayoutManager(recyclerView, largeAlbums);
|
||||||
|
|
||||||
registerForContextMenu(recyclerView);
|
registerForContextMenu(recyclerView);
|
||||||
context.onNewIntent(context.getIntent());
|
context.onNewIntent(context.getIntent());
|
||||||
|
|
||||||
if(searchResult != null) {
|
if(searchResult != null) {
|
||||||
skipSearch = true;
|
skipSearch = true;
|
||||||
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
|
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
||||||
boolean update = this.isOnlyVisible != isOnlyVisible;
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
||||||
super.setIsOnlyVisible(isOnlyVisible);
|
super.setIsOnlyVisible(isOnlyVisible);
|
||||||
if(update && adapter != null) {
|
if(update && adapter != null) {
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if(layoutManager instanceof GridLayoutManager) {
|
||||||
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final GridLayoutManager gridLayoutManager) {
|
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final GridLayoutManager gridLayoutManager) {
|
||||||
return new GridLayoutManager.SpanSizeLookup() {
|
return new GridLayoutManager.SpanSizeLookup() {
|
||||||
@Override
|
@Override
|
||||||
public int getSpanSize(int position) {
|
public int getSpanSize(int position) {
|
||||||
int viewType = adapter.getItemViewType(position);
|
int viewType = adapter.getItemViewType(position);
|
||||||
if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
|
if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) {
|
||||||
return gridLayoutManager.getSpanCount();
|
return gridLayoutManager.getSpanCount();
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
menuInflater.inflate(R.menu.search, menu);
|
menuInflater.inflate(R.menu.search, menu);
|
||||||
onFinishSetupOptionsMenu(menu);
|
onFinishSetupOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
||||||
if(item instanceof MusicDirectory.Entry && !Util.isOffline(context)) {
|
if(item instanceof MusicDirectory.Entry && !Util.isOffline(context)) {
|
||||||
menu.removeItem(R.id.song_menu_remove_playlist);
|
menu.removeItem(R.id.song_menu_remove_playlist);
|
||||||
}
|
}
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
|
||||||
return onContextItemSelected(menuItem, item);
|
return onContextItemSelected(menuItem, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refresh(boolean refresh) {
|
public void refresh(boolean refresh) {
|
||||||
context.onNewIntent(context.getIntent());
|
context.onNewIntent(context.getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
||||||
if (item instanceof Artist) {
|
if (item instanceof Artist) {
|
||||||
onArtistSelected((Artist) item, false);
|
onArtistSelected((Artist) item, false);
|
||||||
} else if (item instanceof MusicDirectory.Entry) {
|
} else if (item instanceof MusicDirectory.Entry) {
|
||||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
|
MusicDirectory.Entry entry = (MusicDirectory.Entry) item;
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
onAlbumSelected(entry, false);
|
onAlbumSelected(entry, false);
|
||||||
} else {
|
} else {
|
||||||
onSongSelected(entry, false, true, true, false);
|
onSongSelected(entry, false, true, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<MusicDirectory.Entry> getSelectedEntries() {
|
protected List<MusicDirectory.Entry> getSelectedEntries() {
|
||||||
List<Serializable> selected = adapter.getSelected();
|
List<Serializable> selected = adapter.getSelected();
|
||||||
List<MusicDirectory.Entry> selectedMedia = new ArrayList<>();
|
List<MusicDirectory.Entry> selectedMedia = new ArrayList<>();
|
||||||
for(Serializable ser: selected) {
|
for(Serializable ser: selected) {
|
||||||
if(ser instanceof MusicDirectory.Entry) {
|
if(ser instanceof MusicDirectory.Entry) {
|
||||||
selectedMedia.add((MusicDirectory.Entry) ser);
|
selectedMedia.add((MusicDirectory.Entry) ser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return selectedMedia;
|
return selectedMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isShowArtistEnabled() {
|
protected boolean isShowArtistEnabled() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void search(final String query, final boolean autoplay) {
|
public void search(final String query, final boolean autoplay) {
|
||||||
if(skipSearch) {
|
if(skipSearch) {
|
||||||
skipSearch = false;
|
skipSearch = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentQuery = query;
|
currentQuery = query;
|
||||||
|
|
||||||
BackgroundTask<SearchResult> task = new TabBackgroundTask<SearchResult>(this) {
|
BackgroundTask<SearchResult> task = new TabBackgroundTask<SearchResult>(this) {
|
||||||
@Override
|
@Override
|
||||||
protected SearchResult doInBackground() throws Throwable {
|
protected SearchResult doInBackground() throws Throwable {
|
||||||
SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
|
SearchCritera criteria = new SearchCritera(query, MAX_ARTISTS, MAX_ALBUMS, MAX_SONGS);
|
||||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||||
return service.search(criteria, context, this);
|
return service.search(criteria, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(SearchResult result) {
|
protected void done(SearchResult result) {
|
||||||
searchResult = result;
|
searchResult = result;
|
||||||
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, SearchFragment.this));
|
recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, SearchFragment.this));
|
||||||
if (autoplay) {
|
if (autoplay) {
|
||||||
autoplay(query);
|
autoplay(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
task.execute();
|
task.execute();
|
||||||
|
|
||||||
if(searchItem != null) {
|
if(searchItem != null) {
|
||||||
MenuItemCompat.collapseActionView(searchItem);
|
MenuItemCompat.collapseActionView(searchItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getCurrentQuery() {
|
protected String getCurrentQuery() {
|
||||||
return currentQuery;
|
return currentQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onArtistSelected(Artist artist, boolean autoplay) {
|
private void onArtistSelected(Artist artist, boolean autoplay) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||||
if(autoplay) {
|
if(autoplay) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
}
|
}
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
|
private void onAlbumSelected(MusicDirectory.Entry album, boolean autoplay) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle());
|
||||||
if(autoplay) {
|
if(autoplay) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
|
private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) {
|
||||||
DownloadService downloadService = getDownloadService();
|
DownloadService downloadService = getDownloadService();
|
||||||
if (downloadService != null) {
|
if (downloadService != null) {
|
||||||
if (!append) {
|
if (!append) {
|
||||||
downloadService.clear();
|
downloadService.clear();
|
||||||
}
|
}
|
||||||
downloadService.download(Arrays.asList(song), save, false, playNext, false);
|
downloadService.download(Arrays.asList(song), save, false, playNext, false);
|
||||||
if (autoplay) {
|
if (autoplay) {
|
||||||
downloadService.play(downloadService.size() - 1);
|
downloadService.play(downloadService.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void autoplay(String query) {
|
private void autoplay(String query) {
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
||||||
Artist artist = null;
|
Artist artist = null;
|
||||||
if(!searchResult.getArtists().isEmpty()) {
|
if(!searchResult.getArtists().isEmpty()) {
|
||||||
artist = searchResult.getArtists().get(0);
|
artist = searchResult.getArtists().get(0);
|
||||||
artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query));
|
artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
MusicDirectory.Entry album = null;
|
MusicDirectory.Entry album = null;
|
||||||
if(!searchResult.getAlbums().isEmpty()) {
|
if(!searchResult.getAlbums().isEmpty()) {
|
||||||
album = searchResult.getAlbums().get(0);
|
album = searchResult.getAlbums().get(0);
|
||||||
album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query));
|
album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
MusicDirectory.Entry song = null;
|
MusicDirectory.Entry song = null;
|
||||||
if(!searchResult.getSongs().isEmpty()) {
|
if(!searchResult.getSongs().isEmpty()) {
|
||||||
song = searchResult.getSongs().get(0);
|
song = searchResult.getSongs().get(0);
|
||||||
song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query));
|
song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(artist != null && (artist.getCloseness() <= MIN_CLOSENESS ||
|
if(artist != null && (artist.getCloseness() <= MIN_CLOSENESS ||
|
||||||
(album == null || artist.getCloseness() <= album.getCloseness()) &&
|
(album == null || artist.getCloseness() <= album.getCloseness()) &&
|
||||||
(song == null || artist.getCloseness() <= song.getCloseness()))) {
|
(song == null || artist.getCloseness() <= song.getCloseness()))) {
|
||||||
onArtistSelected(artist, true);
|
onArtistSelected(artist, true);
|
||||||
} else if(album != null && (album.getCloseness() <= MIN_CLOSENESS ||
|
} else if(album != null && (album.getCloseness() <= MIN_CLOSENESS ||
|
||||||
song == null || album.getCloseness() <= song.getCloseness())) {
|
song == null || album.getCloseness() <= song.getCloseness())) {
|
||||||
onAlbumSelected(album, true);
|
onAlbumSelected(album, true);
|
||||||
} else if(song != null) {
|
} else if(song != null) {
|
||||||
onSongSelected(song, false, false, true, false);
|
onSongSelected(song, false, false, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,224 +29,224 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> implements ArtistAdapter.OnMusicFolderChanged {
|
public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> implements ArtistAdapter.OnMusicFolderChanged {
|
||||||
private static final String TAG = SelectArtistFragment.class.getSimpleName();
|
private static final String TAG = SelectArtistFragment.class.getSimpleName();
|
||||||
|
|
||||||
private List<MusicFolder> musicFolders = null;
|
private List<MusicFolder> musicFolders = null;
|
||||||
private List<Entry> entries;
|
private List<Entry> entries;
|
||||||
private String groupId;
|
private String groupId;
|
||||||
private String groupName;
|
private String groupName;
|
||||||
|
|
||||||
public SelectArtistFragment() {
|
public SelectArtistFragment() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
if(bundle != null) {
|
if(bundle != null) {
|
||||||
musicFolders = (List<MusicFolder>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
musicFolders = (List<MusicFolder>) bundle.getSerializable(Constants.FRAGMENT_LIST2);
|
||||||
}
|
}
|
||||||
artist = true;
|
artist = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putSerializable(Constants.FRAGMENT_LIST2, (Serializable) musicFolders);
|
outState.putSerializable(Constants.FRAGMENT_LIST2, (Serializable) musicFolders);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if(args != null) {
|
if(args != null) {
|
||||||
if(args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) {
|
if(args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) {
|
||||||
groupId = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
groupId = args.getString(Constants.INTENT_EXTRA_NAME_ID);
|
||||||
groupName = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
groupName = args.getString(Constants.INTENT_EXTRA_NAME_NAME);
|
||||||
|
|
||||||
if (groupName != null) {
|
if (groupName != null) {
|
||||||
setTitle(groupName);
|
setTitle(groupName);
|
||||||
context.invalidateOptionsMenu();
|
context.invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onCreateView(inflater, container, bundle);
|
super.onCreateView(inflater, container, bundle);
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Serializable> updateView, Serializable item) {
|
||||||
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
onCreateContextMenuSupport(menu, menuInflater, updateView, item);
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Serializable> updateView, Serializable item) {
|
||||||
return onContextItemSelected(menuItem, item);
|
return onContextItemSelected(menuItem, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
public void onItemClicked(UpdateView<Serializable> updateView, Serializable item) {
|
||||||
SubsonicFragment fragment;
|
SubsonicFragment fragment;
|
||||||
if(item instanceof Artist) {
|
if(item instanceof Artist) {
|
||||||
Artist artist = (Artist) item;
|
Artist artist = (Artist) item;
|
||||||
|
|
||||||
if ((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || groupId != null) {
|
if ((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || groupId != null) {
|
||||||
fragment = new SelectDirectoryFragment();
|
fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||||
|
|
||||||
if (!Util.isOffline(context)) {
|
if (!Util.isOffline(context)) {
|
||||||
args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
|
args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
|
||||||
}
|
}
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
|
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
} else {
|
} else {
|
||||||
fragment = new SelectArtistFragment();
|
fragment = new SelectArtistFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName());
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
||||||
if (!Util.isOffline(context)) {
|
if (!Util.isOffline(context)) {
|
||||||
args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
|
args.putSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY, new Entry(artist));
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
} else {
|
} else {
|
||||||
Entry entry = (Entry) item;
|
Entry entry = (Entry) item;
|
||||||
onSongPress(entries, entry);
|
onSongPress(entries, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
super.onCreateOptionsMenu(menu, menuInflater);
|
super.onCreateOptionsMenu(menu, menuInflater);
|
||||||
|
|
||||||
if(Util.isOffline(context) || Util.isTagBrowsing(context) || groupId != null) {
|
if(Util.isOffline(context) || Util.isTagBrowsing(context) || groupId != null) {
|
||||||
menu.removeItem(R.id.menu_first_level_artist);
|
menu.removeItem(R.id.menu_first_level_artist);
|
||||||
} else {
|
} else {
|
||||||
if (Util.isFirstLevelArtist(context)) {
|
if (Util.isFirstLevelArtist(context)) {
|
||||||
menu.findItem(R.id.menu_first_level_artist).setChecked(true);
|
menu.findItem(R.id.menu_first_level_artist).setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return R.menu.select_artist;
|
return R.menu.select_artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
if(super.onOptionsItemSelected(item)) {
|
if(super.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.menu_first_level_artist:
|
case R.id.menu_first_level_artist:
|
||||||
toggleFirstLevelArtist();
|
toggleFirstLevelArtist();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter getAdapter(List<Serializable> objects) {
|
public SectionAdapter getAdapter(List<Serializable> objects) {
|
||||||
return new ArtistAdapter(context, objects, musicFolders, this, this);
|
return new ArtistAdapter(context, objects, musicFolders, this, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Serializable> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Serializable> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<Serializable> items;
|
List<Serializable> items;
|
||||||
if(groupId == null) {
|
if(groupId == null) {
|
||||||
if (!Util.isOffline(context) && !Util.isTagBrowsing(context)) {
|
if (!Util.isOffline(context) && !Util.isTagBrowsing(context)) {
|
||||||
musicFolders = musicService.getMusicFolders(refresh, context, listener);
|
musicFolders = musicService.getMusicFolders(refresh, context, listener);
|
||||||
|
|
||||||
// Hide folders option if there is only one
|
// Hide folders option if there is only one
|
||||||
if (musicFolders.size() == 1) {
|
if (musicFolders.size() == 1) {
|
||||||
musicFolders = null;
|
musicFolders = null;
|
||||||
Util.setSelectedMusicFolderId(context, null);
|
Util.setSelectedMusicFolderId(context, null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
musicFolders = null;
|
musicFolders = null;
|
||||||
}
|
}
|
||||||
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
String musicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
|
|
||||||
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
|
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
|
||||||
indexes.sortChildren(context);
|
indexes.sortChildren(context);
|
||||||
items = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
|
items = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
|
||||||
items.addAll(indexes.getShortcuts());
|
items.addAll(indexes.getShortcuts());
|
||||||
items.addAll(indexes.getArtists());
|
items.addAll(indexes.getArtists());
|
||||||
entries = indexes.getEntries();
|
entries = indexes.getEntries();
|
||||||
items.addAll(entries);
|
items.addAll(entries);
|
||||||
} else {
|
} else {
|
||||||
List<Artist> artists = new ArrayList<>();
|
List<Artist> artists = new ArrayList<>();
|
||||||
items = new ArrayList<>();
|
items = new ArrayList<>();
|
||||||
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
|
MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener);
|
||||||
for(Entry entry: dir.getChildren(true, false)) {
|
for(Entry entry: dir.getChildren(true, false)) {
|
||||||
Artist artist = new Artist();
|
Artist artist = new Artist();
|
||||||
artist.setId(entry.getId());
|
artist.setId(entry.getId());
|
||||||
artist.setName(entry.getTitle());
|
artist.setName(entry.getTitle());
|
||||||
artists.add(artist);
|
artists.add(artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
Indexes indexes = new Indexes();
|
Indexes indexes = new Indexes();
|
||||||
//indexes.setArtists = artists;
|
//indexes.setArtists = artists;
|
||||||
indexes.sortChildren(context);
|
indexes.sortChildren(context);
|
||||||
items.addAll(indexes.getArtists());
|
items.addAll(indexes.getArtists());
|
||||||
|
|
||||||
entries = dir.getChildren(false, true);
|
entries = dir.getChildren(false, true);
|
||||||
for(Entry entry: entries) {
|
for(Entry entry: entries) {
|
||||||
items.add(entry);
|
items.add(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return groupId == null ? R.string.button_bar_browse : 0;
|
return groupId == null ? R.string.button_bar_browse : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEmpty(boolean empty) {
|
public void setEmpty(boolean empty) {
|
||||||
super.setEmpty(empty);
|
super.setEmpty(empty);
|
||||||
|
|
||||||
if(empty && !Util.isOffline(context)) {
|
if(empty && !Util.isOffline(context)) {
|
||||||
objects.clear();
|
objects.clear();
|
||||||
recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this));
|
recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this));
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
View view = rootView.findViewById(R.id.tab_progress);
|
View view = rootView.findViewById(R.id.tab_progress);
|
||||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
|
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
|
||||||
params.height = 0;
|
params.height = 0;
|
||||||
params.weight = 5;
|
params.weight = 5;
|
||||||
view.setLayoutParams(params);
|
view.setLayoutParams(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleFirstLevelArtist() {
|
private void toggleFirstLevelArtist() {
|
||||||
Util.toggleFirstLevelArtist(context);
|
Util.toggleFirstLevelArtist(context);
|
||||||
context.invalidateOptionsMenu();
|
context.invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMusicFolderChanged(MusicFolder selectedFolder) {
|
public void onMusicFolderChanged(MusicFolder selectedFolder) {
|
||||||
String startMusicFolderId = Util.getSelectedMusicFolderId(context);
|
String startMusicFolderId = Util.getSelectedMusicFolderId(context);
|
||||||
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
String musicFolderId = selectedFolder == null ? null : selectedFolder.getId();
|
||||||
|
|
||||||
if(!Util.equals(startMusicFolderId, musicFolderId)) {
|
if(!Util.equals(startMusicFolderId, musicFolderId)) {
|
||||||
Util.setSelectedMusicFolderId(context, musicFolderId);
|
Util.setSelectedMusicFolderId(context, musicFolderId);
|
||||||
context.invalidate();
|
context.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
@ -32,46 +32,46 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
|
public class SelectGenreFragment extends SelectRecyclerFragment<Genre> {
|
||||||
private static final String TAG = SelectGenreFragment.class.getSimpleName();
|
private static final String TAG = SelectGenreFragment.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return R.menu.empty;
|
return R.menu.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter getAdapter(List<Genre> objs) {
|
public SectionAdapter getAdapter(List<Genre> objs) {
|
||||||
return new GenreAdapter(context, objs, this);
|
return new GenreAdapter(context, objs, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Genre> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Genre> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
return musicService.getGenres(refresh, context, listener);
|
return musicService.getGenres(refresh, context, listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return R.string.main_albums_genres;
|
return R.string.main_albums_genres;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Genre> updateView, Genre genre) {
|
public void onItemClicked(UpdateView<Genre> updateView, Genre genre) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "genres");
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "genres");
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, genre.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, genre.getName());
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Genre> updateView, Genre item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Genre> updateView, Genre item) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Genre> updateView, Genre item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Genre> updateView, Genre item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,311 +36,311 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
public class SelectPlaylistFragment extends SelectRecyclerFragment<Playlist> {
|
||||||
private static final String TAG = SelectPlaylistFragment.class.getSimpleName();
|
private static final String TAG = SelectPlaylistFragment.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) {
|
if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) {
|
||||||
largeAlbums = true;
|
largeAlbums = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Playlist> updateView, Playlist playlist) {
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<Playlist> updateView, Playlist playlist) {
|
||||||
if (Util.isOffline(context)) {
|
if (Util.isOffline(context)) {
|
||||||
menuInflater.inflate(R.menu.select_playlist_context_offline, menu);
|
menuInflater.inflate(R.menu.select_playlist_context_offline, menu);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
menuInflater.inflate(R.menu.select_playlist_context, menu);
|
menuInflater.inflate(R.menu.select_playlist_context, menu);
|
||||||
|
|
||||||
if(playlist.getPublic() != null && playlist.getPublic() == true && playlist.getId().indexOf(".m3u") == -1 && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) {
|
if(playlist.getPublic() != null && playlist.getPublic() == true && playlist.getId().indexOf(".m3u") == -1 && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) {
|
||||||
menu.removeItem(R.id.playlist_update_info);
|
menu.removeItem(R.id.playlist_update_info);
|
||||||
menu.removeItem(R.id.playlist_menu_delete);
|
menu.removeItem(R.id.playlist_menu_delete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recreateContextMenu(menu);
|
recreateContextMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Playlist> updateView, Playlist playlist) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<Playlist> updateView, Playlist playlist) {
|
||||||
SubsonicFragment fragment;
|
SubsonicFragment fragment;
|
||||||
Bundle args;
|
Bundle args;
|
||||||
FragmentTransaction trans;
|
FragmentTransaction trans;
|
||||||
|
|
||||||
switch (menuItem.getItemId()) {
|
switch (menuItem.getItemId()) {
|
||||||
case R.id.playlist_menu_download:
|
case R.id.playlist_menu_download:
|
||||||
downloadPlaylist(playlist.getId(), playlist.getName(), false, true, false, false, true);
|
downloadPlaylist(playlist.getId(), playlist.getName(), false, true, false, false, true);
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_menu_play_now:
|
case R.id.playlist_menu_play_now:
|
||||||
fragment = new SelectDirectoryFragment();
|
fragment = new SelectDirectoryFragment();
|
||||||
args = new Bundle();
|
args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_menu_play_shuffled:
|
case R.id.playlist_menu_play_shuffled:
|
||||||
fragment = new SelectDirectoryFragment();
|
fragment = new SelectDirectoryFragment();
|
||||||
args = new Bundle();
|
args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, true);
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true);
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_menu_delete:
|
case R.id.playlist_menu_delete:
|
||||||
deletePlaylist(playlist);
|
deletePlaylist(playlist);
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_info:
|
case R.id.playlist_info:
|
||||||
displayPlaylistInfo(playlist);
|
displayPlaylistInfo(playlist);
|
||||||
break;
|
break;
|
||||||
case R.id.playlist_update_info:
|
case R.id.playlist_update_info:
|
||||||
updatePlaylistInfo(playlist);
|
updatePlaylistInfo(playlist);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return R.menu.abstract_top_menu;
|
return R.menu.abstract_top_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter<Playlist> getAdapter(List<Playlist> playlists) {
|
public SectionAdapter<Playlist> getAdapter(List<Playlist> playlists) {
|
||||||
List<Playlist> mine = new ArrayList<>();
|
List<Playlist> mine = new ArrayList<>();
|
||||||
|
|
||||||
String currentUsername = UserUtil.getCurrentUsername(context);
|
String currentUsername = UserUtil.getCurrentUsername(context);
|
||||||
for(Playlist playlist: playlists) {
|
for(Playlist playlist: playlists) {
|
||||||
if(playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) {
|
if(playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) {
|
||||||
mine.add(playlist);
|
mine.add(playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PlaylistAdapter(context, playlists, getImageLoader(), largeAlbums, this);
|
return new PlaylistAdapter(context, playlists, getImageLoader(), largeAlbums, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Playlist> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<Playlist> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<Playlist> playlists = musicService.getPlaylists(refresh, context, listener);
|
List<Playlist> playlists = musicService.getPlaylists(refresh, context, listener);
|
||||||
if(!Util.isOffline(context) && refresh) {
|
if(!Util.isOffline(context) && refresh) {
|
||||||
new CacheCleaner(context, getDownloadService()).cleanPlaylists(playlists);
|
new CacheCleaner(context, getDownloadService()).cleanPlaylists(playlists);
|
||||||
}
|
}
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return R.string.playlist_label;
|
return R.string.playlist_label;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<Playlist> updateView, Playlist playlist) {
|
public void onItemClicked(UpdateView<Playlist> updateView, Playlist playlist) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId());
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName());
|
||||||
if((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().indexOf(".m3u") != -1)) {
|
if((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().indexOf(".m3u") != -1)) {
|
||||||
args.putBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, true);
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, true);
|
||||||
}
|
}
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFinishRefresh() {
|
public void onFinishRefresh() {
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if(args != null) {
|
if(args != null) {
|
||||||
String playlistId = args.getString(Constants.INTENT_EXTRA_NAME_ID, null);
|
String playlistId = args.getString(Constants.INTENT_EXTRA_NAME_ID, null);
|
||||||
if (playlistId != null && objects != null) {
|
if (playlistId != null && objects != null) {
|
||||||
for (Playlist playlist : objects) {
|
for (Playlist playlist : objects) {
|
||||||
if (playlistId.equals(playlist.getId())) {
|
if (playlistId.equals(playlist.getId())) {
|
||||||
onItemClicked(null, playlist);
|
onItemClicked(null, playlist);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deletePlaylist(final Playlist playlist) {
|
private void deletePlaylist(final Playlist playlist) {
|
||||||
Util.confirmDialog(context, R.string.common_delete, playlist.getName(), new DialogInterface.OnClickListener() {
|
Util.confirmDialog(context, R.string.common_delete, playlist.getName(), new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
new LoadingTask<Void>(context, false) {
|
new LoadingTask<Void>(context, false) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
musicService.deletePlaylist(playlist.getId(), context, null);
|
musicService.deletePlaylist(playlist.getId(), context, null);
|
||||||
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
adapter.removeItem(playlist);
|
adapter.removeItem(playlist);
|
||||||
Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
|
Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
String msg;
|
String msg;
|
||||||
if (error instanceof OfflineException) {
|
if (error instanceof OfflineException) {
|
||||||
msg = getErrorMessage(error);
|
msg = getErrorMessage(error);
|
||||||
} else {
|
} else {
|
||||||
msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
|
msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.toast(context, msg, false);
|
Util.toast(context, msg, false);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayPlaylistInfo(final Playlist playlist) {
|
private void displayPlaylistInfo(final Playlist playlist) {
|
||||||
List<Integer> headers = new ArrayList<>();
|
List<Integer> headers = new ArrayList<>();
|
||||||
List<String> details = new ArrayList<>();
|
List<String> details = new ArrayList<>();
|
||||||
|
|
||||||
headers.add(R.string.details_title);
|
headers.add(R.string.details_title);
|
||||||
details.add(playlist.getName());
|
details.add(playlist.getName());
|
||||||
|
|
||||||
if(playlist.getOwner() != null) {
|
if(playlist.getOwner() != null) {
|
||||||
headers.add(R.string.details_owner);
|
headers.add(R.string.details_owner);
|
||||||
details.add(playlist.getOwner());
|
details.add(playlist.getOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getComment() != null) {
|
if(playlist.getComment() != null) {
|
||||||
headers.add(R.string.details_comments);
|
headers.add(R.string.details_comments);
|
||||||
details.add(playlist.getComment());
|
details.add(playlist.getComment());
|
||||||
}
|
}
|
||||||
|
|
||||||
headers.add(R.string.details_song_count);
|
headers.add(R.string.details_song_count);
|
||||||
details.add(playlist.getSongCount());
|
details.add(playlist.getSongCount());
|
||||||
|
|
||||||
if(playlist.getDuration() != null) {
|
if(playlist.getDuration() != null) {
|
||||||
headers.add(R.string.details_length);
|
headers.add(R.string.details_length);
|
||||||
details.add(Util.formatDuration(playlist.getDuration()));
|
details.add(Util.formatDuration(playlist.getDuration()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getPublic() != null) {
|
if(playlist.getPublic() != null) {
|
||||||
headers.add(R.string.details_public);
|
headers.add(R.string.details_public);
|
||||||
details.add(Util.formatBoolean(context, playlist.getPublic()));
|
details.add(Util.formatBoolean(context, playlist.getPublic()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(playlist.getCreated() != null) {
|
if(playlist.getCreated() != null) {
|
||||||
headers.add(R.string.details_created);
|
headers.add(R.string.details_created);
|
||||||
|
|
||||||
DateFormat dateFormat = DateFormat.getDateInstance();
|
DateFormat dateFormat = DateFormat.getDateInstance();
|
||||||
details.add(dateFormat.format(playlist.getCreated()));
|
details.add(dateFormat.format(playlist.getCreated()));
|
||||||
}
|
}
|
||||||
if(playlist.getChanged() != null) {
|
if(playlist.getChanged() != null) {
|
||||||
headers.add(R.string.details_updated);
|
headers.add(R.string.details_updated);
|
||||||
|
|
||||||
DateFormat dateFormat = DateFormat.getDateInstance();
|
DateFormat dateFormat = DateFormat.getDateInstance();
|
||||||
details.add(dateFormat.format(playlist.getChanged()));
|
details.add(dateFormat.format(playlist.getChanged()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.showDetailsDialog(context, R.string.details_title_playlist, headers, details);
|
Util.showDetailsDialog(context, R.string.details_title_playlist, headers, details);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePlaylistInfo(final Playlist playlist) {
|
private void updatePlaylistInfo(final Playlist playlist) {
|
||||||
View dialogView = context.getLayoutInflater().inflate(R.layout.update_playlist, null);
|
View dialogView = context.getLayoutInflater().inflate(R.layout.update_playlist, null);
|
||||||
final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_playlist_name);
|
final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_playlist_name);
|
||||||
final EditText commentBox = (EditText)dialogView.findViewById(R.id.get_playlist_comment);
|
final EditText commentBox = (EditText)dialogView.findViewById(R.id.get_playlist_comment);
|
||||||
final CheckBox publicBox = (CheckBox)dialogView.findViewById(R.id.get_playlist_public);
|
final CheckBox publicBox = (CheckBox)dialogView.findViewById(R.id.get_playlist_public);
|
||||||
|
|
||||||
nameBox.setText(playlist.getName());
|
nameBox.setText(playlist.getName());
|
||||||
commentBox.setText(playlist.getComment());
|
commentBox.setText(playlist.getComment());
|
||||||
Boolean pub = playlist.getPublic();
|
Boolean pub = playlist.getPublic();
|
||||||
if(pub == null) {
|
if(pub == null) {
|
||||||
publicBox.setEnabled(false);
|
publicBox.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
publicBox.setChecked(pub);
|
publicBox.setChecked(pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
new AlertDialog.Builder(context)
|
new AlertDialog.Builder(context)
|
||||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
.setTitle(R.string.playlist_update_info)
|
.setTitle(R.string.playlist_update_info)
|
||||||
.setView(dialogView)
|
.setView(dialogView)
|
||||||
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
new LoadingTask<Void>(context, false) {
|
new LoadingTask<Void>(context, false) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
String name = nameBox.getText().toString();
|
String name = nameBox.getText().toString();
|
||||||
String comment = commentBox.getText().toString();
|
String comment = commentBox.getText().toString();
|
||||||
boolean isPublic = publicBox.isChecked();
|
boolean isPublic = publicBox.isChecked();
|
||||||
|
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null);
|
musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null);
|
||||||
|
|
||||||
playlist.setName(name);
|
playlist.setName(name);
|
||||||
playlist.setComment(comment);
|
playlist.setComment(comment);
|
||||||
playlist.setPublic(isPublic);
|
playlist.setPublic(isPublic);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
String msg;
|
String msg;
|
||||||
if (error instanceof OfflineException) {
|
if (error instanceof OfflineException) {
|
||||||
msg = getErrorMessage(error);
|
msg = getErrorMessage(error);
|
||||||
} else {
|
} else {
|
||||||
msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error);
|
msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.toast(context, msg, false);
|
Util.toast(context, msg, false);
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.common_cancel, null)
|
.setNegativeButton(R.string.common_cancel, null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncPlaylist(Playlist playlist) {
|
private void syncPlaylist(Playlist playlist) {
|
||||||
SyncUtil.addSyncedPlaylist(context, playlist.getId());
|
SyncUtil.addSyncedPlaylist(context, playlist.getId());
|
||||||
downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true);
|
downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopSyncPlaylist(final Playlist playlist) {
|
private void stopSyncPlaylist(final Playlist playlist) {
|
||||||
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
SyncUtil.removeSyncedPlaylist(context, playlist.getId());
|
||||||
|
|
||||||
new LoadingTask<Void>(context, false) {
|
new LoadingTask<Void>(context, false) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
// Unpin all of the songs in playlist
|
// Unpin all of the songs in playlist
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
MusicDirectory root = musicService.getPlaylist(true, playlist.getId(), playlist.getName(), context, this);
|
MusicDirectory root = musicService.getPlaylist(true, playlist.getId(), playlist.getName(), context, this);
|
||||||
for(MusicDirectory.Entry entry: root.getChildren()) {
|
for(MusicDirectory.Entry entry: root.getChildren()) {
|
||||||
DownloadFile file = new DownloadFile(context, entry, false);
|
DownloadFile file = new DownloadFile(context, entry, false);
|
||||||
file.unpin();
|
file.unpin();
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
@ -46,174 +46,174 @@ import net.nullsum.audinaut.util.TabBackgroundTask;
|
|||||||
import net.nullsum.audinaut.view.FastScroller;
|
import net.nullsum.audinaut.view.FastScroller;
|
||||||
|
|
||||||
public abstract class SelectRecyclerFragment<T> extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<T> {
|
public abstract class SelectRecyclerFragment<T> extends SubsonicFragment implements SectionAdapter.OnItemClickedListener<T> {
|
||||||
private static final String TAG = SelectRecyclerFragment.class.getSimpleName();
|
private static final String TAG = SelectRecyclerFragment.class.getSimpleName();
|
||||||
protected RecyclerView recyclerView;
|
protected RecyclerView recyclerView;
|
||||||
protected FastScroller fastScroller;
|
protected FastScroller fastScroller;
|
||||||
protected SectionAdapter<T> adapter;
|
protected SectionAdapter<T> adapter;
|
||||||
protected UpdateTask currentTask;
|
protected UpdateTask currentTask;
|
||||||
protected List<T> objects;
|
protected List<T> objects;
|
||||||
protected boolean serialize = true;
|
protected boolean serialize = true;
|
||||||
protected boolean largeAlbums = false;
|
protected boolean largeAlbums = false;
|
||||||
protected boolean pullToRefresh = true;
|
protected boolean pullToRefresh = true;
|
||||||
protected boolean backgroundUpdate = true;
|
protected boolean backgroundUpdate = true;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle bundle) {
|
public void onCreate(Bundle bundle) {
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
|
||||||
if(bundle != null && serialize) {
|
if(bundle != null && serialize) {
|
||||||
objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
objects = (List<T>) bundle.getSerializable(Constants.FRAGMENT_LIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
if(serialize) {
|
if(serialize) {
|
||||||
outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects);
|
outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||||
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false);
|
||||||
|
|
||||||
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);
|
||||||
refreshLayout.setOnRefreshListener(this);
|
refreshLayout.setOnRefreshListener(this);
|
||||||
|
|
||||||
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler);
|
||||||
fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller);
|
fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller);
|
||||||
setupLayoutManager();
|
setupLayoutManager();
|
||||||
|
|
||||||
if(pullToRefresh) {
|
if(pullToRefresh) {
|
||||||
setupScrollList(recyclerView);
|
setupScrollList(recyclerView);
|
||||||
} else {
|
} else {
|
||||||
refreshLayout.setEnabled(false);
|
refreshLayout.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(objects == null) {
|
if(objects == null) {
|
||||||
refresh(false);
|
refresh(false);
|
||||||
} else {
|
} else {
|
||||||
recyclerView.setAdapter(adapter = getAdapter(objects));
|
recyclerView.setAdapter(adapter = getAdapter(objects));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
|
||||||
if(!primaryFragment) {
|
if(!primaryFragment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
menuInflater.inflate(getOptionsMenu(), menu);
|
menuInflater.inflate(getOptionsMenu(), menu);
|
||||||
onFinishSetupOptionsMenu(menu);
|
onFinishSetupOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
public void setIsOnlyVisible(boolean isOnlyVisible) {
|
||||||
boolean update = this.isOnlyVisible != isOnlyVisible;
|
boolean update = this.isOnlyVisible != isOnlyVisible;
|
||||||
super.setIsOnlyVisible(isOnlyVisible);
|
super.setIsOnlyVisible(isOnlyVisible);
|
||||||
if(update && adapter != null) {
|
if(update && adapter != null) {
|
||||||
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
|
||||||
if(layoutManager instanceof GridLayoutManager) {
|
if(layoutManager instanceof GridLayoutManager) {
|
||||||
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void refresh(final boolean refresh) {
|
protected void refresh(final boolean refresh) {
|
||||||
int titleRes = getTitleResource();
|
int titleRes = getTitleResource();
|
||||||
if(titleRes != 0) {
|
if(titleRes != 0) {
|
||||||
setTitle(getTitleResource());
|
setTitle(getTitleResource());
|
||||||
}
|
}
|
||||||
if(backgroundUpdate) {
|
if(backgroundUpdate) {
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel current running task before starting another one
|
// Cancel current running task before starting another one
|
||||||
if(currentTask != null) {
|
if(currentTask != null) {
|
||||||
currentTask.cancel();
|
currentTask.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTask = new UpdateTask(this, refresh);
|
currentTask = new UpdateTask(this, refresh);
|
||||||
|
|
||||||
if(backgroundUpdate) {
|
if(backgroundUpdate) {
|
||||||
currentTask.execute();
|
currentTask.execute();
|
||||||
} else {
|
} else {
|
||||||
objects = new ArrayList<T>();
|
objects = new ArrayList<T>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objects = getObjects(null, refresh, null);
|
objects = getObjects(null, refresh, null);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.e(TAG, "Failed to load", x);
|
Log.e(TAG, "Failed to load", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTask.done(objects);
|
currentTask.done(objects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SectionAdapter getCurrentAdapter() {
|
public SectionAdapter getCurrentAdapter() {
|
||||||
return adapter;
|
return adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupLayoutManager() {
|
private void setupLayoutManager() {
|
||||||
setupLayoutManager(recyclerView, largeAlbums);
|
setupLayoutManager(recyclerView, largeAlbums);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int getOptionsMenu();
|
public abstract int getOptionsMenu();
|
||||||
public abstract SectionAdapter<T> getAdapter(List<T> objs);
|
public abstract SectionAdapter<T> getAdapter(List<T> objs);
|
||||||
public abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception;
|
public abstract List<T> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception;
|
||||||
public abstract int getTitleResource();
|
public abstract int getTitleResource();
|
||||||
|
|
||||||
public void onFinishRefresh() {
|
public void onFinishRefresh() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UpdateTask extends TabBackgroundTask<List<T>> {
|
private class UpdateTask extends TabBackgroundTask<List<T>> {
|
||||||
private boolean refresh;
|
private boolean refresh;
|
||||||
|
|
||||||
public UpdateTask(SubsonicFragment fragment, boolean refresh) {
|
public UpdateTask(SubsonicFragment fragment, boolean refresh) {
|
||||||
super(fragment);
|
super(fragment);
|
||||||
this.refresh = refresh;
|
this.refresh = refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<T> doInBackground() throws Exception {
|
public List<T> doInBackground() throws Exception {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
|
|
||||||
objects = new ArrayList<T>();
|
objects = new ArrayList<T>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
objects = getObjects(musicService, refresh, this);
|
objects = getObjects(musicService, refresh, this);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
Log.e(TAG, "Failed to load", x);
|
Log.e(TAG, "Failed to load", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(List<T> result) {
|
public void done(List<T> result) {
|
||||||
if (result != null && !result.isEmpty()) {
|
if (result != null && !result.isEmpty()) {
|
||||||
recyclerView.setAdapter(adapter = getAdapter(result));
|
recyclerView.setAdapter(adapter = getAdapter(result));
|
||||||
if(!fastScroller.isAttached()) {
|
if(!fastScroller.isAttached()) {
|
||||||
fastScroller.attachRecyclerView(recyclerView);
|
fastScroller.attachRecyclerView(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
onFinishRefresh();
|
onFinishRefresh();
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
setEmpty(true);
|
setEmpty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTask = null;
|
currentTask = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.fragments;
|
package net.nullsum.audinaut.fragments;
|
||||||
@ -33,56 +33,56 @@ import net.nullsum.audinaut.view.UpdateView;
|
|||||||
|
|
||||||
public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
public class SelectYearFragment extends SelectRecyclerFragment<String> {
|
||||||
|
|
||||||
public SelectYearFragment() {
|
public SelectYearFragment() {
|
||||||
super();
|
super();
|
||||||
pullToRefresh = false;
|
pullToRefresh = false;
|
||||||
serialize = false;
|
serialize = false;
|
||||||
backgroundUpdate = false;
|
backgroundUpdate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOptionsMenu() {
|
public int getOptionsMenu() {
|
||||||
return R.menu.empty;
|
return R.menu.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SectionAdapter getAdapter(List<String> objs) {
|
public SectionAdapter getAdapter(List<String> objs) {
|
||||||
return new BasicListAdapter(context, objs, this);
|
return new BasicListAdapter(context, objs, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
public List<String> getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception {
|
||||||
List<String> decades = new ArrayList<>();
|
List<String> decades = new ArrayList<>();
|
||||||
for(int i = 2010; i >= 1800; i -= 10) {
|
for(int i = 2010; i >= 1800; i -= 10) {
|
||||||
decades.add(String.valueOf(i));
|
decades.add(String.valueOf(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return decades;
|
return decades;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTitleResource() {
|
public int getTitleResource() {
|
||||||
return R.string.main_albums_year;
|
return R.string.main_albums_year;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClicked(UpdateView<String> updateView, String decade) {
|
public void onItemClicked(UpdateView<String> updateView, String decade) {
|
||||||
SubsonicFragment fragment = new SelectDirectoryFragment();
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "years");
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, "years");
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
||||||
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
||||||
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, decade);
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA, decade);
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
|
|
||||||
replaceFragment(fragment);
|
replaceFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<String> updateView, String item) {}
|
public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView<String> updateView, String item) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<String> updateView, String item) {
|
public boolean onContextItemSelected(MenuItem menuItem, UpdateView<String> updateView, String item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -46,164 +46,164 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class AudinautSearchProvider extends ContentProvider {
|
public class AudinautSearchProvider extends ContentProvider {
|
||||||
private static final String TAG = AudinautSearchProvider.class.getSimpleName();
|
private static final String TAG = AudinautSearchProvider.class.getSimpleName();
|
||||||
|
|
||||||
private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/";
|
private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/";
|
||||||
private static final String[] COLUMNS = {"_id",
|
private static final String[] COLUMNS = {"_id",
|
||||||
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
||||||
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
||||||
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
||||||
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
|
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
|
||||||
SearchManager.SUGGEST_COLUMN_ICON_1};
|
SearchManager.SUGGEST_COLUMN_ICON_1};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
if(selectionArgs[0].isEmpty()) {
|
if(selectionArgs[0].isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String query = selectionArgs[0] + "*";
|
String query = selectionArgs[0] + "*";
|
||||||
SearchResult searchResult = search(query);
|
SearchResult searchResult = search(query);
|
||||||
return createCursor(selectionArgs[0], searchResult);
|
return createCursor(selectionArgs[0], searchResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SearchResult search(String query) {
|
private SearchResult search(String query) {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(getContext());
|
MusicService musicService = MusicServiceFactory.getMusicService(getContext());
|
||||||
if (musicService == null) {
|
if (musicService == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return musicService.search(new SearchCritera(query, 5, 10, 10), getContext(), null);
|
return musicService.search(new SearchCritera(query, 5, 10, 10), getContext(), null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cursor createCursor(String query, SearchResult searchResult) {
|
private Cursor createCursor(String query, SearchResult searchResult) {
|
||||||
MatrixCursor cursor = new MatrixCursor(COLUMNS);
|
MatrixCursor cursor = new MatrixCursor(COLUMNS);
|
||||||
if (searchResult == null) {
|
if (searchResult == null) {
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all results into one pot
|
// Add all results into one pot
|
||||||
List<Object> results = new ArrayList<Object>();
|
List<Object> results = new ArrayList<Object>();
|
||||||
results.addAll(searchResult.getArtists());
|
results.addAll(searchResult.getArtists());
|
||||||
results.addAll(searchResult.getAlbums());
|
results.addAll(searchResult.getAlbums());
|
||||||
results.addAll(searchResult.getSongs());
|
results.addAll(searchResult.getSongs());
|
||||||
|
|
||||||
// For each, calculate its string distance to the query
|
// For each, calculate its string distance to the query
|
||||||
for(Object obj: results) {
|
for(Object obj: results) {
|
||||||
if(obj instanceof Artist) {
|
if(obj instanceof Artist) {
|
||||||
Artist artist = (Artist) obj;
|
Artist artist = (Artist) obj;
|
||||||
artist.setCloseness(Util.getStringDistance(query, artist.getName()));
|
artist.setCloseness(Util.getStringDistance(query, artist.getName()));
|
||||||
} else {
|
} else {
|
||||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
||||||
entry.setCloseness(Util.getStringDistance(query, entry.getTitle()));
|
entry.setCloseness(Util.getStringDistance(query, entry.getTitle()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort based on the closeness paramater
|
// Sort based on the closeness paramater
|
||||||
Collections.sort(results, new Comparator<Object>() {
|
Collections.sort(results, new Comparator<Object>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(Object lhs, Object rhs) {
|
public int compare(Object lhs, Object rhs) {
|
||||||
// Get the closeness of the two objects
|
// Get the closeness of the two objects
|
||||||
int left, right;
|
int left, right;
|
||||||
boolean leftArtist = lhs instanceof Artist;
|
boolean leftArtist = lhs instanceof Artist;
|
||||||
boolean rightArtist = rhs instanceof Artist;
|
boolean rightArtist = rhs instanceof Artist;
|
||||||
if (leftArtist) {
|
if (leftArtist) {
|
||||||
left = ((Artist) lhs).getCloseness();
|
left = ((Artist) lhs).getCloseness();
|
||||||
} else {
|
} else {
|
||||||
left = ((MusicDirectory.Entry) lhs).getCloseness();
|
left = ((MusicDirectory.Entry) lhs).getCloseness();
|
||||||
}
|
}
|
||||||
if (rightArtist) {
|
if (rightArtist) {
|
||||||
right = ((Artist) rhs).getCloseness();
|
right = ((Artist) rhs).getCloseness();
|
||||||
} else {
|
} else {
|
||||||
right = ((MusicDirectory.Entry) rhs).getCloseness();
|
right = ((MusicDirectory.Entry) rhs).getCloseness();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left == right) {
|
if (left == right) {
|
||||||
if(leftArtist && rightArtist) {
|
if(leftArtist && rightArtist) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if(leftArtist) {
|
} else if(leftArtist) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if(rightArtist) {
|
} else if(rightArtist) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (left > right) {
|
} else if (left > right) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Done sorting, add results to cursor
|
// Done sorting, add results to cursor
|
||||||
for(Object obj: results) {
|
for(Object obj: results) {
|
||||||
if(obj instanceof Artist) {
|
if(obj instanceof Artist) {
|
||||||
Artist artist = (Artist) obj;
|
Artist artist = (Artist) obj;
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist;
|
||||||
cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon});
|
cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon});
|
||||||
} else {
|
} else {
|
||||||
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
MusicDirectory.Entry entry = (MusicDirectory.Entry) obj;
|
||||||
|
|
||||||
if(entry.isDirectory()) {
|
if(entry.isDirectory()) {
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_album;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_album;
|
||||||
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon});
|
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon});
|
||||||
} else {
|
} else {
|
||||||
String icon = RESOURCE_PREFIX + R.drawable.ic_action_song;
|
String icon = RESOURCE_PREFIX + R.drawable.ic_action_song;
|
||||||
String id;
|
String id;
|
||||||
if(Util.isTagBrowsing(getContext())) {
|
if(Util.isTagBrowsing(getContext())) {
|
||||||
id = entry.getAlbumId();
|
id = entry.getAlbumId();
|
||||||
} else {
|
} else {
|
||||||
id = entry.getParent();
|
id = entry.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
String artistDisplay;
|
String artistDisplay;
|
||||||
if(entry.getArtist() == null) {
|
if(entry.getArtist() == null) {
|
||||||
if(entry.getAlbum() != null) {
|
if(entry.getAlbum() != null) {
|
||||||
artistDisplay = entry.getAlbumDisplay();
|
artistDisplay = entry.getAlbumDisplay();
|
||||||
} else {
|
} else {
|
||||||
artistDisplay = "";
|
artistDisplay = "";
|
||||||
}
|
}
|
||||||
} else if(entry.getAlbum() != null) {
|
} else if(entry.getAlbum() != null) {
|
||||||
artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay();
|
artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay();
|
||||||
} else {
|
} else {
|
||||||
artistDisplay = entry.getArtist();
|
artistDisplay = entry.getArtist();
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), artistDisplay, "so-" + id, entry.getTitle(), icon});
|
cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), artistDisplay, "so-" + id, entry.getTitle(), icon});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType(Uri uri) {
|
public String getType(Uri uri) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(Uri uri, ContentValues contentValues) {
|
public Uri insert(Uri uri, ContentValues contentValues) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int delete(Uri uri, String s, String[] strings) {
|
public int delete(Uri uri, String s, String[] strings) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
|
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ package net.nullsum.audinaut.provider;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class AudinautWidget4x1 extends AudinautWidgetProvider {
|
public class AudinautWidget4x1 extends AudinautWidgetProvider {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayout() {
|
protected int getLayout() {
|
||||||
return R.layout.appwidget4x1;
|
return R.layout.appwidget4x1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ package net.nullsum.audinaut.provider;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class AudinautWidget4x2 extends AudinautWidgetProvider {
|
public class AudinautWidget4x2 extends AudinautWidgetProvider {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayout() {
|
protected int getLayout() {
|
||||||
return R.layout.appwidget4x2;
|
return R.layout.appwidget4x2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ package net.nullsum.audinaut.provider;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class AudinautWidget4x3 extends AudinautWidgetProvider {
|
public class AudinautWidget4x3 extends AudinautWidgetProvider {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayout() {
|
protected int getLayout() {
|
||||||
return R.layout.appwidget4x3;
|
return R.layout.appwidget4x3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ package net.nullsum.audinaut.provider;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class AudinautWidget4x4 extends AudinautWidgetProvider {
|
public class AudinautWidget4x4 extends AudinautWidgetProvider {
|
||||||
@Override
|
@Override
|
||||||
protected int getLayout() {
|
protected int getLayout() {
|
||||||
return R.layout.appwidget4x4;
|
return R.layout.appwidget4x4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,44 +60,44 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
*/
|
*/
|
||||||
public class AudinautWidgetProvider extends AppWidgetProvider {
|
public class AudinautWidgetProvider extends AppWidgetProvider {
|
||||||
private static final String TAG = AudinautWidgetProvider.class.getSimpleName();
|
private static final String TAG = AudinautWidgetProvider.class.getSimpleName();
|
||||||
private static AudinautWidget4x1 instance4x1;
|
private static AudinautWidget4x1 instance4x1;
|
||||||
private static AudinautWidget4x2 instance4x2;
|
private static AudinautWidget4x2 instance4x2;
|
||||||
private static AudinautWidget4x3 instance4x3;
|
private static AudinautWidget4x3 instance4x3;
|
||||||
private static AudinautWidget4x4 instance4x4;
|
private static AudinautWidget4x4 instance4x4;
|
||||||
|
|
||||||
public static synchronized void notifyInstances(Context context, DownloadService service, boolean playing) {
|
public static synchronized void notifyInstances(Context context, DownloadService service, boolean playing) {
|
||||||
if(instance4x1 == null) {
|
if(instance4x1 == null) {
|
||||||
instance4x1 = new AudinautWidget4x1();
|
instance4x1 = new AudinautWidget4x1();
|
||||||
}
|
}
|
||||||
if(instance4x2 == null) {
|
if(instance4x2 == null) {
|
||||||
instance4x2 = new AudinautWidget4x2();
|
instance4x2 = new AudinautWidget4x2();
|
||||||
}
|
}
|
||||||
if(instance4x3 == null) {
|
if(instance4x3 == null) {
|
||||||
instance4x3 = new AudinautWidget4x3();
|
instance4x3 = new AudinautWidget4x3();
|
||||||
}
|
}
|
||||||
if(instance4x4 == null) {
|
if(instance4x4 == null) {
|
||||||
instance4x4 = new AudinautWidget4x4();
|
instance4x4 = new AudinautWidget4x4();
|
||||||
}
|
}
|
||||||
|
|
||||||
instance4x1.notifyChange(context, service, playing);
|
instance4x1.notifyChange(context, service, playing);
|
||||||
instance4x2.notifyChange(context, service, playing);
|
instance4x2.notifyChange(context, service, playing);
|
||||||
instance4x3.notifyChange(context, service, playing);
|
instance4x3.notifyChange(context, service, playing);
|
||||||
instance4x4.notifyChange(context, service, playing);
|
instance4x4.notifyChange(context, service, playing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||||
defaultAppWidget(context, appWidgetIds);
|
defaultAppWidget(context, appWidgetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnabled(Context context) {
|
public void onEnabled(Context context) {
|
||||||
notifyInstances(context, DownloadService.getInstance(), false);
|
notifyInstances(context, DownloadService.getInstance(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getLayout() {
|
protected int getLayout() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize given widgets to default state, where we launch Subsonic on default click
|
* Initialize given widgets to default state, where we launch Subsonic on default click
|
||||||
@ -108,12 +108,12 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
||||||
|
|
||||||
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text));
|
||||||
if(getLayout() == R.layout.appwidget4x2) {
|
if(getLayout() == R.layout.appwidget4x2) {
|
||||||
views.setTextViewText(R.id.album, "");
|
views.setTextViewText(R.id.album, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
linkButtons(context, views, false);
|
linkButtons(context, views, false);
|
||||||
performUpdate(context, null, appWidgetIds, false);
|
performUpdate(context, null, appWidgetIds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
|
private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) {
|
||||||
@ -151,20 +151,20 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
final Resources res = context.getResources();
|
final Resources res = context.getResources();
|
||||||
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout());
|
||||||
|
|
||||||
if(playing) {
|
if(playing) {
|
||||||
views.setViewVisibility(R.id.widget_root, View.VISIBLE);
|
views.setViewVisibility(R.id.widget_root, View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
// Hide widget
|
// Hide widget
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
if(prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) {
|
if(prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) {
|
||||||
views.setViewVisibility(R.id.widget_root, View.GONE);
|
views.setViewVisibility(R.id.widget_root, View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Entry from current playing DownloadFile
|
// Get Entry from current playing DownloadFile
|
||||||
MusicDirectory.Entry currentPlaying = null;
|
MusicDirectory.Entry currentPlaying = null;
|
||||||
if(service == null) {
|
if(service == null) {
|
||||||
// Deserialize from playling list to setup
|
// Deserialize from playling list to setup
|
||||||
try {
|
try {
|
||||||
PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
||||||
if (state != null && state.currentPlayingIndex != -1) {
|
if (state != null && state.currentPlayingIndex != -1) {
|
||||||
@ -174,12 +174,12 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
Log.e(TAG, "Failed to grab current playing", e);
|
Log.e(TAG, "Failed to grab current playing", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong();
|
||||||
}
|
}
|
||||||
|
|
||||||
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
String title = currentPlaying == null ? null : currentPlaying.getTitle();
|
||||||
CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist();
|
||||||
CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum();
|
||||||
CharSequence errorState = null;
|
CharSequence errorState = null;
|
||||||
|
|
||||||
// Show error message?
|
// Show error message?
|
||||||
@ -195,19 +195,19 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
|
|
||||||
if (errorState != null) {
|
if (errorState != null) {
|
||||||
// Show error state to user
|
// Show error state to user
|
||||||
views.setTextViewText(R.id.title,null);
|
views.setTextViewText(R.id.title,null);
|
||||||
views.setTextViewText(R.id.artist, errorState);
|
views.setTextViewText(R.id.artist, errorState);
|
||||||
views.setTextViewText(R.id.album, "");
|
views.setTextViewText(R.id.album, "");
|
||||||
if(getLayout() != R.layout.appwidget4x1) {
|
if(getLayout() != R.layout.appwidget4x1) {
|
||||||
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No error, so show normal titles
|
// No error, so show normal titles
|
||||||
views.setTextViewText(R.id.title, title);
|
views.setTextViewText(R.id.title, title);
|
||||||
views.setTextViewText(R.id.artist, artist);
|
views.setTextViewText(R.id.artist, artist);
|
||||||
if(getLayout() != R.layout.appwidget4x1) {
|
if(getLayout() != R.layout.appwidget4x1) {
|
||||||
views.setTextViewText(R.id.album, album);
|
views.setTextViewText(R.id.album, album);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set correct drawable for pause state
|
// Set correct drawable for pause state
|
||||||
@ -220,10 +220,10 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
// Set the cover art
|
// Set the cover art
|
||||||
try {
|
try {
|
||||||
boolean large = false;
|
boolean large = false;
|
||||||
if(getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) {
|
if(getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) {
|
||||||
large = true;
|
large = true;
|
||||||
}
|
}
|
||||||
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
|
||||||
Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large);
|
Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large);
|
||||||
|
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
@ -276,9 +276,9 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
* @param playerActive @param playerActive True if player is active in background. Launch {@link net.nullsum.audinaut.activity.SubsonicFragmentActivity}.
|
* @param playerActive @param playerActive True if player is active in background. Launch {@link net.nullsum.audinaut.activity.SubsonicFragmentActivity}.
|
||||||
*/
|
*/
|
||||||
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {
|
private void linkButtons(Context context, RemoteViews views, boolean playerActive) {
|
||||||
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
Intent intent = new Intent(context, SubsonicFragmentActivity.class);
|
||||||
intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
|
intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
||||||
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent);
|
views.setOnClickPendingIntent(R.id.appwidget_coverart, pendingIntent);
|
||||||
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent);
|
views.setOnClickPendingIntent(R.id.appwidget_top, pendingIntent);
|
||||||
@ -286,19 +286,19 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
|
|||||||
// Emulate media button clicks.
|
// Emulate media button clicks.
|
||||||
intent = new Intent("Audinaut.PLAY_PAUSE");
|
intent = new Intent("Audinaut.PLAY_PAUSE");
|
||||||
intent.setComponent(new ComponentName(context, DownloadService.class));
|
intent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
intent.setAction(DownloadService.CMD_TOGGLEPAUSE);
|
intent.setAction(DownloadService.CMD_TOGGLEPAUSE);
|
||||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||||
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
|
views.setOnClickPendingIntent(R.id.control_play, pendingIntent);
|
||||||
|
|
||||||
intent = new Intent("Audinaut.NEXT"); // Use a unique action name to ensure a different PendingIntent to be created.
|
intent = new Intent("Audinaut.NEXT"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||||
intent.setComponent(new ComponentName(context, DownloadService.class));
|
intent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
intent.setAction(DownloadService.CMD_NEXT);
|
intent.setAction(DownloadService.CMD_NEXT);
|
||||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||||
views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
|
views.setOnClickPendingIntent(R.id.control_next, pendingIntent);
|
||||||
|
|
||||||
intent = new Intent("Audinaut.PREVIOUS"); // Use a unique action name to ensure a different PendingIntent to be created.
|
intent = new Intent("Audinaut.PREVIOUS"); // Use a unique action name to ensure a different PendingIntent to be created.
|
||||||
intent.setComponent(new ComponentName(context, DownloadService.class));
|
intent.setComponent(new ComponentName(context, DownloadService.class));
|
||||||
intent.setAction(DownloadService.CMD_PREVIOUS);
|
intent.setAction(DownloadService.CMD_PREVIOUS);
|
||||||
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
pendingIntent = PendingIntent.getService(context, 0, intent, 0);
|
||||||
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);
|
views.setOnClickPendingIntent(R.id.control_previous, pendingIntent);
|
||||||
}
|
}
|
||||||
|
@ -7,41 +7,41 @@ import android.util.Log;
|
|||||||
import net.nullsum.audinaut.service.DownloadService;
|
import net.nullsum.audinaut.service.DownloadService;
|
||||||
|
|
||||||
public class A2dpIntentReceiver extends BroadcastReceiver {
|
public class A2dpIntentReceiver extends BroadcastReceiver {
|
||||||
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse";
|
||||||
private String TAG = A2dpIntentReceiver.class.getSimpleName();
|
private String TAG = A2dpIntentReceiver.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
Log.i(TAG, "GOT INTENT " + intent);
|
Log.i(TAG, "GOT INTENT " + intent);
|
||||||
|
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
|
|
||||||
if (downloadService != null){
|
if (downloadService != null){
|
||||||
|
|
||||||
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE);
|
||||||
|
|
||||||
avrcpIntent.putExtra("duration", (long) downloadService.getPlayerDuration());
|
avrcpIntent.putExtra("duration", (long) downloadService.getPlayerDuration());
|
||||||
avrcpIntent.putExtra("position", (long) downloadService.getPlayerPosition());
|
avrcpIntent.putExtra("position", (long) downloadService.getPlayerPosition());
|
||||||
avrcpIntent.putExtra("ListSize", (long) downloadService.getSongs().size());
|
avrcpIntent.putExtra("ListSize", (long) downloadService.getSongs().size());
|
||||||
|
|
||||||
switch (downloadService.getPlayerState()){
|
switch (downloadService.getPlayerState()){
|
||||||
case STARTED:
|
case STARTED:
|
||||||
avrcpIntent.putExtra("playing", true);
|
avrcpIntent.putExtra("playing", true);
|
||||||
break;
|
break;
|
||||||
case STOPPED:
|
case STOPPED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
avrcpIntent.putExtra("playing", false);
|
||||||
break;
|
break;
|
||||||
case PAUSED:
|
case PAUSED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
avrcpIntent.putExtra("playing", false);
|
||||||
break;
|
break;
|
||||||
case COMPLETED:
|
case COMPLETED:
|
||||||
avrcpIntent.putExtra("playing", false);
|
avrcpIntent.putExtra("playing", false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.sendBroadcast(avrcpIntent);
|
context.sendBroadcast(avrcpIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.receiver;
|
package net.nullsum.audinaut.receiver;
|
||||||
@ -28,24 +28,24 @@ import net.nullsum.audinaut.util.Constants;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class AudioNoisyReceiver extends BroadcastReceiver {
|
public class AudioNoisyReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = AudioNoisyReceiver.class.getSimpleName();
|
private static final String TAG = AudioNoisyReceiver.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
// Don't do anything if downloadService is not started
|
// Don't do anything if downloadService is not started
|
||||||
if(downloadService == null) {
|
if(downloadService == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals (intent.getAction ())) {
|
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals (intent.getAction ())) {
|
||||||
if((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) {
|
if((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) {
|
||||||
SharedPreferences prefs = Util.getPreferences(downloadService);
|
SharedPreferences prefs = Util.getPreferences(downloadService);
|
||||||
int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0"));
|
int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0"));
|
||||||
if(pausePref == 0) {
|
if(pausePref == 0) {
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.receiver;
|
package net.nullsum.audinaut.receiver;
|
||||||
@ -23,12 +23,12 @@ import net.nullsum.audinaut.service.HeadphoneListenerService;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class BootReceiver extends BroadcastReceiver {
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(Util.shouldStartOnHeadphones(context)) {
|
if(Util.shouldStartOnHeadphones(context)) {
|
||||||
Intent serviceIntent = new Intent();
|
Intent serviceIntent = new Intent();
|
||||||
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName());
|
||||||
context.startService(serviceIntent);
|
context.startService(serviceIntent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.receiver;
|
package net.nullsum.audinaut.receiver;
|
||||||
@ -24,17 +24,17 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class HeadphonePlugReceiver extends BroadcastReceiver {
|
public class HeadphonePlugReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = HeadphonePlugReceiver.class.getSimpleName();
|
private static final String TAG = HeadphonePlugReceiver.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
|
if(Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) {
|
||||||
int headphoneState = intent.getIntExtra("state", -1);
|
int headphoneState = intent.getIntExtra("state", -1);
|
||||||
if(headphoneState == 1 && Util.shouldStartOnHeadphones(context)) {
|
if(headphoneState == 1 && Util.shouldStartOnHeadphones(context)) {
|
||||||
Intent start = new Intent(context, DownloadService.class);
|
Intent start = new Intent(context, DownloadService.class);
|
||||||
start.setAction(DownloadService.START_PLAY);
|
start.setAction(DownloadService.START_PLAY);
|
||||||
context.startService(start);
|
context.startService(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,22 +36,22 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||||
if(DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP ||
|
if(DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP ||
|
||||||
event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
|
event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
|
||||||
Log.w(TAG, "Ignore keycode event because downloadService is off");
|
Log.w(TAG, "Ignore keycode event because downloadService is off");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
|
Log.i(TAG, "Got MEDIA_BUTTON key event: " + event);
|
||||||
|
|
||||||
Intent serviceIntent = new Intent(context, DownloadService.class);
|
Intent serviceIntent = new Intent(context, DownloadService.class);
|
||||||
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
serviceIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
||||||
context.startService(serviceIntent);
|
context.startService(serviceIntent);
|
||||||
if (isOrderedBroadcast()) {
|
if (isOrderedBroadcast()) {
|
||||||
try {
|
try {
|
||||||
abortBroadcast();
|
abortBroadcast();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
// Ignored.
|
// Ignored.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.receiver;
|
package net.nullsum.audinaut.receiver;
|
||||||
@ -25,22 +25,22 @@ import net.nullsum.audinaut.service.DownloadService;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public class PlayActionReceiver extends BroadcastReceiver {
|
public class PlayActionReceiver extends BroadcastReceiver {
|
||||||
private static final String TAG = PlayActionReceiver.class.getSimpleName();
|
private static final String TAG = PlayActionReceiver.class.getSimpleName();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if(intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
|
if(intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
|
||||||
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
|
||||||
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
|
||||||
|
|
||||||
Intent start = new Intent(context, DownloadService.class);
|
Intent start = new Intent(context, DownloadService.class);
|
||||||
start.setAction(DownloadService.START_PLAY);
|
start.setAction(DownloadService.START_PLAY);
|
||||||
start.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, startShuffled);
|
start.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, startShuffled);
|
||||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
|
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
|
||||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
|
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
|
||||||
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
|
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
|
||||||
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, data.getInt(Constants.PREFERENCES_KEY_OFFLINE));
|
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, data.getInt(Constants.PREFERENCES_KEY_OFFLINE));
|
||||||
context.startService(start);
|
context.startService(start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -53,378 +53,378 @@ import static net.nullsum.audinaut.domain.PlayerState.PREPARING;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class DownloadServiceLifecycleSupport {
|
public class DownloadServiceLifecycleSupport {
|
||||||
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName();
|
||||||
public static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser";
|
public static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser";
|
||||||
private static final int DEBOUNCE_TIME = 200;
|
private static final int DEBOUNCE_TIME = 200;
|
||||||
|
|
||||||
private final DownloadService downloadService;
|
private final DownloadService downloadService;
|
||||||
private Looper eventLooper;
|
private Looper eventLooper;
|
||||||
private Handler eventHandler;
|
private Handler eventHandler;
|
||||||
private BroadcastReceiver ejectEventReceiver;
|
private BroadcastReceiver ejectEventReceiver;
|
||||||
private PhoneStateListener phoneStateListener;
|
private PhoneStateListener phoneStateListener;
|
||||||
private boolean externalStorageAvailable= true;
|
private boolean externalStorageAvailable= true;
|
||||||
private ReentrantLock lock = new ReentrantLock();
|
private ReentrantLock lock = new ReentrantLock();
|
||||||
private final AtomicBoolean setup = new AtomicBoolean(false);
|
private final AtomicBoolean setup = new AtomicBoolean(false);
|
||||||
private long lastPressTime = 0;
|
private long lastPressTime = 0;
|
||||||
private SilentBackgroundTask<Void> currentSavePlayQueueTask = null;
|
private SilentBackgroundTask<Void> currentSavePlayQueueTask = null;
|
||||||
private Date lastChange = null;
|
private Date lastChange = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This receiver manages the intent that could come from other applications.
|
* This receiver manages the intent that could come from other applications.
|
||||||
*/
|
*/
|
||||||
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
|
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
Log.i(TAG, "intentReceiver.onReceive: " + action);
|
||||||
if (DownloadService.CMD_PLAY.equals(action)) {
|
if (DownloadService.CMD_PLAY.equals(action)) {
|
||||||
downloadService.play();
|
downloadService.play();
|
||||||
} else if (DownloadService.CMD_NEXT.equals(action)) {
|
} else if (DownloadService.CMD_NEXT.equals(action)) {
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
} else if (DownloadService.CMD_PREVIOUS.equals(action)) {
|
} else if (DownloadService.CMD_PREVIOUS.equals(action)) {
|
||||||
downloadService.previous();
|
downloadService.previous();
|
||||||
} else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
} else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
||||||
downloadService.togglePlayPause();
|
downloadService.togglePlayPause();
|
||||||
} else if (DownloadService.CMD_PAUSE.equals(action)) {
|
} else if (DownloadService.CMD_PAUSE.equals(action)) {
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
} else if (DownloadService.CMD_STOP.equals(action)) {
|
} else if (DownloadService.CMD_STOP.equals(action)) {
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
downloadService.seekTo(0);
|
downloadService.seekTo(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public DownloadServiceLifecycleSupport(DownloadService downloadService) {
|
public DownloadServiceLifecycleSupport(DownloadService downloadService) {
|
||||||
this.downloadService = downloadService;
|
this.downloadService = downloadService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
eventLooper = Looper.myLooper();
|
eventLooper = Looper.myLooper();
|
||||||
eventHandler = new Handler(eventLooper);
|
eventHandler = new Handler(eventLooper);
|
||||||
|
|
||||||
// Deserialize queue before starting looper
|
// Deserialize queue before starting looper
|
||||||
try {
|
try {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
deserializeDownloadQueueNow();
|
deserializeDownloadQueueNow();
|
||||||
|
|
||||||
// Wait until PREPARING is done to mark lifecycle as ready to receive events
|
// Wait until PREPARING is done to mark lifecycle as ready to receive events
|
||||||
while(downloadService.getPlayerState() == PREPARING) {
|
while(downloadService.getPlayerState() == PREPARING) {
|
||||||
Util.sleepQuietly(50L);
|
Util.sleepQuietly(50L);
|
||||||
}
|
}
|
||||||
|
|
||||||
setup.set(true);
|
setup.set(true);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
Looper.loop();
|
Looper.loop();
|
||||||
}
|
}
|
||||||
}, "DownloadServiceLifecycleSupport").start();
|
}, "DownloadServiceLifecycleSupport").start();
|
||||||
|
|
||||||
// Stop when SD card is ejected.
|
// Stop when SD card is ejected.
|
||||||
ejectEventReceiver = new BroadcastReceiver() {
|
ejectEventReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
|
externalStorageAvailable = Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction());
|
||||||
if (!externalStorageAvailable) {
|
if (!externalStorageAvailable) {
|
||||||
Log.i(TAG, "External media is ejecting. Stopping playback.");
|
Log.i(TAG, "External media is ejecting. Stopping playback.");
|
||||||
downloadService.reset();
|
downloadService.reset();
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "External media is available.");
|
Log.i(TAG, "External media is available.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
|
IntentFilter ejectFilter = new IntentFilter(Intent.ACTION_MEDIA_EJECT);
|
||||||
ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
ejectFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||||
ejectFilter.addDataScheme("file");
|
ejectFilter.addDataScheme("file");
|
||||||
downloadService.registerReceiver(ejectEventReceiver, ejectFilter);
|
downloadService.registerReceiver(ejectEventReceiver, ejectFilter);
|
||||||
|
|
||||||
// React to media buttons.
|
// React to media buttons.
|
||||||
Util.registerMediaButtonEventReceiver(downloadService);
|
Util.registerMediaButtonEventReceiver(downloadService);
|
||||||
|
|
||||||
// Pause temporarily on incoming phone calls.
|
// Pause temporarily on incoming phone calls.
|
||||||
phoneStateListener = new MyPhoneStateListener();
|
phoneStateListener = new MyPhoneStateListener();
|
||||||
|
|
||||||
// Android 6.0 removes requirement for android.Manifest.permission.READ_PHONE_STATE;
|
// Android 6.0 removes requirement for android.Manifest.permission.READ_PHONE_STATE;
|
||||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||||
|
|
||||||
// Register the handler for outside intents.
|
// Register the handler for outside intents.
|
||||||
IntentFilter commandFilter = new IntentFilter();
|
IntentFilter commandFilter = new IntentFilter();
|
||||||
commandFilter.addAction(DownloadService.CMD_PLAY);
|
commandFilter.addAction(DownloadService.CMD_PLAY);
|
||||||
commandFilter.addAction(DownloadService.CMD_TOGGLEPAUSE);
|
commandFilter.addAction(DownloadService.CMD_TOGGLEPAUSE);
|
||||||
commandFilter.addAction(DownloadService.CMD_PAUSE);
|
commandFilter.addAction(DownloadService.CMD_PAUSE);
|
||||||
commandFilter.addAction(DownloadService.CMD_STOP);
|
commandFilter.addAction(DownloadService.CMD_STOP);
|
||||||
commandFilter.addAction(DownloadService.CMD_PREVIOUS);
|
commandFilter.addAction(DownloadService.CMD_PREVIOUS);
|
||||||
commandFilter.addAction(DownloadService.CMD_NEXT);
|
commandFilter.addAction(DownloadService.CMD_NEXT);
|
||||||
commandFilter.addAction(DownloadService.CANCEL_DOWNLOADS);
|
commandFilter.addAction(DownloadService.CANCEL_DOWNLOADS);
|
||||||
downloadService.registerReceiver(intentReceiver, commandFilter);
|
downloadService.registerReceiver(intentReceiver, commandFilter);
|
||||||
|
|
||||||
new CacheCleaner(downloadService, downloadService).clean();
|
new CacheCleaner(downloadService, downloadService).clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return setup.get();
|
return setup.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStart(final Intent intent) {
|
public void onStart(final Intent intent) {
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
final String action = intent.getAction();
|
final String action = intent.getAction();
|
||||||
|
|
||||||
if(eventHandler == null) {
|
if(eventHandler == null) {
|
||||||
Util.sleepQuietly(100L);
|
Util.sleepQuietly(100L);
|
||||||
}
|
}
|
||||||
if(eventHandler == null) {
|
if(eventHandler == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if(!setup.get()) {
|
if(!setup.get()) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(DownloadService.START_PLAY.equals(action)) {
|
if(DownloadService.START_PLAY.equals(action)) {
|
||||||
int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0);
|
||||||
if(offlinePref != 0) {
|
if(offlinePref != 0) {
|
||||||
boolean offline = (offlinePref == 2);
|
boolean offline = (offlinePref == 2);
|
||||||
Util.setOffline(downloadService, offline);
|
Util.setOffline(downloadService, offline);
|
||||||
if (offline) {
|
if (offline) {
|
||||||
downloadService.clearIncomplete();
|
downloadService.clearIncomplete();
|
||||||
} else {
|
} else {
|
||||||
downloadService.checkDownloads();
|
downloadService.checkDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) {
|
if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) {
|
||||||
// Add shuffle parameters
|
// Add shuffle parameters
|
||||||
SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit();
|
SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit();
|
||||||
String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR);
|
String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR);
|
||||||
if(startYear != null) {
|
if(startYear != null) {
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR);
|
String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR);
|
||||||
if(endYear != null) {
|
if(endYear != null) {
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear);
|
||||||
}
|
}
|
||||||
|
|
||||||
String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE);
|
String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE);
|
||||||
if(genre != null) {
|
if(genre != null) {
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre);
|
||||||
}
|
}
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
downloadService.clear();
|
downloadService.clear();
|
||||||
downloadService.setShufflePlayEnabled(true);
|
downloadService.setShufflePlayEnabled(true);
|
||||||
} else {
|
} else {
|
||||||
downloadService.start();
|
downloadService.start();
|
||||||
}
|
}
|
||||||
} else if(DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
} else if(DownloadService.CMD_TOGGLEPAUSE.equals(action)) {
|
||||||
downloadService.togglePlayPause();
|
downloadService.togglePlayPause();
|
||||||
} else if(DownloadService.CMD_NEXT.equals(action)) {
|
} else if(DownloadService.CMD_NEXT.equals(action)) {
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
} else if(DownloadService.CMD_PREVIOUS.equals(action)) {
|
} else if(DownloadService.CMD_PREVIOUS.equals(action)) {
|
||||||
downloadService.previous();
|
downloadService.previous();
|
||||||
} else if(DownloadService.CANCEL_DOWNLOADS.equals(action)) {
|
} else if(DownloadService.CANCEL_DOWNLOADS.equals(action)) {
|
||||||
downloadService.clearBackground();
|
downloadService.clearBackground();
|
||||||
} else if(intent.getExtras() != null) {
|
} else if(intent.getExtras() != null) {
|
||||||
final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
handleKeyEvent(event);
|
handleKeyEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
serializeDownloadQueue();
|
serializeDownloadQueue();
|
||||||
eventLooper.quit();
|
eventLooper.quit();
|
||||||
downloadService.unregisterReceiver(ejectEventReceiver);
|
downloadService.unregisterReceiver(ejectEventReceiver);
|
||||||
downloadService.unregisterReceiver(intentReceiver);
|
downloadService.unregisterReceiver(intentReceiver);
|
||||||
|
|
||||||
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
TelephonyManager telephonyManager = (TelephonyManager) downloadService.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExternalStorageAvailable() {
|
public boolean isExternalStorageAvailable() {
|
||||||
return externalStorageAvailable;
|
return externalStorageAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serializeDownloadQueue() {
|
public void serializeDownloadQueue() {
|
||||||
serializeDownloadQueue(true);
|
serializeDownloadQueue(true);
|
||||||
}
|
}
|
||||||
public void serializeDownloadQueue(final boolean serializeRemote) {
|
public void serializeDownloadQueue(final boolean serializeRemote) {
|
||||||
if(!setup.get()) {
|
if(!setup.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<DownloadFile> songs = new ArrayList<DownloadFile>(downloadService.getSongs());
|
final List<DownloadFile> songs = new ArrayList<DownloadFile>(downloadService.getSongs());
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if(lock.tryLock()) {
|
if(lock.tryLock()) {
|
||||||
try {
|
try {
|
||||||
serializeDownloadQueueNow(songs, serializeRemote);
|
serializeDownloadQueueNow(songs, serializeRemote);
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serializeDownloadQueueNow(List<DownloadFile> songs, boolean serializeRemote) {
|
public void serializeDownloadQueueNow(List<DownloadFile> songs, boolean serializeRemote) {
|
||||||
final PlayerQueue state = new PlayerQueue();
|
final PlayerQueue state = new PlayerQueue();
|
||||||
for (DownloadFile downloadFile : songs) {
|
for (DownloadFile downloadFile : songs) {
|
||||||
state.songs.add(downloadFile.getSong());
|
state.songs.add(downloadFile.getSong());
|
||||||
}
|
}
|
||||||
for (DownloadFile downloadFile : downloadService.getToDelete()) {
|
for (DownloadFile downloadFile : downloadService.getToDelete()) {
|
||||||
state.toDelete.add(downloadFile.getSong());
|
state.toDelete.add(downloadFile.getSong());
|
||||||
}
|
}
|
||||||
state.currentPlayingIndex = downloadService.getCurrentPlayingIndex();
|
state.currentPlayingIndex = downloadService.getCurrentPlayingIndex();
|
||||||
state.currentPlayingPosition = downloadService.getPlayerPosition();
|
state.currentPlayingPosition = downloadService.getPlayerPosition();
|
||||||
|
|
||||||
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
||||||
if(currentPlaying != null) {
|
if(currentPlaying != null) {
|
||||||
state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable();
|
state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable();
|
||||||
}
|
}
|
||||||
state.changed = lastChange = new Date();
|
state.changed = lastChange = new Date();
|
||||||
|
|
||||||
Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||||
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
|
FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void post(Runnable runnable) {
|
public void post(Runnable runnable) {
|
||||||
eventHandler.post(runnable);
|
eventHandler.post(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deserializeDownloadQueueNow() {
|
private void deserializeDownloadQueueNow() {
|
||||||
PlayerQueue state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
PlayerQueue state = FileUtil.deserialize(downloadService, FILENAME_DOWNLOADS_SER, PlayerQueue.class);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition);
|
||||||
|
|
||||||
// Rename first thing before anything else starts
|
// Rename first thing before anything else starts
|
||||||
if(state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) {
|
if(state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) {
|
||||||
DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false);
|
DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false);
|
||||||
currentPlaying.renamePartial();
|
currentPlaying.renamePartial();
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadService.restore(state.songs, state.toDelete, state.currentPlayingIndex, state.currentPlayingPosition);
|
downloadService.restore(state.songs, state.toDelete, state.currentPlayingIndex, state.currentPlayingPosition);
|
||||||
|
|
||||||
if(state != null) {
|
if(state != null) {
|
||||||
lastChange = state.changed;
|
lastChange = state.changed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getLastChange() {
|
public Date getLastChange() {
|
||||||
return lastChange;
|
return lastChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleKeyEvent(KeyEvent event) {
|
public void handleKeyEvent(KeyEvent event) {
|
||||||
if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) {
|
if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) {
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
downloadService.fastForward();
|
downloadService.fastForward();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
downloadService.rewind();
|
downloadService.rewind();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(event.getAction() == KeyEvent.ACTION_UP) {
|
} else if(event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - 500)) {
|
if(lastPressTime < (System.currentTimeMillis() - 500)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.togglePlayPause();
|
downloadService.togglePlayPause();
|
||||||
} else {
|
} else {
|
||||||
downloadService.next(false, true);
|
downloadService.next(false, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.previous();
|
downloadService.previous();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||||
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) {
|
||||||
lastPressTime = System.currentTimeMillis();
|
lastPressTime = System.currentTimeMillis();
|
||||||
downloadService.next();
|
downloadService.next();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||||
downloadService.rewind();
|
downloadService.rewind();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||||||
downloadService.fastForward();
|
downloadService.fastForward();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||||
downloadService.stop();
|
downloadService.stop();
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||||
if(downloadService.getPlayerState() != PlayerState.STARTED) {
|
if(downloadService.getPlayerState() != PlayerState.STARTED) {
|
||||||
downloadService.start();
|
downloadService.start();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||||
downloadService.pause();
|
downloadService.pause();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logic taken from packages/apps/Music. Will pause when an incoming
|
* Logic taken from packages/apps/Music. Will pause when an incoming
|
||||||
* call rings or if a call (incoming or outgoing) is connected.
|
* call rings or if a call (incoming or outgoing) is connected.
|
||||||
*/
|
*/
|
||||||
private class MyPhoneStateListener extends PhoneStateListener {
|
private class MyPhoneStateListener extends PhoneStateListener {
|
||||||
private boolean resumeAfterCall;
|
private boolean resumeAfterCall;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCallStateChanged(final int state, String incomingNumber) {
|
public void onCallStateChanged(final int state, String incomingNumber) {
|
||||||
eventHandler.post(new Runnable() {
|
eventHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case TelephonyManager.CALL_STATE_RINGING:
|
case TelephonyManager.CALL_STATE_RINGING:
|
||||||
case TelephonyManager.CALL_STATE_OFFHOOK:
|
case TelephonyManager.CALL_STATE_OFFHOOK:
|
||||||
if (downloadService.getPlayerState() == PlayerState.STARTED) {
|
if (downloadService.getPlayerState() == PlayerState.STARTED) {
|
||||||
resumeAfterCall = true;
|
resumeAfterCall = true;
|
||||||
downloadService.pause(true);
|
downloadService.pause(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TelephonyManager.CALL_STATE_IDLE:
|
case TelephonyManager.CALL_STATE_IDLE:
|
||||||
if (resumeAfterCall) {
|
if (resumeAfterCall) {
|
||||||
resumeAfterCall = false;
|
resumeAfterCall = false;
|
||||||
if(downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) {
|
if(downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) {
|
||||||
downloadService.start();
|
downloadService.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.service;
|
package net.nullsum.audinaut.service;
|
||||||
@ -27,40 +27,40 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
* Created by Scott on 4/6/2015.
|
* Created by Scott on 4/6/2015.
|
||||||
*/
|
*/
|
||||||
public class HeadphoneListenerService extends Service {
|
public class HeadphoneListenerService extends Service {
|
||||||
private HeadphonePlugReceiver receiver;
|
private HeadphonePlugReceiver receiver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
receiver = new HeadphonePlugReceiver();
|
receiver = new HeadphonePlugReceiver();
|
||||||
registerReceiver(receiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
|
registerReceiver(receiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
if(!Util.shouldStartOnHeadphones(this)) {
|
if(!Util.shouldStartOnHeadphones(this)) {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Service.START_STICKY;
|
return Service.START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(receiver != null) {
|
if(receiver != null) {
|
||||||
unregisterReceiver(receiver);
|
unregisterReceiver(receiver);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,24 +36,24 @@ import net.nullsum.audinaut.util.Util;
|
|||||||
*/
|
*/
|
||||||
public class MediaStoreService {
|
public class MediaStoreService {
|
||||||
|
|
||||||
private static final String TAG = MediaStoreService.class.getSimpleName();
|
private static final String TAG = MediaStoreService.class.getSimpleName();
|
||||||
private static final Uri ALBUM_ART_URI = Uri.parse("content://media/external/audio/albumart");
|
private static final Uri ALBUM_ART_URI = Uri.parse("content://media/external/audio/albumart");
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
public MediaStoreService(Context context) {
|
public MediaStoreService(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveInMediaStore(DownloadFile downloadFile) {
|
public void saveInMediaStore(DownloadFile downloadFile) {
|
||||||
MusicDirectory.Entry song = downloadFile.getSong();
|
MusicDirectory.Entry song = downloadFile.getSong();
|
||||||
File songFile = downloadFile.getCompleteFile();
|
File songFile = downloadFile.getCompleteFile();
|
||||||
|
|
||||||
// Delete existing row in case the song has been downloaded before.
|
// Delete existing row in case the song has been downloaded before.
|
||||||
deleteFromMediaStore(downloadFile);
|
deleteFromMediaStore(downloadFile);
|
||||||
|
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(MediaStore.MediaColumns.TITLE, song.getTitle());
|
values.put(MediaStore.MediaColumns.TITLE, song.getTitle());
|
||||||
values.put(MediaStore.MediaColumns.DATA, songFile.getAbsolutePath());
|
values.put(MediaStore.MediaColumns.DATA, songFile.getAbsolutePath());
|
||||||
values.put(MediaStore.Audio.AudioColumns.ARTIST, song.getArtist());
|
values.put(MediaStore.Audio.AudioColumns.ARTIST, song.getArtist());
|
||||||
@ -84,68 +84,68 @@ public class MediaStoreService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteFromMediaStore(DownloadFile downloadFile) {
|
public void deleteFromMediaStore(DownloadFile downloadFile) {
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
MusicDirectory.Entry song = downloadFile.getSong();
|
MusicDirectory.Entry song = downloadFile.getSong();
|
||||||
File file = downloadFile.getCompleteFile();
|
File file = downloadFile.getCompleteFile();
|
||||||
|
|
||||||
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
|
||||||
int n = contentResolver.delete(uri,
|
int n = contentResolver.delete(uri,
|
||||||
MediaStore.MediaColumns.DATA + "=?",
|
MediaStore.MediaColumns.DATA + "=?",
|
||||||
new String[]{file.getAbsolutePath()});
|
new String[]{file.getAbsolutePath()});
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
Log.i(TAG, "Deleting media store row for " + song);
|
Log.i(TAG, "Deleting media store row for " + song);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteFromMediaStore(File file) {
|
public void deleteFromMediaStore(File file) {
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
|
|
||||||
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||||
|
|
||||||
int n = contentResolver.delete(uri,
|
int n = contentResolver.delete(uri,
|
||||||
MediaStore.MediaColumns.DATA + "=?",
|
MediaStore.MediaColumns.DATA + "=?",
|
||||||
new String[]{file.getAbsolutePath()});
|
new String[]{file.getAbsolutePath()});
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
Log.i(TAG, "Deleting media store row for " + file);
|
Log.i(TAG, "Deleting media store row for " + file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renameInMediaStore(File start, File end) {
|
public void renameInMediaStore(File start, File end) {
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(MediaStore.MediaColumns.DATA, end.getAbsolutePath());
|
values.put(MediaStore.MediaColumns.DATA, end.getAbsolutePath());
|
||||||
|
|
||||||
int n = contentResolver.update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
int n = contentResolver.update(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||||
values,
|
values,
|
||||||
MediaStore.MediaColumns.DATA + "=?",
|
MediaStore.MediaColumns.DATA + "=?",
|
||||||
new String[]{start.getAbsolutePath()});
|
new String[]{start.getAbsolutePath()});
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
Log.i(TAG, "Rename media store row for " + start + " to " + end);
|
Log.i(TAG, "Rename media store row for " + start + " to " + end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertAlbumArt(int albumId, DownloadFile downloadFile) {
|
private void insertAlbumArt(int albumId, DownloadFile downloadFile) {
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
|
|
||||||
Cursor cursor = contentResolver.query(Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId)), null, null, null, null);
|
Cursor cursor = contentResolver.query(Uri.withAppendedPath(ALBUM_ART_URI, String.valueOf(albumId)), null, null, null, null);
|
||||||
if (!cursor.moveToFirst()) {
|
if (!cursor.moveToFirst()) {
|
||||||
|
|
||||||
// No album art found, add it.
|
// No album art found, add it.
|
||||||
File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
|
File albumArtFile = FileUtil.getAlbumArtFile(context, downloadFile.getSong());
|
||||||
if (albumArtFile.exists()) {
|
if (albumArtFile.exists()) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId);
|
values.put(MediaStore.Audio.AlbumColumns.ALBUM_ID, albumId);
|
||||||
values.put(MediaStore.MediaColumns.DATA, albumArtFile.getPath());
|
values.put(MediaStore.MediaColumns.DATA, albumArtFile.getPath());
|
||||||
contentResolver.insert(ALBUM_ART_URI, values);
|
contentResolver.insert(ALBUM_ART_URI, values);
|
||||||
Log.i(TAG, "Added album art: " + albumArtFile);
|
Log.i(TAG, "Added album art: " + albumArtFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,9 @@ public interface MusicService {
|
|||||||
|
|
||||||
MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception;
|
SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
@ -62,40 +62,40 @@ public interface MusicService {
|
|||||||
|
|
||||||
void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception;
|
void createPlaylist(String id, String name, List<MusicDirectory.Entry> entries, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception;
|
void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void addToPlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
|
void addToPlaylist(String id, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception;
|
void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void overwritePlaylist(String id, String name, int toRemove, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
|
void overwritePlaylist(String id, String name, int toRemove, List<MusicDirectory.Entry> toAdd, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception;
|
void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception;
|
||||||
MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
||||||
|
|
||||||
Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception;
|
Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception;
|
||||||
|
|
||||||
List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
|
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
|
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception;
|
||||||
|
|
||||||
void savePlayQueue(List<MusicDirectory.Entry> songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception;
|
void savePlayQueue(List<MusicDirectory.Entry> songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception;
|
PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception;
|
||||||
|
|
||||||
void setInstance(Integer instance) throws Exception;
|
void setInstance(Integer instance) throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -62,19 +62,19 @@ import java.util.SortedSet;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class OfflineMusicService implements MusicService {
|
public class OfflineMusicService implements MusicService {
|
||||||
private static final String TAG = OfflineMusicService.class.getSimpleName();
|
private static final String TAG = OfflineMusicService.class.getSimpleName();
|
||||||
private static final String ERRORMSG = "Not available in offline mode";
|
private static final String ERRORMSG = "Not available in offline mode";
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ping(Context context, ProgressListener progressListener) throws Exception {
|
public void ping(Context context, ProgressListener progressListener) throws Exception {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<Artist>();
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
for (File file : FileUtil.listFiles(root)) {
|
for (File file : FileUtil.listFiles(root)) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
@ -84,47 +84,47 @@ public class OfflineMusicService implements MusicService {
|
|||||||
artist.setName(file.getName());
|
artist.setName(file.getName());
|
||||||
artists.add(artist);
|
artists.add(artist);
|
||||||
} else if(!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) {
|
} else if(!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) {
|
||||||
entries.add(createEntry(context, file));
|
entries.add(createEntry(context, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Indexes indexes = new Indexes(0L, Collections.<Artist>emptyList(), artists, entries);
|
Indexes indexes = new Indexes(0L, Collections.<Artist>emptyList(), artists, entries);
|
||||||
return indexes;
|
return indexes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
return getMusicDirectory(id, artistName, refresh, context, progressListener, false);
|
return getMusicDirectory(id, artistName, refresh, context, progressListener, false);
|
||||||
}
|
}
|
||||||
private MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener, boolean isPodcast) throws Exception {
|
private MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener, boolean isPodcast) throws Exception {
|
||||||
File dir = new File(id);
|
File dir = new File(id);
|
||||||
MusicDirectory result = new MusicDirectory();
|
MusicDirectory result = new MusicDirectory();
|
||||||
result.setName(dir.getName());
|
result.setName(dir.getName());
|
||||||
|
|
||||||
Set<String> names = new HashSet<String>();
|
Set<String> names = new HashSet<String>();
|
||||||
|
|
||||||
for (File file : FileUtil.listMediaFiles(dir)) {
|
for (File file : FileUtil.listMediaFiles(dir)) {
|
||||||
String name = getName(file);
|
String name = getName(file);
|
||||||
if (name != null & !names.contains(name)) {
|
if (name != null & !names.contains(name)) {
|
||||||
names.add(name);
|
names.add(name);
|
||||||
result.addChild(createEntry(context, file, name, true, isPodcast));
|
result.addChild(createEntry(context, file, name, true, isPodcast));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
result.sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getName(File file) {
|
private String getName(File file) {
|
||||||
String name = file.getName();
|
String name = file.getName();
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
return name;
|
return name;
|
||||||
@ -138,401 +138,401 @@ public class OfflineMusicService implements MusicService {
|
|||||||
return FileUtil.getBaseName(name);
|
return FileUtil.getBaseName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Entry createEntry(Context context, File file) {
|
private Entry createEntry(Context context, File file) {
|
||||||
return createEntry(context, file, getName(file));
|
return createEntry(context, file, getName(file));
|
||||||
}
|
}
|
||||||
private Entry createEntry(Context context, File file, String name) {
|
private Entry createEntry(Context context, File file, String name) {
|
||||||
return createEntry(context, file, name, true);
|
return createEntry(context, file, name, true);
|
||||||
}
|
}
|
||||||
private Entry createEntry(Context context, File file, String name, boolean load) {
|
private Entry createEntry(Context context, File file, String name, boolean load) {
|
||||||
return createEntry(context, file, name, load, false);
|
return createEntry(context, file, name, load, false);
|
||||||
}
|
}
|
||||||
private Entry createEntry(Context context, File file, String name, boolean load, boolean isPodcast) {
|
private Entry createEntry(Context context, File file, String name, boolean load, boolean isPodcast) {
|
||||||
Entry entry;
|
Entry entry;
|
||||||
entry = new Entry();
|
entry = new Entry();
|
||||||
entry.setDirectory(file.isDirectory());
|
entry.setDirectory(file.isDirectory());
|
||||||
entry.setId(file.getPath());
|
entry.setId(file.getPath());
|
||||||
entry.setParent(file.getParent());
|
entry.setParent(file.getParent());
|
||||||
entry.setSize(file.length());
|
entry.setSize(file.length());
|
||||||
String root = FileUtil.getMusicDirectory(context).getPath();
|
String root = FileUtil.getMusicDirectory(context).getPath();
|
||||||
if(!file.getParentFile().getParentFile().getPath().equals(root)) {
|
if(!file.getParentFile().getParentFile().getPath().equals(root)) {
|
||||||
entry.setGrandParent(file.getParentFile().getParent());
|
entry.setGrandParent(file.getParentFile().getParent());
|
||||||
}
|
}
|
||||||
entry.setPath(file.getPath().replaceFirst("^" + root + "/" , ""));
|
entry.setPath(file.getPath().replaceFirst("^" + root + "/" , ""));
|
||||||
String title = name;
|
String title = name;
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
File artistFolder = file.getParentFile().getParentFile();
|
File artistFolder = file.getParentFile().getParentFile();
|
||||||
File albumFolder = file.getParentFile();
|
File albumFolder = file.getParentFile();
|
||||||
if(artistFolder.getPath().equals(root)) {
|
if(artistFolder.getPath().equals(root)) {
|
||||||
entry.setArtist(albumFolder.getName());
|
entry.setArtist(albumFolder.getName());
|
||||||
} else {
|
} else {
|
||||||
entry.setArtist(artistFolder.getName());
|
entry.setArtist(artistFolder.getName());
|
||||||
}
|
}
|
||||||
entry.setAlbum(albumFolder.getName());
|
entry.setAlbum(albumFolder.getName());
|
||||||
|
|
||||||
int index = name.indexOf('-');
|
int index = name.indexOf('-');
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
try {
|
try {
|
||||||
entry.setTrack(Integer.parseInt(name.substring(0, index)));
|
entry.setTrack(Integer.parseInt(name.substring(0, index)));
|
||||||
title = title.substring(index + 1);
|
title = title.substring(index + 1);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Failed parseInt, just means track filled out
|
// Failed parseInt, just means track filled out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(load) {
|
if(load) {
|
||||||
entry.loadMetadata(file);
|
entry.loadMetadata(file);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.setTitle(title);
|
|
||||||
entry.setSuffix(FileUtil.getExtension(file.getName().replace(".complete", "")));
|
|
||||||
|
|
||||||
File albumArt = FileUtil.getAlbumArtFile(context, entry);
|
|
||||||
if (albumArt.exists()) {
|
|
||||||
entry.setCoverArt(albumArt.getPath());
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getCoverArt(Context context, Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
|
||||||
try {
|
|
||||||
return FileUtil.getAlbumArtBitmap(context, entry, size);
|
|
||||||
} catch(Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response getDownloadInputStream(Context context, Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
throw new OfflineException(ERRORMSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
|
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
|
||||||
List<Entry> albums = new ArrayList<Entry>();
|
|
||||||
List<Entry> songs = new ArrayList<Entry>();
|
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
|
||||||
int closeness = 0;
|
|
||||||
for (File artistFile : FileUtil.listFiles(root)) {
|
|
||||||
String artistName = artistFile.getName();
|
|
||||||
if (artistFile.isDirectory()) {
|
|
||||||
if((closeness = matchCriteria(criteria, artistName)) > 0) {
|
|
||||||
Artist artist = new Artist();
|
|
||||||
artist.setId(artistFile.getPath());
|
|
||||||
artist.setIndex(artistFile.getName().substring(0, 1));
|
|
||||||
artist.setName(artistName);
|
|
||||||
artist.setCloseness(closeness);
|
|
||||||
artists.add(artist);
|
|
||||||
}
|
|
||||||
|
|
||||||
recursiveAlbumSearch(artistName, artistFile, criteria, context, albums, songs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(artists, new Comparator<Artist>() {
|
entry.setTitle(title);
|
||||||
public int compare(Artist lhs, Artist rhs) {
|
entry.setSuffix(FileUtil.getExtension(file.getName().replace(".complete", "")));
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Collections.sort(albums, new Comparator<Entry>() {
|
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Collections.sort(songs, new Comparator<Entry>() {
|
|
||||||
public int compare(Entry lhs, Entry rhs) {
|
|
||||||
if(lhs.getCloseness() == rhs.getCloseness()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Respect counts in search criteria
|
File albumArt = FileUtil.getAlbumArtFile(context, entry);
|
||||||
int artistCount = Math.min(artists.size(), criteria.getArtistCount());
|
if (albumArt.exists()) {
|
||||||
int albumCount = Math.min(albums.size(), criteria.getAlbumCount());
|
entry.setCoverArt(albumArt.getPath());
|
||||||
int songCount = Math.min(songs.size(), criteria.getSongCount());
|
}
|
||||||
artists = artists.subList(0, artistCount);
|
return entry;
|
||||||
albums = albums.subList(0, albumCount);
|
|
||||||
songs = songs.subList(0, songCount);
|
|
||||||
|
|
||||||
return new SearchResult(artists, albums, songs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<Entry> albums, List<Entry> songs) {
|
@Override
|
||||||
int closeness;
|
public Bitmap getCoverArt(Context context, Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
||||||
for(File albumFile : FileUtil.listMediaFiles(file)) {
|
try {
|
||||||
if(albumFile.isDirectory()) {
|
return FileUtil.getAlbumArtBitmap(context, entry, size);
|
||||||
String albumName = getName(albumFile);
|
} catch(Exception e) {
|
||||||
if((closeness = matchCriteria(criteria, albumName)) > 0) {
|
return null;
|
||||||
Entry album = createEntry(context, albumFile, albumName);
|
}
|
||||||
album.setArtist(artistName);
|
}
|
||||||
album.setCloseness(closeness);
|
|
||||||
albums.add(album);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(File songFile : FileUtil.listMediaFiles(albumFile)) {
|
@Override
|
||||||
String songName = getName(songFile);
|
public Response getDownloadInputStream(Context context, Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
|
||||||
if(songName == null) {
|
throw new OfflineException(ERRORMSG);
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(songFile.isDirectory()) {
|
@Override
|
||||||
recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs);
|
public List<MusicFolder> getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
}
|
throw new OfflineException(ERRORMSG);
|
||||||
else if((closeness = matchCriteria(criteria, songName)) > 0){
|
}
|
||||||
Entry song = createEntry(context, albumFile, songName);
|
|
||||||
song.setArtist(artistName);
|
@Override
|
||||||
song.setAlbum(albumName);
|
public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception {
|
||||||
song.setCloseness(closeness);
|
List<Artist> artists = new ArrayList<Artist>();
|
||||||
songs.add(song);
|
List<Entry> albums = new ArrayList<Entry>();
|
||||||
}
|
List<Entry> songs = new ArrayList<Entry>();
|
||||||
}
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
}
|
int closeness = 0;
|
||||||
else {
|
for (File artistFile : FileUtil.listFiles(root)) {
|
||||||
String songName = getName(albumFile);
|
String artistName = artistFile.getName();
|
||||||
if((closeness = matchCriteria(criteria, songName)) > 0) {
|
if (artistFile.isDirectory()) {
|
||||||
Entry song = createEntry(context, albumFile, songName);
|
if((closeness = matchCriteria(criteria, artistName)) > 0) {
|
||||||
song.setArtist(artistName);
|
Artist artist = new Artist();
|
||||||
song.setAlbum(songName);
|
artist.setId(artistFile.getPath());
|
||||||
song.setCloseness(closeness);
|
artist.setIndex(artistFile.getName().substring(0, 1));
|
||||||
songs.add(song);
|
artist.setName(artistName);
|
||||||
}
|
artist.setCloseness(closeness);
|
||||||
}
|
artists.add(artist);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
private int matchCriteria(SearchCritera criteria, String name) {
|
recursiveAlbumSearch(artistName, artistFile, criteria, context, albums, songs);
|
||||||
if (criteria.getPattern().matcher(name).matches()) {
|
}
|
||||||
return Util.getStringDistance(
|
}
|
||||||
criteria.getQuery().toLowerCase(),
|
|
||||||
name.toLowerCase());
|
Collections.sort(artists, new Comparator<Artist>() {
|
||||||
} else {
|
public int compare(Artist lhs, Artist rhs) {
|
||||||
return 0;
|
if(lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Collections.sort(albums, new Comparator<Entry>() {
|
||||||
|
public int compare(Entry lhs, Entry rhs) {
|
||||||
|
if(lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Collections.sort(songs, new Comparator<Entry>() {
|
||||||
|
public int compare(Entry lhs, Entry rhs) {
|
||||||
|
if(lhs.getCloseness() == rhs.getCloseness()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(lhs.getCloseness() > rhs.getCloseness()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Respect counts in search criteria
|
||||||
|
int artistCount = Math.min(artists.size(), criteria.getArtistCount());
|
||||||
|
int albumCount = Math.min(albums.size(), criteria.getAlbumCount());
|
||||||
|
int songCount = Math.min(songs.size(), criteria.getSongCount());
|
||||||
|
artists = artists.subList(0, artistCount);
|
||||||
|
albums = albums.subList(0, albumCount);
|
||||||
|
songs = songs.subList(0, songCount);
|
||||||
|
|
||||||
|
return new SearchResult(artists, albums, songs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List<Entry> albums, List<Entry> songs) {
|
||||||
|
int closeness;
|
||||||
|
for(File albumFile : FileUtil.listMediaFiles(file)) {
|
||||||
|
if(albumFile.isDirectory()) {
|
||||||
|
String albumName = getName(albumFile);
|
||||||
|
if((closeness = matchCriteria(criteria, albumName)) > 0) {
|
||||||
|
Entry album = createEntry(context, albumFile, albumName);
|
||||||
|
album.setArtist(artistName);
|
||||||
|
album.setCloseness(closeness);
|
||||||
|
albums.add(album);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(File songFile : FileUtil.listMediaFiles(albumFile)) {
|
||||||
|
String songName = getName(songFile);
|
||||||
|
if(songName == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(songFile.isDirectory()) {
|
||||||
|
recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs);
|
||||||
|
}
|
||||||
|
else if((closeness = matchCriteria(criteria, songName)) > 0){
|
||||||
|
Entry song = createEntry(context, albumFile, songName);
|
||||||
|
song.setArtist(artistName);
|
||||||
|
song.setAlbum(albumName);
|
||||||
|
song.setCloseness(closeness);
|
||||||
|
songs.add(song);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String songName = getName(albumFile);
|
||||||
|
if((closeness = matchCriteria(criteria, songName)) > 0) {
|
||||||
|
Entry song = createEntry(context, albumFile, songName);
|
||||||
|
song.setArtist(artistName);
|
||||||
|
song.setAlbum(songName);
|
||||||
|
song.setCloseness(closeness);
|
||||||
|
songs.add(song);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int matchCriteria(SearchCritera criteria, String name) {
|
||||||
|
if (criteria.getPattern().matcher(name).matches()) {
|
||||||
|
return Util.getStringDistance(
|
||||||
|
criteria.getQuery().toLowerCase(),
|
||||||
|
name.toLowerCase());
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<Playlist> getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
List<Playlist> playlists = new ArrayList<Playlist>();
|
List<Playlist> playlists = new ArrayList<Playlist>();
|
||||||
File root = FileUtil.getPlaylistDirectory(context);
|
File root = FileUtil.getPlaylistDirectory(context);
|
||||||
String lastServer = null;
|
String lastServer = null;
|
||||||
boolean removeServer = true;
|
boolean removeServer = true;
|
||||||
for (File folder : FileUtil.listFiles(root)) {
|
for (File folder : FileUtil.listFiles(root)) {
|
||||||
if(folder.isDirectory()) {
|
if(folder.isDirectory()) {
|
||||||
String server = folder.getName();
|
String server = folder.getName();
|
||||||
SortedSet<File> fileList = FileUtil.listFiles(folder);
|
SortedSet<File> fileList = FileUtil.listFiles(folder);
|
||||||
for(File file: fileList) {
|
for(File file: fileList) {
|
||||||
if(FileUtil.isPlaylistFile(file)) {
|
if(FileUtil.isPlaylistFile(file)) {
|
||||||
String id = file.getName();
|
String id = file.getName();
|
||||||
String filename = FileUtil.getBaseName(id);
|
String filename = FileUtil.getBaseName(id);
|
||||||
String name = server + ": " + filename;
|
String name = server + ": " + filename;
|
||||||
Playlist playlist = new Playlist(server, name);
|
Playlist playlist = new Playlist(server, name);
|
||||||
playlist.setComment(filename);
|
playlist.setComment(filename);
|
||||||
|
|
||||||
Reader reader = null;
|
Reader reader = null;
|
||||||
BufferedReader buffer = null;
|
BufferedReader buffer = null;
|
||||||
int songCount = 0;
|
int songCount = 0;
|
||||||
try {
|
try {
|
||||||
reader = new FileReader(file);
|
reader = new FileReader(file);
|
||||||
buffer = new BufferedReader(reader);
|
buffer = new BufferedReader(reader);
|
||||||
|
|
||||||
String line = buffer.readLine();
|
String line = buffer.readLine();
|
||||||
while( (line = buffer.readLine()) != null ){
|
while( (line = buffer.readLine()) != null ){
|
||||||
// No matter what, end file can't have .complete in it
|
// No matter what, end file can't have .complete in it
|
||||||
line = line.replace(".complete", "");
|
line = line.replace(".complete", "");
|
||||||
File entryFile = new File(line);
|
File entryFile = new File(line);
|
||||||
|
|
||||||
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
||||||
File checkFile = entryFile;
|
File checkFile = entryFile;
|
||||||
if(!checkFile.exists()) {
|
if(!checkFile.exists()) {
|
||||||
// If normal file doens't exist, check if .complete version does
|
// If normal file doens't exist, check if .complete version does
|
||||||
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
||||||
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryName = getName(entryFile);
|
String entryName = getName(entryFile);
|
||||||
if(checkFile.exists() && entryName != null){
|
if(checkFile.exists() && entryName != null){
|
||||||
songCount++;
|
songCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist.setSongCount(Integer.toString(songCount));
|
playlist.setSongCount(Integer.toString(songCount));
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to count songs in playlist", e);
|
Log.w(TAG, "Failed to count songs in playlist", e);
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(buffer);
|
Util.close(buffer);
|
||||||
Util.close(reader);
|
Util.close(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(songCount > 0) {
|
if(songCount > 0) {
|
||||||
playlists.add(playlist);
|
playlists.add(playlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!server.equals(lastServer) && fileList.size() > 0) {
|
if(!server.equals(lastServer) && fileList.size() > 0) {
|
||||||
if(lastServer != null) {
|
if(lastServer != null) {
|
||||||
removeServer = false;
|
removeServer = false;
|
||||||
}
|
}
|
||||||
lastServer = server;
|
lastServer = server;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Delete legacy playlist files
|
// Delete legacy playlist files
|
||||||
try {
|
try {
|
||||||
folder.delete();
|
folder.delete();
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to delete old playlist file: " + folder.getName());
|
Log.w(TAG, "Failed to delete old playlist file: " + folder.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(removeServer) {
|
if(removeServer) {
|
||||||
for(Playlist playlist: playlists) {
|
for(Playlist playlist: playlists) {
|
||||||
playlist.setName(playlist.getName().substring(playlist.getId().length() + 2));
|
playlist.setName(playlist.getName().substring(playlist.getId().length() + 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
return new MusicDirectory();
|
return new MusicDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
Reader reader = null;
|
Reader reader = null;
|
||||||
BufferedReader buffer = null;
|
BufferedReader buffer = null;
|
||||||
try {
|
try {
|
||||||
int firstIndex = name.indexOf(id);
|
int firstIndex = name.indexOf(id);
|
||||||
if(firstIndex != -1) {
|
if(firstIndex != -1) {
|
||||||
name = name.substring(id.length() + 2);
|
name = name.substring(id.length() + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
File playlistFile = FileUtil.getPlaylistFile(context, id, name);
|
File playlistFile = FileUtil.getPlaylistFile(context, id, name);
|
||||||
reader = new FileReader(playlistFile);
|
reader = new FileReader(playlistFile);
|
||||||
buffer = new BufferedReader(reader);
|
buffer = new BufferedReader(reader);
|
||||||
|
|
||||||
MusicDirectory playlist = new MusicDirectory();
|
MusicDirectory playlist = new MusicDirectory();
|
||||||
String line = buffer.readLine();
|
String line = buffer.readLine();
|
||||||
if(!"#EXTM3U".equals(line)) return playlist;
|
if(!"#EXTM3U".equals(line)) return playlist;
|
||||||
|
|
||||||
while( (line = buffer.readLine()) != null ){
|
while( (line = buffer.readLine()) != null ){
|
||||||
// No matter what, end file can't have .complete in it
|
// No matter what, end file can't have .complete in it
|
||||||
line = line.replace(".complete", "");
|
line = line.replace(".complete", "");
|
||||||
File entryFile = new File(line);
|
File entryFile = new File(line);
|
||||||
|
|
||||||
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
// Don't add file to playlist if it doesn't exist as cached or pinned!
|
||||||
File checkFile = entryFile;
|
File checkFile = entryFile;
|
||||||
if(!checkFile.exists()) {
|
if(!checkFile.exists()) {
|
||||||
// If normal file doens't exist, check if .complete version does
|
// If normal file doens't exist, check if .complete version does
|
||||||
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName())
|
||||||
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
+ ".complete." + FileUtil.getExtension(entryFile.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
String entryName = getName(entryFile);
|
String entryName = getName(entryFile);
|
||||||
if(checkFile.exists() && entryName != null){
|
if(checkFile.exists() && entryName != null){
|
||||||
playlist.addChild(createEntry(context, entryFile, entryName, false));
|
playlist.addChild(createEntry(context, entryFile, entryName, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return playlist;
|
return playlist;
|
||||||
} finally {
|
} finally {
|
||||||
Util.close(buffer);
|
Util.close(buffer);
|
||||||
Util.close(reader);
|
Util.close(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createPlaylist(String id, String name, List<Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
public void createPlaylist(String id, String name, List<Entry> entries, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addToPlaylist(String id, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void addToPlaylist(String id, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
public void removeFromPlaylist(String id, List<Integer> toRemove, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void overwritePlaylist(String id, String name, int toRemove, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
public void overwritePlaylist(String id, String name, int toRemove, List<Entry> toAdd, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
public List<Genre> getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception {
|
||||||
File root = FileUtil.getMusicDirectory(context);
|
File root = FileUtil.getMusicDirectory(context);
|
||||||
List<File> children = new LinkedList<File>();
|
List<File> children = new LinkedList<File>();
|
||||||
@ -550,29 +550,29 @@ public class OfflineMusicService implements MusicService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void savePlayQueue(List<Entry> songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception {
|
public void savePlayQueue(List<Entry> songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception {
|
public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception {
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInstance(Integer instance) throws Exception{
|
public void setInstance(Integer instance) throws Exception{
|
||||||
throw new OfflineException(ERRORMSG);
|
throw new OfflineException(ERRORMSG);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void listFilesRecursively(File parent, List<File> children) {
|
private void listFilesRecursively(File parent, List<File> children) {
|
||||||
|
@ -45,10 +45,10 @@ public class EntryListParser extends MusicDirectoryEntryParser {
|
|||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if ("album".equals(name)) {
|
if ("album".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
if(get("isDir") == null) {
|
if(get("isDir") == null) {
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
}
|
}
|
||||||
dir.addChild(entry);
|
dir.addChild(entry);
|
||||||
} else if ("song".equals(name)) {
|
} else if ("song".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
|
@ -29,8 +29,8 @@ import java.io.InputStream;
|
|||||||
public class ErrorParser extends AbstractParser {
|
public class ErrorParser extends AbstractParser {
|
||||||
|
|
||||||
public ErrorParser(Context context, int instance) {
|
public ErrorParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void parse(InputStream inputStream) throws Exception {
|
public void parse(InputStream inputStream) throws Exception {
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
|
|
||||||
List<Artist> artists = new ArrayList<Artist>();
|
List<Artist> artists = new ArrayList<Artist>();
|
||||||
List<Artist> shortcuts = new ArrayList<Artist>();
|
List<Artist> shortcuts = new ArrayList<Artist>();
|
||||||
List<MusicDirectory.Entry> entries = new ArrayList<MusicDirectory.Entry>();
|
List<MusicDirectory.Entry> entries = new ArrayList<MusicDirectory.Entry>();
|
||||||
Long lastModified = null;
|
Long lastModified = null;
|
||||||
int eventType;
|
int eventType;
|
||||||
String index = "#";
|
String index = "#";
|
||||||
String ignoredArticles = null;
|
String ignoredArticles = null;
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
Map<String, Artist> artistList = new HashMap<String, Artist>();
|
Map<String, Artist> artistList = new HashMap<String, Artist>();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
@ -68,7 +68,7 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
if ("indexes".equals(name) || "artists".equals(name)) {
|
if ("indexes".equals(name) || "artists".equals(name)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
lastModified = getLong("lastModified");
|
lastModified = getLong("lastModified");
|
||||||
ignoredArticles = get("ignoredArticles");
|
ignoredArticles = get("ignoredArticles");
|
||||||
} else if ("index".equals(name)) {
|
} else if ("index".equals(name)) {
|
||||||
index = get("name");
|
index = get("name");
|
||||||
|
|
||||||
@ -78,14 +78,14 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
artist.setName(get("name"));
|
artist.setName(get("name"));
|
||||||
artist.setIndex(index);
|
artist.setIndex(index);
|
||||||
|
|
||||||
// Combine the id's for the two artists
|
// Combine the id's for the two artists
|
||||||
if(artistList.containsKey(artist.getName())) {
|
if(artistList.containsKey(artist.getName())) {
|
||||||
Artist originalArtist = artistList.get(artist.getName());
|
Artist originalArtist = artistList.get(artist.getName());
|
||||||
originalArtist.setId(originalArtist.getId() + ";" + artist.getId());
|
originalArtist.setId(originalArtist.getId() + ";" + artist.getId());
|
||||||
} else {
|
} else {
|
||||||
artistList.put(artist.getName(), artist);
|
artistList.put(artist.getName(), artist);
|
||||||
artists.add(artist);
|
artists.add(artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (artists.size() % 10 == 0) {
|
if (artists.size() % 10 == 0) {
|
||||||
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size());
|
||||||
@ -97,10 +97,10 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
shortcut.setName(get("name"));
|
shortcut.setName(get("name"));
|
||||||
shortcut.setIndex("*");
|
shortcut.setIndex("*");
|
||||||
shortcuts.add(shortcut);
|
shortcuts.add(shortcut);
|
||||||
} else if("child".equals(name)) {
|
} else if("child".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
entries.add(entry);
|
entries.add(entry);
|
||||||
} else if ("error".equals(name)) {
|
} else if ("error".equals(name)) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,11 +108,11 @@ public class IndexesParser extends MusicDirectoryEntryParser {
|
|||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
if(ignoredArticles != null) {
|
if(ignoredArticles != null) {
|
||||||
SharedPreferences.Editor prefs = Util.getPreferences(context).edit();
|
SharedPreferences.Editor prefs = Util.getPreferences(context).edit();
|
||||||
prefs.putString(Constants.CACHE_KEY_IGNORE, ignoredArticles);
|
prefs.putString(Constants.CACHE_KEY_IGNORE, ignoredArticles);
|
||||||
prefs.apply();
|
prefs.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changed) {
|
if (!changed) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -33,21 +33,21 @@ public class MusicDirectoryEntryParser extends AbstractParser {
|
|||||||
protected MusicDirectory.Entry parseEntry(String artist) {
|
protected MusicDirectory.Entry parseEntry(String artist) {
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||||
entry.setId(get("id"));
|
entry.setId(get("id"));
|
||||||
entry.setParent(get("parent"));
|
entry.setParent(get("parent"));
|
||||||
entry.setArtistId(get("artistId"));
|
entry.setArtistId(get("artistId"));
|
||||||
entry.setTitle(get("title"));
|
entry.setTitle(get("title"));
|
||||||
if(entry.getTitle() == null) {
|
if(entry.getTitle() == null) {
|
||||||
entry.setTitle(get("name"));
|
entry.setTitle(get("name"));
|
||||||
}
|
}
|
||||||
entry.setDirectory(getBoolean("isDir"));
|
entry.setDirectory(getBoolean("isDir"));
|
||||||
entry.setCoverArt(get("coverArt"));
|
entry.setCoverArt(get("coverArt"));
|
||||||
entry.setArtist(get("artist"));
|
entry.setArtist(get("artist"));
|
||||||
entry.setYear(getInteger("year"));
|
entry.setYear(getInteger("year"));
|
||||||
entry.setGenre(get("genre"));
|
entry.setGenre(get("genre"));
|
||||||
entry.setAlbum(get("album"));
|
entry.setAlbum(get("album"));
|
||||||
|
|
||||||
if (!entry.isDirectory()) {
|
if (!entry.isDirectory()) {
|
||||||
entry.setAlbumId(get("albumId"));
|
entry.setAlbumId(get("albumId"));
|
||||||
entry.setTrack(getInteger("track"));
|
entry.setTrack(getInteger("track"));
|
||||||
entry.setContentType(get("contentType"));
|
entry.setContentType(get("contentType"));
|
||||||
entry.setSuffix(get("suffix"));
|
entry.setSuffix(get("suffix"));
|
||||||
@ -57,23 +57,23 @@ public class MusicDirectoryEntryParser extends AbstractParser {
|
|||||||
entry.setDuration(getInteger("duration"));
|
entry.setDuration(getInteger("duration"));
|
||||||
entry.setBitRate(getInteger("bitRate"));
|
entry.setBitRate(getInteger("bitRate"));
|
||||||
entry.setPath(get("path"));
|
entry.setPath(get("path"));
|
||||||
entry.setDiscNumber(getInteger("discNumber"));
|
entry.setDiscNumber(getInteger("discNumber"));
|
||||||
|
|
||||||
String type = get("type");
|
String type = get("type");
|
||||||
} else if(!"".equals(artist)) {
|
} else if(!"".equals(artist)) {
|
||||||
entry.setPath(artist + "/" + entry.getTitle());
|
entry.setPath(artist + "/" + entry.getTitle());
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MusicDirectory.Entry parseArtist() {
|
protected MusicDirectory.Entry parseArtist() {
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||||
|
|
||||||
entry.setId(get("id"));
|
entry.setId(get("id"));
|
||||||
entry.setTitle(get("name"));
|
entry.setTitle(get("name"));
|
||||||
entry.setPath(entry.getTitle());
|
entry.setPath(entry.getTitle());
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,52 +49,52 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser {
|
|||||||
|
|
||||||
MusicDirectory dir = new MusicDirectory();
|
MusicDirectory dir = new MusicDirectory();
|
||||||
int eventType;
|
int eventType;
|
||||||
boolean isArtist = false;
|
boolean isArtist = false;
|
||||||
Map<String, Entry> titleMap = new HashMap<String, Entry>();
|
Map<String, Entry> titleMap = new HashMap<String, Entry>();
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if ("child".equals(name) || "song".equals(name)) {
|
if ("child".equals(name) || "song".equals(name)) {
|
||||||
Entry entry = parseEntry(artist);
|
Entry entry = parseEntry(artist);
|
||||||
entry.setGrandParent(dir.getParent());
|
entry.setGrandParent(dir.getParent());
|
||||||
|
|
||||||
// Only check for songs
|
// Only check for songs
|
||||||
if(!entry.isDirectory()) {
|
if(!entry.isDirectory()) {
|
||||||
// Check if duplicates
|
// Check if duplicates
|
||||||
String disc = (entry.getDiscNumber() != null) ? Integer.toString(entry.getDiscNumber()) : "";
|
String disc = (entry.getDiscNumber() != null) ? Integer.toString(entry.getDiscNumber()) : "";
|
||||||
String track = (entry.getTrack() != null) ? Integer.toString(entry.getTrack()) : "";
|
String track = (entry.getTrack() != null) ? Integer.toString(entry.getTrack()) : "";
|
||||||
String duplicateId = disc + "-" + track + "-" + entry.getTitle();
|
String duplicateId = disc + "-" + track + "-" + entry.getTitle();
|
||||||
|
|
||||||
Entry duplicate = titleMap.get(duplicateId);
|
Entry duplicate = titleMap.get(duplicateId);
|
||||||
if (duplicate != null) {
|
if (duplicate != null) {
|
||||||
// Check if the first already has been rebased or not
|
// Check if the first already has been rebased or not
|
||||||
if (duplicate.getTitle().equals(entry.getTitle())) {
|
if (duplicate.getTitle().equals(entry.getTitle())) {
|
||||||
duplicate.rebaseTitleOffPath();
|
duplicate.rebaseTitleOffPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebase if this is the second instance of this title found
|
// Rebase if this is the second instance of this title found
|
||||||
entry.rebaseTitleOffPath();
|
entry.rebaseTitleOffPath();
|
||||||
} else {
|
} else {
|
||||||
titleMap.put(duplicateId, entry);
|
titleMap.put(duplicateId, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dir.addChild(entry);
|
dir.addChild(entry);
|
||||||
} else if ("directory".equals(name) || "artist".equals(name) || ("album".equals(name) && !isArtist)) {
|
} else if ("directory".equals(name) || "artist".equals(name) || ("album".equals(name) && !isArtist)) {
|
||||||
dir.setName(get("name"));
|
dir.setName(get("name"));
|
||||||
dir.setId(get("id"));
|
dir.setId(get("id"));
|
||||||
if(Util.isTagBrowsing(context, instance)) {
|
if(Util.isTagBrowsing(context, instance)) {
|
||||||
dir.setParent(get("artistId"));
|
dir.setParent(get("artistId"));
|
||||||
} else {
|
} else {
|
||||||
dir.setParent(get("parent"));
|
dir.setParent(get("parent"));
|
||||||
}
|
}
|
||||||
isArtist = true;
|
isArtist = true;
|
||||||
} else if("album".equals(name)) {
|
} else if("album".equals(name)) {
|
||||||
Entry entry = parseEntry(artist);
|
Entry entry = parseEntry(artist);
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
dir.addChild(entry);
|
dir.addChild(entry);
|
||||||
} else if ("error".equals(name)) {
|
} else if ("error".equals(name)) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
@ -30,54 +30,54 @@ import net.nullsum.audinaut.domain.PlayerQueue;
|
|||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
|
||||||
public class PlayQueueParser extends MusicDirectoryEntryParser {
|
public class PlayQueueParser extends MusicDirectoryEntryParser {
|
||||||
private static final String TAG = PlayQueueParser.class.getSimpleName();
|
private static final String TAG = PlayQueueParser.class.getSimpleName();
|
||||||
|
|
||||||
public PlayQueueParser(Context context, int instance) {
|
public PlayQueueParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerQueue parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public PlayerQueue parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
|
||||||
PlayerQueue state = new PlayerQueue();
|
PlayerQueue state = new PlayerQueue();
|
||||||
String currentId = null;
|
String currentId = null;
|
||||||
int eventType;
|
int eventType;
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
String name = getElementName();
|
String name = getElementName();
|
||||||
if("playQueue".equals(name)) {
|
if("playQueue".equals(name)) {
|
||||||
currentId = get("current");
|
currentId = get("current");
|
||||||
state.currentPlayingPosition = getInteger("position");
|
state.currentPlayingPosition = getInteger("position");
|
||||||
try {
|
try {
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
|
||||||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
state.changed = dateFormat.parse(get("changed"));
|
state.changed = dateFormat.parse(get("changed"));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
state.changed = null;
|
state.changed = null;
|
||||||
}
|
}
|
||||||
} else if ("entry".equals(name)) {
|
} else if ("entry".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
// Only add songs
|
// Only add songs
|
||||||
state.songs.add(entry);
|
state.songs.add(entry);
|
||||||
} else if ("error".equals(name)) {
|
} else if ("error".equals(name)) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||||
|
|
||||||
if(currentId != null) {
|
if(currentId != null) {
|
||||||
for (MusicDirectory.Entry entry : state.songs) {
|
for (MusicDirectory.Entry entry : state.songs) {
|
||||||
if (entry.getId().equals(currentId)) {
|
if (entry.getId().equals(currentId)) {
|
||||||
state.currentPlayingIndex = state.songs.indexOf(entry);
|
state.currentPlayingIndex = state.songs.indexOf(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.currentPlayingIndex = 0;
|
state.currentPlayingIndex = 0;
|
||||||
state.currentPlayingPosition = 0;
|
state.currentPlayingPosition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ import java.io.InputStream;
|
|||||||
public class PlaylistParser extends MusicDirectoryEntryParser {
|
public class PlaylistParser extends MusicDirectoryEntryParser {
|
||||||
|
|
||||||
public PlaylistParser(Context context, int instance) {
|
public PlaylistParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
@ -49,9 +49,9 @@ public class PlaylistParser extends MusicDirectoryEntryParser {
|
|||||||
} else if ("error".equals(name)) {
|
} else if ("error".equals(name)) {
|
||||||
handleError();
|
handleError();
|
||||||
} else if ("playlist".equals(name)) {
|
} else if ("playlist".equals(name)) {
|
||||||
dir.setName(get("name"));
|
dir.setName(get("name"));
|
||||||
dir.setId(get("id"));
|
dir.setId(get("id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ import java.util.List;
|
|||||||
public class PlaylistsParser extends AbstractParser {
|
public class PlaylistsParser extends AbstractParser {
|
||||||
|
|
||||||
public PlaylistsParser(Context context, int instance) {
|
public PlaylistsParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Playlist> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<Playlist> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
@ -49,13 +49,13 @@ public class PlaylistsParser extends AbstractParser {
|
|||||||
if ("playlist".equals(tag)) {
|
if ("playlist".equals(tag)) {
|
||||||
String id = get("id");
|
String id = get("id");
|
||||||
String name = get("name");
|
String name = get("name");
|
||||||
String owner = get("owner");
|
String owner = get("owner");
|
||||||
String comment = get("comment");
|
String comment = get("comment");
|
||||||
String songCount = get("songCount");
|
String songCount = get("songCount");
|
||||||
String pub = get("public");
|
String pub = get("public");
|
||||||
String created = get("created");
|
String created = get("created");
|
||||||
String changed = get("changed");
|
String changed = get("changed");
|
||||||
Integer duration = getInteger("duration");
|
Integer duration = getInteger("duration");
|
||||||
result.add(new Playlist(id, name, owner, comment, songCount, pub, created, changed, duration));
|
result.add(new Playlist(id, name, owner, comment, songCount, pub, created, changed, duration));
|
||||||
} else if ("error".equals(tag)) {
|
} else if ("error".equals(tag)) {
|
||||||
handleError();
|
handleError();
|
||||||
|
@ -32,8 +32,8 @@ import java.io.InputStream;
|
|||||||
public class RandomSongsParser extends MusicDirectoryEntryParser {
|
public class RandomSongsParser extends MusicDirectoryEntryParser {
|
||||||
|
|
||||||
public RandomSongsParser(Context context, int instance) {
|
public RandomSongsParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
|
@ -36,8 +36,8 @@ import java.util.ArrayList;
|
|||||||
public class SearchResult2Parser extends MusicDirectoryEntryParser {
|
public class SearchResult2Parser extends MusicDirectoryEntryParser {
|
||||||
|
|
||||||
public SearchResult2Parser(Context context, int instance) {
|
public SearchResult2Parser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SearchResult parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public SearchResult parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
@ -56,8 +56,8 @@ public class SearchResult2Parser extends MusicDirectoryEntryParser {
|
|||||||
artist.setName(get("name"));
|
artist.setName(get("name"));
|
||||||
artists.add(artist);
|
artists.add(artist);
|
||||||
} else if ("album".equals(name)) {
|
} else if ("album".equals(name)) {
|
||||||
MusicDirectory.Entry entry = parseEntry("");
|
MusicDirectory.Entry entry = parseEntry("");
|
||||||
entry.setDirectory(true);
|
entry.setDirectory(true);
|
||||||
albums.add(entry);
|
albums.add(entry);
|
||||||
} else if ("song".equals(name)) {
|
} else if ("song".equals(name)) {
|
||||||
songs.add(parseEntry(""));
|
songs.add(parseEntry(""));
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.service.parser;
|
package net.nullsum.audinaut.service.parser;
|
||||||
@ -33,76 +33,76 @@ import net.nullsum.audinaut.service.MusicServiceFactory;
|
|||||||
import net.nullsum.audinaut.util.ProgressListener;
|
import net.nullsum.audinaut.util.ProgressListener;
|
||||||
|
|
||||||
public class UserParser extends AbstractParser {
|
public class UserParser extends AbstractParser {
|
||||||
private static final String TAG = UserParser.class.getSimpleName();
|
private static final String TAG = UserParser.class.getSimpleName();
|
||||||
|
|
||||||
public UserParser(Context context, int instance) {
|
public UserParser(Context context, int instance) {
|
||||||
super(context, instance);
|
super(context, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<User> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
public List<User> parse(InputStream inputStream, ProgressListener progressListener) throws Exception {
|
||||||
init(inputStream);
|
init(inputStream);
|
||||||
List<User> result = new ArrayList<User>();
|
List<User> result = new ArrayList<User>();
|
||||||
List<MusicFolder> musicFolders = null;
|
List<MusicFolder> musicFolders = null;
|
||||||
User user = null;
|
User user = null;
|
||||||
int eventType;
|
int eventType;
|
||||||
|
|
||||||
String tagName = null;
|
String tagName = null;
|
||||||
do {
|
do {
|
||||||
eventType = nextParseEvent();
|
eventType = nextParseEvent();
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
if (eventType == XmlPullParser.START_TAG) {
|
||||||
tagName = getElementName();
|
tagName = getElementName();
|
||||||
if ("user".equals(tagName)) {
|
if ("user".equals(tagName)) {
|
||||||
user = new User();
|
user = new User();
|
||||||
|
|
||||||
user.setUsername(get("username"));
|
user.setUsername(get("username"));
|
||||||
user.setEmail(get("email"));
|
user.setEmail(get("email"));
|
||||||
for(String role: User.ROLES) {
|
for(String role: User.ROLES) {
|
||||||
parseSetting(user, role);
|
parseSetting(user, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.add(user);
|
result.add(user);
|
||||||
} else if ("error".equals(tagName)) {
|
} else if ("error".equals(tagName)) {
|
||||||
handleError();
|
handleError();
|
||||||
}
|
}
|
||||||
} else if(eventType == XmlPullParser.TEXT) {
|
} else if(eventType == XmlPullParser.TEXT) {
|
||||||
if("folder".equals(tagName)) {
|
if("folder".equals(tagName)) {
|
||||||
String id = getText();
|
String id = getText();
|
||||||
if(musicFolders == null) {
|
if(musicFolders == null) {
|
||||||
musicFolders = getMusicFolders();
|
musicFolders = getMusicFolders();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(user != null) {
|
if(user != null) {
|
||||||
if(user.getMusicFolderSettings() == null) {
|
if(user.getMusicFolderSettings() == null) {
|
||||||
for (MusicFolder musicFolder : musicFolders) {
|
for (MusicFolder musicFolder : musicFolders) {
|
||||||
user.addMusicFolder(musicFolder);
|
user.addMusicFolder(musicFolder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Setting musicFolder: user.getMusicFolderSettings()) {
|
for(Setting musicFolder: user.getMusicFolderSettings()) {
|
||||||
if(musicFolder.getName().equals(id)) {
|
if(musicFolder.getName().equals(id)) {
|
||||||
musicFolder.setValue(true);
|
musicFolder.setValue(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (eventType != XmlPullParser.END_DOCUMENT);
|
} while (eventType != XmlPullParser.END_DOCUMENT);
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MusicFolder> getMusicFolders() throws Exception{
|
private List<MusicFolder> getMusicFolders() throws Exception{
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
||||||
return musicService.getMusicFolders(false, context, null);
|
return musicService.getMusicFolders(false, context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseSetting(User user, String name) {
|
private void parseSetting(User user, String name) {
|
||||||
String value = get(name);
|
String value = get(name);
|
||||||
if(value != null) {
|
if(value != null) {
|
||||||
user.addSetting(name, "true".equals(value));
|
user.addSetting(name, "true".equals(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,57 +34,57 @@ import android.os.IBinder;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class AuthenticatorService extends Service {
|
public class AuthenticatorService extends Service {
|
||||||
private SubsonicAuthenticator authenticator;
|
private SubsonicAuthenticator authenticator;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
authenticator = new SubsonicAuthenticator(this);
|
authenticator = new SubsonicAuthenticator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return authenticator.getIBinder();
|
return authenticator.getIBinder();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SubsonicAuthenticator extends AbstractAccountAuthenticator {
|
private class SubsonicAuthenticator extends AbstractAccountAuthenticator {
|
||||||
public SubsonicAuthenticator(Context context) {
|
public SubsonicAuthenticator(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
|
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
|
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthTokenLabel(String authTokenType) {
|
public String getAuthTokenLabel(String authTokenType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
|
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,71 +32,71 @@ import java.util.List;
|
|||||||
* @author Scott
|
* @author Scott
|
||||||
*/
|
*/
|
||||||
public class Updater {
|
public class Updater {
|
||||||
protected String TAG = Updater.class.getSimpleName();
|
protected String TAG = Updater.class.getSimpleName();
|
||||||
protected int version;
|
protected int version;
|
||||||
protected Context context;
|
protected Context context;
|
||||||
|
|
||||||
public Updater(int version) {
|
public Updater(int version) {
|
||||||
// 5.2 should show as 520 instead of 52
|
// 5.2 should show as 520 instead of 52
|
||||||
if(version < 100) {
|
if(version < 100) {
|
||||||
version *= 10;
|
version *= 10;
|
||||||
}
|
}
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkUpdates(Context context) {
|
public void checkUpdates(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
List<Updater> updaters = new ArrayList<Updater>();
|
List<Updater> updaters = new ArrayList<Updater>();
|
||||||
updaters.add(new UpdaterSongPress());
|
updaters.add(new UpdaterSongPress());
|
||||||
|
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
int lastVersion = prefs.getInt(Constants.LAST_VERSION, 0);
|
int lastVersion = prefs.getInt(Constants.LAST_VERSION, 0);
|
||||||
if(lastVersion == 0) {
|
if(lastVersion == 0) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.LAST_VERSION, version);
|
editor.putInt(Constants.LAST_VERSION, version);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
else if(version > lastVersion) {
|
else if(version > lastVersion) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putInt(Constants.LAST_VERSION, version);
|
editor.putInt(Constants.LAST_VERSION, version);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
|
|
||||||
Log.i(TAG, "Updating from version " + lastVersion + " to " + version);
|
Log.i(TAG, "Updating from version " + lastVersion + " to " + version);
|
||||||
for(Updater updater: updaters) {
|
for(Updater updater: updaters) {
|
||||||
if(updater.shouldUpdate(lastVersion)) {
|
if(updater.shouldUpdate(lastVersion)) {
|
||||||
new BackgroundUpdate(context, updater).execute();
|
new BackgroundUpdate(context, updater).execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return this.TAG;
|
return this.TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BackgroundUpdate extends SilentBackgroundTask<Void> {
|
private class BackgroundUpdate extends SilentBackgroundTask<Void> {
|
||||||
private final Updater updater;
|
private final Updater updater;
|
||||||
|
|
||||||
public BackgroundUpdate(Context context, Updater updater) {
|
public BackgroundUpdate(Context context, Updater updater) {
|
||||||
super(context);
|
super(context);
|
||||||
this.updater = updater;
|
this.updater = updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
try {
|
try {
|
||||||
updater.update(context);
|
updater.update(context);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to run update for " + updater.getName());
|
Log.w(TAG, "Failed to run update for " + updater.getName());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldUpdate(int version) {
|
public boolean shouldUpdate(int version) {
|
||||||
return this.version > version;
|
return this.version > version;
|
||||||
}
|
}
|
||||||
public void update(Context context) {
|
public void update(Context context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2016 (C) Scott Jackson
|
Copyright 2016 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.updates;
|
package net.nullsum.audinaut.updates;
|
||||||
@ -22,21 +22,21 @@ import net.nullsum.audinaut.util.Constants;
|
|||||||
import net.nullsum.audinaut.util.Util;
|
import net.nullsum.audinaut.util.Util;
|
||||||
|
|
||||||
public class UpdaterSongPress extends Updater {
|
public class UpdaterSongPress extends Updater {
|
||||||
public UpdaterSongPress() {
|
public UpdaterSongPress() {
|
||||||
super(521);
|
super(521);
|
||||||
TAG = this.getClass().getSimpleName();
|
TAG = this.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Context context) {
|
public void update(Context context) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
boolean playNowAfter = prefs.getBoolean("playNowAfter", true);
|
boolean playNowAfter = prefs.getBoolean("playNowAfter", true);
|
||||||
|
|
||||||
// Migrate the old preference so behavior stays the same
|
// Migrate the old preference so behavior stays the same
|
||||||
if(playNowAfter == false) {
|
if(playNowAfter == false) {
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
editor.putString(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION, "single");
|
editor.putString(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION, "single");
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,62 +45,62 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
private static final String TAG = BackgroundTask.class.getSimpleName();
|
private static final String TAG = BackgroundTask.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
protected AtomicBoolean cancelled = new AtomicBoolean(false);
|
protected AtomicBoolean cancelled = new AtomicBoolean(false);
|
||||||
protected OnCancelListener cancelListener;
|
protected OnCancelListener cancelListener;
|
||||||
protected Runnable onCompletionListener = null;
|
protected Runnable onCompletionListener = null;
|
||||||
protected Task task;
|
protected Task task;
|
||||||
|
|
||||||
private static final int DEFAULT_CONCURRENCY = 8;
|
private static final int DEFAULT_CONCURRENCY = 8;
|
||||||
private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>());
|
private static final Collection<Thread> threads = Collections.synchronizedCollection(new ArrayList<Thread>());
|
||||||
protected static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<BackgroundTask.Task>(10);
|
protected static final BlockingQueue<BackgroundTask.Task> queue = new LinkedBlockingQueue<BackgroundTask.Task>(10);
|
||||||
private static Handler handler = null;
|
private static Handler handler = null;
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Not called from main thread
|
// Not called from main thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackgroundTask(Context context) {
|
public BackgroundTask(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
if(threads.size() < DEFAULT_CONCURRENCY) {
|
if(threads.size() < DEFAULT_CONCURRENCY) {
|
||||||
for(int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) {
|
for(int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) {
|
||||||
Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i));
|
Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i));
|
||||||
threads.add(thread);
|
threads.add(thread);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(handler == null) {
|
if(handler == null) {
|
||||||
try {
|
try {
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Not called from main thread
|
// Not called from main thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void stopThreads() {
|
public static void stopThreads() {
|
||||||
for(Thread thread: threads) {
|
for(Thread thread: threads) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
threads.clear();
|
threads.clear();
|
||||||
queue.clear();
|
queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Activity getActivity() {
|
protected Activity getActivity() {
|
||||||
return (context instanceof Activity) ? ((Activity) context) : null;
|
return (context instanceof Activity) ? ((Activity) context) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Context getContext() {
|
protected Context getContext() {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
protected Handler getHandler() {
|
protected Handler getHandler() {
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void execute();
|
public abstract void execute();
|
||||||
|
|
||||||
protected abstract T doInBackground() throws Throwable;
|
protected abstract T doInBackground() throws Throwable;
|
||||||
|
|
||||||
@ -108,10 +108,10 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
|
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
Log.w(TAG, "Got exception: " + error, error);
|
Log.w(TAG, "Got exception: " + error, error);
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if(activity != null) {
|
if(activity != null) {
|
||||||
new ErrorDialog(activity, getErrorMessage(error), true);
|
new ErrorDialog(activity, getErrorMessage(error), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getErrorMessage(Throwable error) {
|
protected String getErrorMessage(Throwable error) {
|
||||||
@ -139,33 +139,33 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
return error.getClass().getSimpleName();
|
return error.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
if(cancelled.compareAndSet(false, true)) {
|
if(cancelled.compareAndSet(false, true)) {
|
||||||
if(isRunning()) {
|
if(isRunning()) {
|
||||||
if(cancelListener != null) {
|
if(cancelListener != null) {
|
||||||
cancelListener.onCancel();
|
cancelListener.onCancel();
|
||||||
} else {
|
} else {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task = null;
|
task = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return cancelled.get();
|
return cancelled.get();
|
||||||
}
|
}
|
||||||
public void setOnCancelListener(OnCancelListener listener) {
|
public void setOnCancelListener(OnCancelListener listener) {
|
||||||
cancelListener = listener;
|
cancelListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
if(task == null) {
|
if(task == null) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return task.isRunning();
|
return task.isRunning();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract void updateProgress(final String message);
|
public abstract void updateProgress(final String message);
|
||||||
@ -175,151 +175,151 @@ public abstract class BackgroundTask<T> implements ProgressListener {
|
|||||||
updateProgress(context.getResources().getString(messageId));
|
updateProgress(context.getResources().getString(messageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateCache(int changeCode) {
|
public void updateCache(int changeCode) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnCompletionListener(Runnable onCompletionListener) {
|
public void setOnCompletionListener(Runnable onCompletionListener) {
|
||||||
this.onCompletionListener = onCompletionListener;
|
this.onCompletionListener = onCompletionListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class Task {
|
protected class Task {
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private AtomicBoolean taskStart = new AtomicBoolean(false);
|
private AtomicBoolean taskStart = new AtomicBoolean(false);
|
||||||
|
|
||||||
private void execute() throws Exception {
|
private void execute() throws Exception {
|
||||||
// Don't run if cancelled already
|
// Don't run if cancelled already
|
||||||
if(isCancelled()) {
|
if(isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
thread = Thread.currentThread();
|
thread = Thread.currentThread();
|
||||||
taskStart.set(true);
|
taskStart.set(true);
|
||||||
|
|
||||||
final T result = doInBackground();
|
final T result = doInBackground();
|
||||||
if(isCancelled()) {
|
if(isCancelled()) {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handler != null) {
|
if(handler != null) {
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!isCancelled()) {
|
if (!isCancelled()) {
|
||||||
try {
|
try {
|
||||||
onDone(result);
|
onDone(result);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if(!isCancelled()) {
|
if(!isCancelled()) {
|
||||||
try {
|
try {
|
||||||
onError(t);
|
onError(t);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
}
|
}
|
||||||
} catch(InterruptedException interrupt) {
|
} catch(InterruptedException interrupt) {
|
||||||
if(taskStart.get()) {
|
if(taskStart.get()) {
|
||||||
// Don't exit root thread if task cancelled
|
// Don't exit root thread if task cancelled
|
||||||
throw interrupt;
|
throw interrupt;
|
||||||
}
|
}
|
||||||
} catch(final Throwable t) {
|
} catch(final Throwable t) {
|
||||||
if(isCancelled()) {
|
if(isCancelled()) {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handler != null) {
|
if(handler != null) {
|
||||||
handler.post(new Runnable() {
|
handler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if(!isCancelled()) {
|
if(!isCancelled()) {
|
||||||
try {
|
try {
|
||||||
onError(t);
|
onError(t);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// Don't care
|
// Don't care
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskStart.set(false);
|
taskStart.set(false);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
thread = null;
|
thread = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
if(taskStart.compareAndSet(true, false)) {
|
if(taskStart.compareAndSet(true, false)) {
|
||||||
if (thread != null) {
|
if (thread != null) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
if(Thread.interrupted()) {
|
if(Thread.interrupted()) {
|
||||||
return true;
|
return true;
|
||||||
} else if(BackgroundTask.this.isCancelled()) {
|
} else if(BackgroundTask.this.isCancelled()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void onDone(T result) {
|
public void onDone(T result) {
|
||||||
done(result);
|
done(result);
|
||||||
|
|
||||||
if(onCompletionListener != null) {
|
if(onCompletionListener != null) {
|
||||||
onCompletionListener.run();
|
onCompletionListener.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
error(t);
|
error(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return taskStart.get();
|
return taskStart.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TaskRunnable implements Runnable {
|
private class TaskRunnable implements Runnable {
|
||||||
private boolean running = true;
|
private boolean running = true;
|
||||||
|
|
||||||
public TaskRunnable() {
|
public TaskRunnable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Looper.prepare();
|
Looper.prepare();
|
||||||
while(running) {
|
while(running) {
|
||||||
try {
|
try {
|
||||||
Task task = queue.take();
|
Task task = queue.take();
|
||||||
task.execute();
|
task.execute();
|
||||||
} catch(InterruptedException stop) {
|
} catch(InterruptedException stop) {
|
||||||
Log.e(TAG, "Thread died");
|
Log.e(TAG, "Thread died");
|
||||||
running = false;
|
running = false;
|
||||||
threads.remove(Thread.currentThread());
|
threads.remove(Thread.currentThread());
|
||||||
} catch(Throwable t) {
|
} catch(Throwable t) {
|
||||||
Log.e(TAG, "Unexpected crash in BackgroundTask thread", t);
|
Log.e(TAG, "Unexpected crash in BackgroundTask thread", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface OnCancelListener {
|
public static interface OnCancelListener {
|
||||||
void onCancel();
|
void onCancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of ServerProxy.
|
This file is part of ServerProxy.
|
||||||
SocketProxy is free software: you can redistribute it and/or modify
|
SocketProxy is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -18,11 +18,11 @@ package net.nullsum.audinaut.util;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public interface BufferFile {
|
public interface BufferFile {
|
||||||
File getFile();
|
File getFile();
|
||||||
Long getContentLength();
|
Long getContentLength();
|
||||||
long getEstimatedSize();
|
long getEstimatedSize();
|
||||||
boolean isWorkDone();
|
boolean isWorkDone();
|
||||||
void onStart();
|
void onStart();
|
||||||
void onStop();
|
void onStop();
|
||||||
void onResume();
|
void onResume();
|
||||||
}
|
}
|
||||||
|
@ -23,60 +23,60 @@ import android.content.Context;
|
|||||||
import net.nullsum.audinaut.util.FileProxy;
|
import net.nullsum.audinaut.util.FileProxy;
|
||||||
|
|
||||||
public class BufferProxy extends FileProxy {
|
public class BufferProxy extends FileProxy {
|
||||||
private static final String TAG = BufferProxy.class.getSimpleName();
|
private static final String TAG = BufferProxy.class.getSimpleName();
|
||||||
protected BufferFile progress;
|
protected BufferFile progress;
|
||||||
|
|
||||||
public BufferProxy(Context context) {
|
public BufferProxy(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyTask getTask(Socket client) {
|
protected ProxyTask getTask(Socket client) {
|
||||||
return new BufferFileTask(client);
|
return new BufferFileTask(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBufferFile(BufferFile progress) {
|
public void setBufferFile(BufferFile progress) {
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class BufferFileTask extends StreamFileTask {
|
protected class BufferFileTask extends StreamFileTask {
|
||||||
public BufferFileTask(Socket client) {
|
public BufferFileTask(Socket client) {
|
||||||
super(client);
|
super(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
File getFile(String path) {
|
File getFile(String path) {
|
||||||
return progress.getFile();
|
return progress.getFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Long getContentLength() {
|
Long getContentLength() {
|
||||||
Long contentLength = progress.getContentLength();
|
Long contentLength = progress.getContentLength();
|
||||||
if(contentLength == null && progress.isWorkDone()) {
|
if(contentLength == null && progress.isWorkDone()) {
|
||||||
contentLength = file.length();
|
contentLength = file.length();
|
||||||
}
|
}
|
||||||
return contentLength;
|
return contentLength;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
long getFileSize() {
|
long getFileSize() {
|
||||||
return progress.getEstimatedSize();
|
return progress.getEstimatedSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
progress.onStart();
|
progress.onStart();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
progress.onStop();
|
progress.onStop();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
progress.onResume();
|
progress.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isWorkDone() {
|
public boolean isWorkDone() {
|
||||||
return progress.isWorkDone() && cbSkip >= file.length();
|
return progress.isWorkDone() && cbSkip >= file.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,28 +25,28 @@ import java.util.*;
|
|||||||
public class CacheCleaner {
|
public class CacheCleaner {
|
||||||
|
|
||||||
private static final String TAG = CacheCleaner.class.getSimpleName();
|
private static final String TAG = CacheCleaner.class.getSimpleName();
|
||||||
private static final long MIN_FREE_SPACE = 500 * 1024L * 1024L;
|
private static final long MIN_FREE_SPACE = 500 * 1024L * 1024L;
|
||||||
private static final long MAX_COVER_ART_SPACE = 100 * 1024L * 1024L;
|
private static final long MAX_COVER_ART_SPACE = 100 * 1024L * 1024L;
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final DownloadService downloadService;
|
private final DownloadService downloadService;
|
||||||
private final MediaStoreService mediaStore;
|
private final MediaStoreService mediaStore;
|
||||||
|
|
||||||
public CacheCleaner(Context context, DownloadService downloadService) {
|
public CacheCleaner(Context context, DownloadService downloadService) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.downloadService = downloadService;
|
this.downloadService = downloadService;
|
||||||
this.mediaStore = new MediaStoreService(context);
|
this.mediaStore = new MediaStoreService(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clean() {
|
public void clean() {
|
||||||
new BackgroundCleanup(context).execute();
|
new BackgroundCleanup(context).execute();
|
||||||
|
}
|
||||||
|
public void cleanSpace() {
|
||||||
|
new BackgroundSpaceCleanup(context).execute();
|
||||||
|
}
|
||||||
|
public void cleanPlaylists(List<Playlist> playlists) {
|
||||||
|
new BackgroundPlaylistsCleanup(context, playlists).execute();
|
||||||
}
|
}
|
||||||
public void cleanSpace() {
|
|
||||||
new BackgroundSpaceCleanup(context).execute();
|
|
||||||
}
|
|
||||||
public void cleanPlaylists(List<Playlist> playlists) {
|
|
||||||
new BackgroundPlaylistsCleanup(context, playlists).execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteEmptyDirs(List<File> dirs, Set<File> undeletable) {
|
private void deleteEmptyDirs(List<File> dirs, Set<File> undeletable) {
|
||||||
for (File dir : dirs) {
|
for (File dir : dirs) {
|
||||||
@ -58,12 +58,12 @@ public class CacheCleaner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getMinimumDelete(List<File> files, List<File> pinned) {
|
private long getMinimumDelete(List<File> files, List<File> pinned) {
|
||||||
if(files.size() == 0) {
|
if(files.size() == 0) {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
long cacheSizeBytes = Util.getCacheSizeMB(context) * 1024L * 1024L;
|
long cacheSizeBytes = Util.getCacheSizeMB(context) * 1024L * 1024L;
|
||||||
|
|
||||||
long bytesUsedBySubsonic = 0L;
|
long bytesUsedBySubsonic = 0L;
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
@ -73,7 +73,7 @@ public class CacheCleaner {
|
|||||||
bytesUsedBySubsonic += file.length();
|
bytesUsedBySubsonic += file.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that file system is not more than 95% full.
|
// Ensure that file system is not more than 95% full.
|
||||||
StatFs stat = new StatFs(files.get(0).getPath());
|
StatFs stat = new StatFs(files.get(0).getPath());
|
||||||
long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize();
|
||||||
long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();
|
||||||
@ -89,8 +89,8 @@ public class CacheCleaner {
|
|||||||
Log.i(TAG, "Cache size before : " + Util.formatBytes(bytesUsedBySubsonic));
|
Log.i(TAG, "Cache size before : " + Util.formatBytes(bytesUsedBySubsonic));
|
||||||
Log.i(TAG, "Minimum to delete : " + Util.formatBytes(bytesToDelete));
|
Log.i(TAG, "Minimum to delete : " + Util.formatBytes(bytesToDelete));
|
||||||
|
|
||||||
return bytesToDelete;
|
return bytesToDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteFiles(List<File> files, Set<File> undeletable, long bytesToDelete, boolean deletePartials) {
|
private void deleteFiles(List<File> files, Set<File> undeletable, long bytesToDelete, boolean deletePartials) {
|
||||||
if (files.isEmpty()) {
|
if (files.isEmpty()) {
|
||||||
@ -99,14 +99,14 @@ public class CacheCleaner {
|
|||||||
|
|
||||||
long bytesDeleted = 0L;
|
long bytesDeleted = 0L;
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if(!deletePartials && bytesDeleted > bytesToDelete) break;
|
if(!deletePartials && bytesDeleted > bytesToDelete) break;
|
||||||
|
|
||||||
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) {
|
if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) {
|
||||||
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) {
|
if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) {
|
||||||
long size = file.length();
|
long size = file.length();
|
||||||
if (Util.delete(file)) {
|
if (Util.delete(file)) {
|
||||||
bytesDeleted += size;
|
bytesDeleted += size;
|
||||||
mediaStore.deleteFromMediaStore(file);
|
mediaStore.deleteFromMediaStore(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,8 +122,8 @@ public class CacheCleaner {
|
|||||||
if (isCacheFile) {
|
if (isCacheFile) {
|
||||||
files.add(file);
|
files.add(file);
|
||||||
} else {
|
} else {
|
||||||
pinned.add(file);
|
pinned.add(file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Depth-first
|
// Depth-first
|
||||||
for (File child : FileUtil.listFiles(file)) {
|
for (File child : FileUtil.listFiles(file)) {
|
||||||
@ -160,133 +160,133 @@ public class CacheCleaner {
|
|||||||
return undeletable;
|
return undeletable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupCoverArt(Context context) {
|
private void cleanupCoverArt(Context context) {
|
||||||
File dir = FileUtil.getAlbumArtDirectory(context);
|
File dir = FileUtil.getAlbumArtDirectory(context);
|
||||||
|
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<File>();
|
||||||
long bytesUsed = 0L;
|
long bytesUsed = 0L;
|
||||||
for(File file: dir.listFiles()) {
|
for(File file: dir.listFiles()) {
|
||||||
if(file.isFile()) {
|
if(file.isFile()) {
|
||||||
files.add(file);
|
files.add(file);
|
||||||
bytesUsed += file.length();
|
bytesUsed += file.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't waste time sorting if under limit already
|
// Don't waste time sorting if under limit already
|
||||||
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
long bytesDeleted = 0L;
|
long bytesDeleted = 0L;
|
||||||
for(File file: files) {
|
for(File file: files) {
|
||||||
// End as soon as the space used is below the threshold
|
// End as soon as the space used is below the threshold
|
||||||
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
if(bytesUsed < MAX_COVER_ART_SPACE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
long bytes = file.length();
|
long bytes = file.length();
|
||||||
if(file.delete()) {
|
if(file.delete()) {
|
||||||
bytesUsed -= bytes;
|
bytesUsed -= bytes;
|
||||||
bytesDeleted += bytes;
|
bytesDeleted += bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Deleted " + Util.formatBytes(bytesDeleted) + " worth of cover art");
|
Log.i(TAG, "Deleted " + Util.formatBytes(bytesDeleted) + " worth of cover art");
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BackgroundCleanup extends SilentBackgroundTask<Void> {
|
private class BackgroundCleanup extends SilentBackgroundTask<Void> {
|
||||||
public BackgroundCleanup(Context context) {
|
public BackgroundCleanup(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<File>();
|
||||||
List<File> pinned = new ArrayList<File>();
|
List<File> pinned = new ArrayList<File>();
|
||||||
List<File> dirs = new ArrayList<File>();
|
List<File> dirs = new ArrayList<File>();
|
||||||
|
|
||||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
|
|
||||||
Set<File> undeletable = findUndeletableFiles();
|
Set<File> undeletable = findUndeletableFiles();
|
||||||
|
|
||||||
deleteFiles(files, undeletable, getMinimumDelete(files, pinned), true);
|
deleteFiles(files, undeletable, getMinimumDelete(files, pinned), true);
|
||||||
deleteEmptyDirs(dirs, undeletable);
|
deleteEmptyDirs(dirs, undeletable);
|
||||||
|
|
||||||
// Make sure cover art directory does not grow too large
|
// Make sure cover art directory does not grow too large
|
||||||
cleanupCoverArt(context);
|
cleanupCoverArt(context);
|
||||||
} catch (RuntimeException x) {
|
} catch (RuntimeException x) {
|
||||||
Log.e(TAG, "Error in cache cleaning.", x);
|
Log.e(TAG, "Error in cache cleaning.", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BackgroundSpaceCleanup extends SilentBackgroundTask<Void> {
|
private class BackgroundSpaceCleanup extends SilentBackgroundTask<Void> {
|
||||||
public BackgroundSpaceCleanup(Context context) {
|
public BackgroundSpaceCleanup(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
if (downloadService == null) {
|
if (downloadService == null) {
|
||||||
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
Log.e(TAG, "DownloadService not set. Aborting cache cleaning.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<File> files = new ArrayList<File>();
|
List<File> files = new ArrayList<File>();
|
||||||
List<File> pinned = new ArrayList<File>();
|
List<File> pinned = new ArrayList<File>();
|
||||||
List<File> dirs = new ArrayList<File>();
|
List<File> dirs = new ArrayList<File>();
|
||||||
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs);
|
||||||
|
|
||||||
long bytesToDelete = getMinimumDelete(files, pinned);
|
long bytesToDelete = getMinimumDelete(files, pinned);
|
||||||
if(bytesToDelete > 0L) {
|
if(bytesToDelete > 0L) {
|
||||||
sortByAscendingModificationTime(files);
|
sortByAscendingModificationTime(files);
|
||||||
Set<File> undeletable = findUndeletableFiles();
|
Set<File> undeletable = findUndeletableFiles();
|
||||||
deleteFiles(files, undeletable, bytesToDelete, false);
|
deleteFiles(files, undeletable, bytesToDelete, false);
|
||||||
}
|
}
|
||||||
} catch (RuntimeException x) {
|
} catch (RuntimeException x) {
|
||||||
Log.e(TAG, "Error in cache cleaning.", x);
|
Log.e(TAG, "Error in cache cleaning.", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BackgroundPlaylistsCleanup extends SilentBackgroundTask<Void> {
|
private class BackgroundPlaylistsCleanup extends SilentBackgroundTask<Void> {
|
||||||
private final List<Playlist> playlists;
|
private final List<Playlist> playlists;
|
||||||
|
|
||||||
public BackgroundPlaylistsCleanup(Context context, List<Playlist> playlists) {
|
public BackgroundPlaylistsCleanup(Context context, List<Playlist> playlists) {
|
||||||
super(context);
|
super(context);
|
||||||
this.playlists = playlists;
|
this.playlists = playlists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
try {
|
try {
|
||||||
String server = Util.getServerName(context);
|
String server = Util.getServerName(context);
|
||||||
SortedSet<File> playlistFiles = FileUtil.listFiles(FileUtil.getPlaylistDirectory(context, server));
|
SortedSet<File> playlistFiles = FileUtil.listFiles(FileUtil.getPlaylistDirectory(context, server));
|
||||||
for (Playlist playlist : playlists) {
|
for (Playlist playlist : playlists) {
|
||||||
playlistFiles.remove(FileUtil.getPlaylistFile(context, server, playlist.getName()));
|
playlistFiles.remove(FileUtil.getPlaylistFile(context, server, playlist.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(File playlist : playlistFiles) {
|
for(File playlist : playlistFiles) {
|
||||||
playlist.delete();
|
playlist.delete();
|
||||||
}
|
}
|
||||||
} catch (RuntimeException x) {
|
} catch (RuntimeException x) {
|
||||||
Log.e(TAG, "Error in playlist cache cleaning.", x);
|
Log.e(TAG, "Error in playlist cache cleaning.", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,13 @@ public final class Constants {
|
|||||||
|
|
||||||
public static final String REST_PROTOCOL_VERSION_SUBSONIC = "1.13.0";
|
public static final String REST_PROTOCOL_VERSION_SUBSONIC = "1.13.0";
|
||||||
public static final String REST_CLIENT_ID = "Audinaut";
|
public static final String REST_CLIENT_ID = "Audinaut";
|
||||||
public static final String LAST_VERSION = "subsonic.version";
|
public static final String LAST_VERSION = "subsonic.version";
|
||||||
|
|
||||||
// Names for intent extras.
|
// Names for intent extras.
|
||||||
public static final String INTENT_EXTRA_NAME_ID = "subsonic.id";
|
public static final String INTENT_EXTRA_NAME_ID = "subsonic.id";
|
||||||
public static final String INTENT_EXTRA_NAME_NAME = "subsonic.name";
|
public static final String INTENT_EXTRA_NAME_NAME = "subsonic.name";
|
||||||
public static final String INTENT_EXTRA_NAME_DIRECTORY = "subsonic.directory";
|
public static final String INTENT_EXTRA_NAME_DIRECTORY = "subsonic.directory";
|
||||||
public static final String INTENT_EXTRA_NAME_CHILD_ID = "subsonic.child.id";
|
public static final String INTENT_EXTRA_NAME_CHILD_ID = "subsonic.child.id";
|
||||||
public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist";
|
public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist";
|
||||||
public static final String INTENT_EXTRA_NAME_TITLE = "subsonic.title";
|
public static final String INTENT_EXTRA_NAME_TITLE = "subsonic.title";
|
||||||
public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall";
|
public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall";
|
||||||
@ -44,131 +44,131 @@ public final class Constants {
|
|||||||
public static final String INTENT_EXTRA_NAME_PLAYLIST_NAME = "subsonic.playlist.name";
|
public static final String INTENT_EXTRA_NAME_PLAYLIST_NAME = "subsonic.playlist.name";
|
||||||
public static final String INTENT_EXTRA_NAME_PLAYLIST_OWNER = "subsonic.playlist.isOwner";
|
public static final String INTENT_EXTRA_NAME_PLAYLIST_OWNER = "subsonic.playlist.isOwner";
|
||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_TYPE = "subsonic.albumlisttype";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_TYPE = "subsonic.albumlisttype";
|
||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA = "subsonic.albumlistextra";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA = "subsonic.albumlistextra";
|
||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_SIZE = "subsonic.albumlistsize";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_SIZE = "subsonic.albumlistsize";
|
||||||
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET = "subsonic.albumlistoffset";
|
public static final String INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET = "subsonic.albumlistoffset";
|
||||||
public static final String INTENT_EXTRA_NAME_SHUFFLE = "subsonic.shuffle";
|
public static final String INTENT_EXTRA_NAME_SHUFFLE = "subsonic.shuffle";
|
||||||
public static final String INTENT_EXTRA_REQUEST_SEARCH = "subsonic.requestsearch";
|
public static final String INTENT_EXTRA_REQUEST_SEARCH = "subsonic.requestsearch";
|
||||||
public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit" ;
|
public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit" ;
|
||||||
public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download";
|
public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download";
|
||||||
public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view";
|
public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view";
|
||||||
public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album";
|
public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album";
|
||||||
public static final String INTENT_EXTRA_NAME_SHARE = "subsonic.share";
|
public static final String INTENT_EXTRA_NAME_SHARE = "subsonic.share";
|
||||||
public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType";
|
public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType";
|
||||||
public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings";
|
public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings";
|
||||||
public static final String INTENT_EXTRA_SEARCH_SONG = "searchSong";
|
public static final String INTENT_EXTRA_SEARCH_SONG = "searchSong";
|
||||||
public static final String INTENT_EXTRA_TOP_TRACKS = "topTracks";
|
public static final String INTENT_EXTRA_TOP_TRACKS = "topTracks";
|
||||||
public static final String INTENT_EXTRA_PLAY_LAST = "playLast";
|
public static final String INTENT_EXTRA_PLAY_LAST = "playLast";
|
||||||
public static final String INTENT_EXTRA_ENTRY = "passedEntry";
|
public static final String INTENT_EXTRA_ENTRY = "passedEntry";
|
||||||
|
|
||||||
// Preferences keys.
|
// Preferences keys.
|
||||||
public static final String PREFERENCES_KEY_SERVER_KEY = "server";
|
public static final String PREFERENCES_KEY_SERVER_KEY = "server";
|
||||||
public static final String PREFERENCES_KEY_SERVER_COUNT = "serverCount";
|
public static final String PREFERENCES_KEY_SERVER_COUNT = "serverCount";
|
||||||
public static final String PREFERENCES_KEY_SERVER_ADD = "serverAdd";
|
public static final String PREFERENCES_KEY_SERVER_ADD = "serverAdd";
|
||||||
public static final String PREFERENCES_KEY_SERVER_REMOVE = "serverRemove";
|
public static final String PREFERENCES_KEY_SERVER_REMOVE = "serverRemove";
|
||||||
public static final String PREFERENCES_KEY_SERVER_INSTANCE = "serverInstanceId";
|
public static final String PREFERENCES_KEY_SERVER_INSTANCE = "serverInstanceId";
|
||||||
public static final String PREFERENCES_KEY_SERVER_NAME = "serverName";
|
public static final String PREFERENCES_KEY_SERVER_NAME = "serverName";
|
||||||
public static final String PREFERENCES_KEY_SERVER_URL = "serverUrl";
|
public static final String PREFERENCES_KEY_SERVER_URL = "serverUrl";
|
||||||
public static final String PREFERENCES_KEY_SERVER_INTERNAL_URL = "serverInternalUrl";
|
public static final String PREFERENCES_KEY_SERVER_INTERNAL_URL = "serverInternalUrl";
|
||||||
public static final String PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID = "serverLocalNetworkSSID";
|
public static final String PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID = "serverLocalNetworkSSID";
|
||||||
public static final String PREFERENCES_KEY_TEST_CONNECTION = "serverTestConnection";
|
public static final String PREFERENCES_KEY_TEST_CONNECTION = "serverTestConnection";
|
||||||
public static final String PREFERENCES_KEY_OPEN_BROWSER = "openBrowser";
|
public static final String PREFERENCES_KEY_OPEN_BROWSER = "openBrowser";
|
||||||
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
|
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
|
||||||
public static final String PREFERENCES_KEY_USERNAME = "username";
|
public static final String PREFERENCES_KEY_USERNAME = "username";
|
||||||
public static final String PREFERENCES_KEY_PASSWORD = "password";
|
public static final String PREFERENCES_KEY_PASSWORD = "password";
|
||||||
public static final String PREFERENCES_KEY_INSTALL_TIME = "installTime";
|
public static final String PREFERENCES_KEY_INSTALL_TIME = "installTime";
|
||||||
public static final String PREFERENCES_KEY_THEME = "theme";
|
public static final String PREFERENCES_KEY_THEME = "theme";
|
||||||
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
|
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
|
||||||
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";
|
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";
|
||||||
public static final String PREFERENCES_KEY_MAX_BITRATE_WIFI = "maxBitrateWifi";
|
public static final String PREFERENCES_KEY_MAX_BITRATE_WIFI = "maxBitrateWifi";
|
||||||
public static final String PREFERENCES_KEY_MAX_BITRATE_MOBILE = "maxBitrateMobile";
|
public static final String PREFERENCES_KEY_MAX_BITRATE_MOBILE = "maxBitrateMobile";
|
||||||
public static final String PREFERENCES_KEY_NETWORK_TIMEOUT = "networkTimeout";
|
public static final String PREFERENCES_KEY_NETWORK_TIMEOUT = "networkTimeout";
|
||||||
public static final String PREFERENCES_KEY_CACHE_SIZE = "cacheSize";
|
public static final String PREFERENCES_KEY_CACHE_SIZE = "cacheSize";
|
||||||
public static final String PREFERENCES_KEY_CACHE_LOCATION = "cacheLocation";
|
public static final String PREFERENCES_KEY_CACHE_LOCATION = "cacheLocation";
|
||||||
public static final String PREFERENCES_KEY_PRELOAD_COUNT_WIFI = "preloadCountWifi";
|
public static final String PREFERENCES_KEY_PRELOAD_COUNT_WIFI = "preloadCountWifi";
|
||||||
public static final String PREFERENCES_KEY_PRELOAD_COUNT_MOBILE = "preloadCountMobile";
|
public static final String PREFERENCES_KEY_PRELOAD_COUNT_MOBILE = "preloadCountMobile";
|
||||||
public static final String PREFERENCES_KEY_HIDE_MEDIA = "hideMedia";
|
public static final String PREFERENCES_KEY_HIDE_MEDIA = "hideMedia";
|
||||||
public static final String PREFERENCES_KEY_MEDIA_BUTTONS = "mediaButtons";
|
public static final String PREFERENCES_KEY_MEDIA_BUTTONS = "mediaButtons";
|
||||||
public static final String PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD = "screenLitOnDownload";
|
public static final String PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD = "screenLitOnDownload";
|
||||||
public static final String PREFERENCES_KEY_REPEAT_MODE = "repeatMode";
|
public static final String PREFERENCES_KEY_REPEAT_MODE = "repeatMode";
|
||||||
public static final String PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD = "wifiRequiredForDownload";
|
public static final String PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD = "wifiRequiredForDownload";
|
||||||
public static final String PREFERENCES_KEY_RANDOM_SIZE = "randomSize";
|
public static final String PREFERENCES_KEY_RANDOM_SIZE = "randomSize";
|
||||||
public static final String PREFERENCES_KEY_OFFLINE = "offline";
|
public static final String PREFERENCES_KEY_OFFLINE = "offline";
|
||||||
public static final String PREFERENCES_KEY_TEMP_LOSS = "tempLoss";
|
public static final String PREFERENCES_KEY_TEMP_LOSS = "tempLoss";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear";
|
public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear";
|
public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre";
|
public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre";
|
||||||
public static final String PREFERENCES_KEY_KEEP_SCREEN_ON = "keepScreenOn";
|
public static final String PREFERENCES_KEY_KEEP_SCREEN_ON = "keepScreenOn";
|
||||||
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
|
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
|
||||||
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
|
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
|
||||||
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
|
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
|
||||||
public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
|
public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
|
||||||
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
|
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
|
||||||
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
|
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_MODE = "shuffleMode2";
|
public static final String PREFERENCES_KEY_SHUFFLE_MODE = "shuffleMode2";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_MODE_EXTRA = "shuffleModeExtra";
|
public static final String PREFERENCES_KEY_SHUFFLE_MODE_EXTRA = "shuffleModeExtra";
|
||||||
public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled";
|
public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled";
|
||||||
public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval";
|
public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval";
|
||||||
public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi";
|
public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi";
|
||||||
public static final String PREFERENCES_KEY_SYNC_NOTIFICATION = "syncNotification";
|
public static final String PREFERENCES_KEY_SYNC_NOTIFICATION = "syncNotification";
|
||||||
public static final String PREFERENCES_KEY_SYNC_MOST_RECENT = "syncMostRecent";
|
public static final String PREFERENCES_KEY_SYNC_MOST_RECENT = "syncMostRecent";
|
||||||
public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect";
|
public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect";
|
||||||
public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget";
|
public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget";
|
||||||
public static final String PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled";
|
public static final String PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled";
|
||||||
public static final String PREFERENCES_KEY_SHARED_ENABLED = "sharedEnabled";
|
public static final String PREFERENCES_KEY_SHARED_ENABLED = "sharedEnabled";
|
||||||
public static final String PREFERENCES_KEY_OPEN_TO_TAB = "openToTab";
|
public static final String PREFERENCES_KEY_OPEN_TO_TAB = "openToTab";
|
||||||
// public static final String PREFERENCES_KEY_PLAY_NOW_AFTER = "playNowAfter";
|
// public static final String PREFERENCES_KEY_PLAY_NOW_AFTER = "playNowAfter";
|
||||||
public static final String PREFERENCES_KEY_SONG_PRESS_ACTION = "songPressAction";
|
public static final String PREFERENCES_KEY_SONG_PRESS_ACTION = "songPressAction";
|
||||||
public static final String PREFERENCES_KEY_LARGE_ALBUM_ART = "largeAlbumArt";
|
public static final String PREFERENCES_KEY_LARGE_ALBUM_ART = "largeAlbumArt";
|
||||||
public static final String PREFERENCES_KEY_PLAYLIST_NAME = "suggestedPlaylistName";
|
public static final String PREFERENCES_KEY_PLAYLIST_NAME = "suggestedPlaylistName";
|
||||||
public static final String PREFERENCES_KEY_PLAYLIST_ID = "suggestedPlaylistId";
|
public static final String PREFERENCES_KEY_PLAYLIST_ID = "suggestedPlaylistId";
|
||||||
public static final String PREFERENCES_KEY_RECENT_COUNT = "mostRecentCount";
|
public static final String PREFERENCES_KEY_RECENT_COUNT = "mostRecentCount";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2";
|
||||||
public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE= "replayGainType";
|
public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE= "replayGainType";
|
||||||
public static final String PREFERENCES_KEY_ALBUMS_PER_FOLDER = "albumsPerFolder";
|
public static final String PREFERENCES_KEY_ALBUMS_PER_FOLDER = "albumsPerFolder";
|
||||||
public static final String PREFERENCES_KEY_FIRST_LEVEL_ARTIST = "firstLevelArtist";
|
public static final String PREFERENCES_KEY_FIRST_LEVEL_ARTIST = "firstLevelArtist";
|
||||||
public static final String PREFERENCES_KEY_START_ON_HEADPHONES = "startOnHeadphones";
|
public static final String PREFERENCES_KEY_START_ON_HEADPHONES = "startOnHeadphones";
|
||||||
public static final String PREFERENCES_KEY_COLOR_ACTION_BAR = "colorActionBar";
|
public static final String PREFERENCES_KEY_COLOR_ACTION_BAR = "colorActionBar";
|
||||||
public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum";
|
public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum";
|
||||||
public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue";
|
public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue";
|
||||||
public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode";
|
public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode";
|
||||||
public static final String PREFERENCES_KEY_HEADS_UP_NOTIFICATION = "headsUpNotification";
|
public static final String PREFERENCES_KEY_HEADS_UP_NOTIFICATION = "headsUpNotification";
|
||||||
|
|
||||||
public static final String OFFLINE_STAR_COUNT = "starCount";
|
public static final String OFFLINE_STAR_COUNT = "starCount";
|
||||||
public static final String OFFLINE_STAR_ID = "starID";
|
public static final String OFFLINE_STAR_ID = "starID";
|
||||||
public static final String OFFLINE_STAR_SEARCH = "starTitle";
|
public static final String OFFLINE_STAR_SEARCH = "starTitle";
|
||||||
public static final String OFFLINE_STAR_SETTING = "starSetting";
|
public static final String OFFLINE_STAR_SETTING = "starSetting";
|
||||||
|
|
||||||
public static final String CACHE_KEY_IGNORE = "ignoreArticles";
|
public static final String CACHE_KEY_IGNORE = "ignoreArticles";
|
||||||
public static final String CACHE_AUDIO_SESSION_ID = "audioSessionId";
|
public static final String CACHE_AUDIO_SESSION_ID = "audioSessionId";
|
||||||
public static final String CACHE_BLOCK_TOKEN_USE = "blockTokenUse";
|
public static final String CACHE_BLOCK_TOKEN_USE = "blockTokenUse";
|
||||||
|
|
||||||
public static final String MAIN_BACK_STACK = "backStackIds";
|
public static final String MAIN_BACK_STACK = "backStackIds";
|
||||||
public static final String MAIN_BACK_STACK_SIZE = "backStackIdsSize";
|
public static final String MAIN_BACK_STACK_SIZE = "backStackIdsSize";
|
||||||
public static final String MAIN_NOW_PLAYING = "nowPlayingId";
|
public static final String MAIN_NOW_PLAYING = "nowPlayingId";
|
||||||
public static final String MAIN_NOW_PLAYING_SECONDARY = "nowPlayingSecondaryId";
|
public static final String MAIN_NOW_PLAYING_SECONDARY = "nowPlayingSecondaryId";
|
||||||
public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState";
|
public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState";
|
||||||
public static final String FRAGMENT_LIST = "fragmentList";
|
public static final String FRAGMENT_LIST = "fragmentList";
|
||||||
public static final String FRAGMENT_LIST2 = "fragmentList2";
|
public static final String FRAGMENT_LIST2 = "fragmentList2";
|
||||||
public static final String FRAGMENT_EXTRA = "fragmentExtra";
|
public static final String FRAGMENT_EXTRA = "fragmentExtra";
|
||||||
public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper";
|
public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper";
|
||||||
public static final String FRAGMENT_NAME = "fragmentName";
|
public static final String FRAGMENT_NAME = "fragmentName";
|
||||||
public static final String FRAGMENT_POSITION = "fragmentPosition";
|
public static final String FRAGMENT_POSITION = "fragmentPosition";
|
||||||
|
|
||||||
// Name of the preferences file.
|
// Name of the preferences file.
|
||||||
public static final String PREFERENCES_FILE_NAME = "net.nullsum.audinaut_preferences";
|
public static final String PREFERENCES_FILE_NAME = "net.nullsum.audinaut_preferences";
|
||||||
public static final String OFFLINE_SYNC_NAME = "net.nullsum.audinaut.offline";
|
public static final String OFFLINE_SYNC_NAME = "net.nullsum.audinaut.offline";
|
||||||
public static final String OFFLINE_SYNC_DEFAULT = "syncDefaults";
|
public static final String OFFLINE_SYNC_DEFAULT = "syncDefaults";
|
||||||
|
|
||||||
// Account prefs
|
// Account prefs
|
||||||
public static final String SYNC_ACCOUNT_NAME = "Subsonic Account";
|
public static final String SYNC_ACCOUNT_NAME = "Subsonic Account";
|
||||||
public static final String SYNC_ACCOUNT_TYPE = "Audinaut";
|
public static final String SYNC_ACCOUNT_TYPE = "Audinaut";
|
||||||
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "net.nullsum.audinaut.playlists.provider";
|
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "net.nullsum.audinaut.playlists.provider";
|
||||||
public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = "net.nullsum.audinaut.mostrecent.provider";
|
public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = "net.nullsum.audinaut.mostrecent.provider";
|
||||||
|
|
||||||
public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE";
|
public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE";
|
||||||
|
|
||||||
public static final String ALBUM_ART_FILE = "albumart.jpg";
|
public static final String ALBUM_ART_FILE = "albumart.jpg";
|
||||||
|
|
||||||
|
@ -15,100 +15,100 @@ import net.nullsum.audinaut.view.SongView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback {
|
public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback {
|
||||||
private static final String TAG = DownloadFileItemHelperCallback.class.getSimpleName();
|
private static final String TAG = DownloadFileItemHelperCallback.class.getSimpleName();
|
||||||
|
|
||||||
private SubsonicFragment fragment;
|
private SubsonicFragment fragment;
|
||||||
private boolean mainList;
|
private boolean mainList;
|
||||||
|
|
||||||
private BackgroundTask pendingTask = null;
|
private BackgroundTask pendingTask = null;
|
||||||
private Deque pendingOperations = new ArrayDeque();
|
private Deque pendingOperations = new ArrayDeque();
|
||||||
|
|
||||||
public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) {
|
public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) {
|
||||||
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
|
super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
this.mainList = mainList;
|
this.mainList = mainList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder fromHolder, RecyclerView.ViewHolder toHolder) {
|
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder fromHolder, RecyclerView.ViewHolder toHolder) {
|
||||||
int from = fromHolder.getAdapterPosition();
|
int from = fromHolder.getAdapterPosition();
|
||||||
int to = toHolder.getAdapterPosition();
|
int to = toHolder.getAdapterPosition();
|
||||||
getSectionAdapter().moveItem(from, to);
|
getSectionAdapter().moveItem(from, to);
|
||||||
|
|
||||||
synchronized (pendingOperations) {
|
synchronized (pendingOperations) {
|
||||||
pendingOperations.add(new Pair<>(from, to));
|
pendingOperations.add(new Pair<>(from, to));
|
||||||
updateDownloadService();
|
updateDownloadService();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||||
SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView();
|
SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView();
|
||||||
DownloadFile downloadFile = songView.getDownloadFile();
|
DownloadFile downloadFile = songView.getDownloadFile();
|
||||||
|
|
||||||
getSectionAdapter().removeItem(downloadFile);
|
getSectionAdapter().removeItem(downloadFile);
|
||||||
synchronized (pendingOperations) {
|
synchronized (pendingOperations) {
|
||||||
pendingOperations.add(downloadFile);
|
pendingOperations.add(downloadFile);
|
||||||
updateDownloadService();
|
updateDownloadService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadService getDownloadService() {
|
public DownloadService getDownloadService() {
|
||||||
return fragment.getDownloadService();
|
return fragment.getDownloadService();
|
||||||
}
|
}
|
||||||
public SectionAdapter getSectionAdapter() {
|
public SectionAdapter getSectionAdapter() {
|
||||||
return fragment.getCurrentAdapter();
|
return fragment.getCurrentAdapter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDownloadService() {
|
private void updateDownloadService() {
|
||||||
if(pendingTask == null) {
|
if(pendingTask == null) {
|
||||||
final DownloadService downloadService = getDownloadService();
|
final DownloadService downloadService = getDownloadService();
|
||||||
if(downloadService == null) {
|
if(downloadService == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingTask = new SilentBackgroundTask<Void>(downloadService) {
|
pendingTask = new SilentBackgroundTask<Void>(downloadService) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
boolean running = true;
|
boolean running = true;
|
||||||
while(running) {
|
while(running) {
|
||||||
Object nextOperation = null;
|
Object nextOperation = null;
|
||||||
synchronized (pendingOperations) {
|
synchronized (pendingOperations) {
|
||||||
if(!pendingOperations.isEmpty()) {
|
if(!pendingOperations.isEmpty()) {
|
||||||
nextOperation = pendingOperations.remove();
|
nextOperation = pendingOperations.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nextOperation != null) {
|
if(nextOperation != null) {
|
||||||
if(nextOperation instanceof Pair) {
|
if(nextOperation instanceof Pair) {
|
||||||
Pair<Integer, Integer> swap = (Pair) nextOperation;
|
Pair<Integer, Integer> swap = (Pair) nextOperation;
|
||||||
downloadService.swap(mainList, swap.getFirst(), swap.getSecond());
|
downloadService.swap(mainList, swap.getFirst(), swap.getSecond());
|
||||||
} else if(nextOperation instanceof DownloadFile) {
|
} else if(nextOperation instanceof DownloadFile) {
|
||||||
DownloadFile downloadFile = (DownloadFile) nextOperation;
|
DownloadFile downloadFile = (DownloadFile) nextOperation;
|
||||||
if(mainList) {
|
if(mainList) {
|
||||||
downloadService.remove(downloadFile);
|
downloadService.remove(downloadFile);
|
||||||
} else {
|
} else {
|
||||||
downloadService.removeBackground(downloadFile);
|
downloadService.removeBackground(downloadFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (pendingOperations) {
|
synchronized (pendingOperations) {
|
||||||
pendingTask = null;
|
pendingTask = null;
|
||||||
|
|
||||||
// Start a task if this is non-empty. Means someone added while we were running operations
|
// Start a task if this is non-empty. Means someone added while we were running operations
|
||||||
if(!pendingOperations.isEmpty()) {
|
if(!pendingOperations.isEmpty()) {
|
||||||
updateDownloadService();
|
updateDownloadService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pendingTask.execute();
|
pendingTask.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -32,71 +32,71 @@ import java.util.WeakHashMap;
|
|||||||
import net.nullsum.audinaut.R;
|
import net.nullsum.audinaut.R;
|
||||||
|
|
||||||
public class DrawableTint {
|
public class DrawableTint {
|
||||||
private static final Map<Integer, Integer> attrMap = new HashMap<>();
|
private static final Map<Integer, Integer> attrMap = new HashMap<>();
|
||||||
private static final WeakHashMap<Integer, Drawable> tintedDrawables = new WeakHashMap<>();
|
private static final WeakHashMap<Integer, Drawable> tintedDrawables = new WeakHashMap<>();
|
||||||
|
|
||||||
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes) {
|
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes) {
|
||||||
return getTintedDrawable(context, drawableRes, R.attr.colorAccent);
|
return getTintedDrawable(context, drawableRes, R.attr.colorAccent);
|
||||||
}
|
}
|
||||||
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes, @AttrRes int colorAttr) {
|
public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes, @AttrRes int colorAttr) {
|
||||||
if(tintedDrawables.containsKey(drawableRes)) {
|
if(tintedDrawables.containsKey(drawableRes)) {
|
||||||
return tintedDrawables.get(drawableRes);
|
return tintedDrawables.get(drawableRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int color = getColorRes(context, colorAttr);
|
int color = getColorRes(context, colorAttr);
|
||||||
Drawable background = context.getResources().getDrawable(drawableRes);
|
Drawable background = context.getResources().getDrawable(drawableRes);
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||||
tintedDrawables.put(drawableRes, background);
|
tintedDrawables.put(drawableRes, background);
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
public static Drawable getTintedDrawableFromColor(Context context, @DrawableRes int drawableRes, @ColorRes int colorRes) {
|
public static Drawable getTintedDrawableFromColor(Context context, @DrawableRes int drawableRes, @ColorRes int colorRes) {
|
||||||
if(tintedDrawables.containsKey(drawableRes)) {
|
if(tintedDrawables.containsKey(drawableRes)) {
|
||||||
return tintedDrawables.get(drawableRes);
|
return tintedDrawables.get(drawableRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int color = context.getResources().getColor(colorRes);
|
int color = context.getResources().getColor(colorRes);
|
||||||
Drawable background = context.getResources().getDrawable(drawableRes);
|
Drawable background = context.getResources().getDrawable(drawableRes);
|
||||||
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
background.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||||
tintedDrawables.put(drawableRes, background);
|
tintedDrawables.put(drawableRes, background);
|
||||||
return background;
|
return background;
|
||||||
}
|
}
|
||||||
public static int getColorRes(Context context, @AttrRes int colorAttr) {
|
public static int getColorRes(Context context, @AttrRes int colorAttr) {
|
||||||
int color;
|
int color;
|
||||||
if(attrMap.containsKey(colorAttr)) {
|
if(attrMap.containsKey(colorAttr)) {
|
||||||
color = attrMap.get(colorAttr);
|
color = attrMap.get(colorAttr);
|
||||||
} else {
|
} else {
|
||||||
TypedValue typedValue = new TypedValue();
|
TypedValue typedValue = new TypedValue();
|
||||||
Resources.Theme theme = context.getTheme();
|
Resources.Theme theme = context.getTheme();
|
||||||
theme.resolveAttribute(colorAttr, typedValue, true);
|
theme.resolveAttribute(colorAttr, typedValue, true);
|
||||||
color = typedValue.data;
|
color = typedValue.data;
|
||||||
attrMap.put(colorAttr, color);
|
attrMap.put(colorAttr, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
public static int getDrawableRes(Context context, @AttrRes int drawableAttr) {
|
public static int getDrawableRes(Context context, @AttrRes int drawableAttr) {
|
||||||
if(attrMap.containsKey(drawableAttr)) {
|
if(attrMap.containsKey(drawableAttr)) {
|
||||||
return attrMap.get(drawableAttr);
|
return attrMap.get(drawableAttr);
|
||||||
} else {
|
} else {
|
||||||
int[] attrs = new int[]{drawableAttr};
|
int[] attrs = new int[]{drawableAttr};
|
||||||
TypedArray typedArray = context.obtainStyledAttributes(attrs);
|
TypedArray typedArray = context.obtainStyledAttributes(attrs);
|
||||||
@DrawableRes int drawableRes = typedArray.getResourceId(0, 0);
|
@DrawableRes int drawableRes = typedArray.getResourceId(0, 0);
|
||||||
typedArray.recycle();
|
typedArray.recycle();
|
||||||
attrMap.put(drawableAttr, drawableRes);
|
attrMap.put(drawableAttr, drawableRes);
|
||||||
return drawableRes;
|
return drawableRes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Drawable getTintedAttrDrawable(Context context, @AttrRes int drawableAttr, @AttrRes int colorAttr) {
|
public static Drawable getTintedAttrDrawable(Context context, @AttrRes int drawableAttr, @AttrRes int colorAttr) {
|
||||||
if(tintedDrawables.containsKey(drawableAttr)) {
|
if(tintedDrawables.containsKey(drawableAttr)) {
|
||||||
return getTintedDrawable(context, attrMap.get(drawableAttr), colorAttr);
|
return getTintedDrawable(context, attrMap.get(drawableAttr), colorAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@DrawableRes int drawableRes = getDrawableRes(context, drawableAttr);
|
@DrawableRes int drawableRes = getDrawableRes(context, drawableAttr);
|
||||||
return getTintedDrawable(context, drawableRes, colorAttr);
|
return getTintedDrawable(context, drawableRes, colorAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void wipeTintCache() {
|
public static void wipeTintCache() {
|
||||||
attrMap.clear();
|
attrMap.clear();
|
||||||
tintedDrawables.clear();
|
tintedDrawables.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2016 (C) Scott Jackson
|
Copyright 2016 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
public final class EnvironmentVariables {
|
public final class EnvironmentVariables {
|
||||||
public static final String PASTEBIN_DEV_KEY = "";
|
public static final String PASTEBIN_DEV_KEY = "";
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of ServerProxy.
|
This file is part of ServerProxy.
|
||||||
SocketProxy is free software: you can redistribute it and/or modify
|
SocketProxy is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -29,191 +29,191 @@ import android.util.Log;
|
|||||||
import net.nullsum.audinaut.util.ServerProxy;
|
import net.nullsum.audinaut.util.ServerProxy;
|
||||||
|
|
||||||
public class FileProxy extends ServerProxy {
|
public class FileProxy extends ServerProxy {
|
||||||
private static final String TAG = FileProxy.class.getSimpleName();
|
private static final String TAG = FileProxy.class.getSimpleName();
|
||||||
|
|
||||||
public FileProxy(Context context) {
|
public FileProxy(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ProxyTask getTask(Socket client) {
|
protected ProxyTask getTask(Socket client) {
|
||||||
return new StreamFileTask(client);
|
return new StreamFileTask(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class StreamFileTask extends ProxyTask {
|
protected class StreamFileTask extends ProxyTask {
|
||||||
File file;
|
File file;
|
||||||
|
|
||||||
public StreamFileTask(Socket client) {
|
public StreamFileTask(Socket client) {
|
||||||
super(client);
|
super(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processRequest() {
|
public boolean processRequest() {
|
||||||
if(!super.processRequest()) {
|
if(!super.processRequest()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(TAG, "Processing request for file " + path);
|
Log.i(TAG, "Processing request for file " + path);
|
||||||
file = getFile(path);
|
file = getFile(path);
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
Log.e(TAG, "File " + path + " does not exist");
|
Log.e(TAG, "File " + path + " does not exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure to not try to read past where the file is downloaded
|
// Make sure to not try to read past where the file is downloaded
|
||||||
if(cbSkip != 0 && cbSkip >= file.length()) {
|
if(cbSkip != 0 && cbSkip >= file.length()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
File getFile(String path) {
|
File getFile(String path) {
|
||||||
return new File(path);
|
return new File(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Long getContentLength() {
|
Long getContentLength() {
|
||||||
return file.length();
|
return file.length();
|
||||||
}
|
}
|
||||||
long getFileSize() {
|
long getFileSize() {
|
||||||
return file.length();
|
return file.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Long contentLength = getContentLength();
|
Long contentLength = getContentLength();
|
||||||
|
|
||||||
// Create HTTP header
|
// Create HTTP header
|
||||||
String headers;
|
String headers;
|
||||||
if(cbSkip == 0) {
|
if(cbSkip == 0) {
|
||||||
headers = "HTTP/1.0 200 OK\r\n";
|
headers = "HTTP/1.0 200 OK\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers = "HTTP/1.0 206 OK\r\n";
|
headers = "HTTP/1.0 206 OK\r\n";
|
||||||
headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/";
|
headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/";
|
||||||
if(contentLength == null) {
|
if(contentLength == null) {
|
||||||
headers += "*";
|
headers += "*";
|
||||||
} else {
|
} else {
|
||||||
headers += contentLength;
|
headers += contentLength;
|
||||||
}
|
}
|
||||||
headers += "\r\n";
|
headers += "\r\n";
|
||||||
|
|
||||||
Log.i(TAG, "Streaming starts from: " + cbSkip);
|
Log.i(TAG, "Streaming starts from: " + cbSkip);
|
||||||
}
|
}
|
||||||
|
|
||||||
String name = file.getPath();
|
String name = file.getPath();
|
||||||
int index = name.lastIndexOf('.');
|
int index = name.lastIndexOf('.');
|
||||||
String ext = "";
|
String ext = "";
|
||||||
if(index != -1) {
|
if(index != -1) {
|
||||||
ext = name.substring(index + 1).toLowerCase();
|
ext = name.substring(index + 1).toLowerCase();
|
||||||
}
|
}
|
||||||
if("mp3".equals(ext)) {
|
if("mp3".equals(ext)) {
|
||||||
headers += "Content-Type: audio/mpeg\r\n";
|
headers += "Content-Type: audio/mpeg\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
|
headers += "Content-Type: " + "application/octet-stream" + "\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
long fileSize;
|
long fileSize;
|
||||||
if(contentLength == null) {
|
if(contentLength == null) {
|
||||||
fileSize = getFileSize();
|
fileSize = getFileSize();
|
||||||
} else {
|
} else {
|
||||||
fileSize = contentLength;
|
fileSize = contentLength;
|
||||||
if(cbSkip > 0) {
|
if(cbSkip > 0) {
|
||||||
headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n";
|
headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n";
|
||||||
} else {
|
} else {
|
||||||
headers += "Content-Length: " + fileSize + "\r\n";
|
headers += "Content-Length: " + fileSize + "\r\n";
|
||||||
}
|
}
|
||||||
headers += "Accept-Ranges: bytes \r\n";
|
headers += "Accept-Ranges: bytes \r\n";
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Streaming fileSize: " + fileSize);
|
Log.i(TAG, "Streaming fileSize: " + fileSize);
|
||||||
|
|
||||||
headers += "Connection: close\r\n";
|
headers += "Connection: close\r\n";
|
||||||
headers += "\r\n";
|
headers += "\r\n";
|
||||||
|
|
||||||
long cbToSend = fileSize - cbSkip;
|
long cbToSend = fileSize - cbSkip;
|
||||||
OutputStream output = null;
|
OutputStream output = null;
|
||||||
byte[] buff = new byte[64 * 1024];
|
byte[] buff = new byte[64 * 1024];
|
||||||
try {
|
try {
|
||||||
output = new BufferedOutputStream(client.getOutputStream(), 32*1024);
|
output = new BufferedOutputStream(client.getOutputStream(), 32*1024);
|
||||||
output.write(headers.getBytes());
|
output.write(headers.getBytes());
|
||||||
|
|
||||||
// Make sure to have file lock
|
// Make sure to have file lock
|
||||||
onStart();
|
onStart();
|
||||||
|
|
||||||
// Loop as long as there's stuff to send
|
// Loop as long as there's stuff to send
|
||||||
while (isRunning && !client.isClosed()) {
|
while (isRunning && !client.isClosed()) {
|
||||||
onResume();
|
onResume();
|
||||||
|
|
||||||
// See if there's more to send
|
// See if there's more to send
|
||||||
int cbSentThisBatch = 0;
|
int cbSentThisBatch = 0;
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
FileInputStream input = new FileInputStream(file);
|
FileInputStream input = new FileInputStream(file);
|
||||||
input.skip(cbSkip);
|
input.skip(cbSkip);
|
||||||
int cbToSendThisBatch = input.available();
|
int cbToSendThisBatch = input.available();
|
||||||
while (cbToSendThisBatch > 0) {
|
while (cbToSendThisBatch > 0) {
|
||||||
int cbToRead = Math.min(cbToSendThisBatch, buff.length);
|
int cbToRead = Math.min(cbToSendThisBatch, buff.length);
|
||||||
int cbRead = input.read(buff, 0, cbToRead);
|
int cbRead = input.read(buff, 0, cbToRead);
|
||||||
if (cbRead == -1) {
|
if (cbRead == -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cbToSendThisBatch -= cbRead;
|
cbToSendThisBatch -= cbRead;
|
||||||
cbToSend -= cbRead;
|
cbToSend -= cbRead;
|
||||||
output.write(buff, 0, cbRead);
|
output.write(buff, 0, cbRead);
|
||||||
output.flush();
|
output.flush();
|
||||||
cbSkip += cbRead;
|
cbSkip += cbRead;
|
||||||
cbSentThisBatch += cbRead;
|
cbSentThisBatch += cbRead;
|
||||||
}
|
}
|
||||||
input.close();
|
input.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done regardless of whether or not it thinks it is
|
// Done regardless of whether or not it thinks it is
|
||||||
if(isWorkDone()) {
|
if(isWorkDone()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we did nothing this batch, block for a second
|
// If we did nothing this batch, block for a second
|
||||||
if (cbSentThisBatch == 0) {
|
if (cbSentThisBatch == 0) {
|
||||||
Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")");
|
Log.d(TAG, "Blocking until more data appears (" + cbToSend + ")");
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release file lock, use of stream proxy means nothing else is using it
|
// Release file lock, use of stream proxy means nothing else is using it
|
||||||
onStop();
|
onStop();
|
||||||
}
|
}
|
||||||
catch (SocketException socketException) {
|
catch (SocketException socketException) {
|
||||||
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
|
Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly");
|
||||||
|
|
||||||
// Release file lock, use of stream proxy means nothing else is using it
|
// Release file lock, use of stream proxy means nothing else is using it
|
||||||
onStop();
|
onStop();
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
Log.e(TAG, "Exception thrown from streaming task:");
|
Log.e(TAG, "Exception thrown from streaming task:");
|
||||||
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
try {
|
try {
|
||||||
if (output != null) {
|
if (output != null) {
|
||||||
output.close();
|
output.close();
|
||||||
}
|
}
|
||||||
client.close();
|
client.close();
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
Log.e(TAG, "IOException while cleaning up streaming task:");
|
Log.e(TAG, "IOException while cleaning up streaming task:");
|
||||||
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public boolean isWorkDone() {
|
public boolean isWorkDone() {
|
||||||
return cbSkip >= file.length();
|
return cbSkip >= file.length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -54,386 +54,386 @@ import net.nullsum.audinaut.service.MusicServiceFactory;
|
|||||||
* @author Sindre Mehus
|
* @author Sindre Mehus
|
||||||
*/
|
*/
|
||||||
public class ImageLoader {
|
public class ImageLoader {
|
||||||
private static final String TAG = ImageLoader.class.getSimpleName();
|
private static final String TAG = ImageLoader.class.getSimpleName();
|
||||||
public static final String PLAYLIST_PREFIX = "pl-";
|
public static final String PLAYLIST_PREFIX = "pl-";
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private LruCache<String, Bitmap> cache;
|
private LruCache<String, Bitmap> cache;
|
||||||
private Handler handler;
|
private Handler handler;
|
||||||
private Bitmap nowPlaying;
|
private Bitmap nowPlaying;
|
||||||
private Bitmap nowPlayingSmall;
|
private Bitmap nowPlayingSmall;
|
||||||
private final int imageSizeDefault;
|
private final int imageSizeDefault;
|
||||||
private final int imageSizeLarge;
|
private final int imageSizeLarge;
|
||||||
private boolean clearingCache = false;
|
private boolean clearingCache = false;
|
||||||
private final int cacheSize;
|
private final int cacheSize;
|
||||||
|
|
||||||
private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444};
|
private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444};
|
||||||
|
|
||||||
public ImageLoader(Context context) {
|
public ImageLoader(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
handler = new Handler(Looper.getMainLooper());
|
handler = new Handler(Looper.getMainLooper());
|
||||||
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
|
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
|
||||||
cacheSize = maxMemory / 4;
|
cacheSize = maxMemory / 4;
|
||||||
|
|
||||||
// Determine the density-dependent image sizes.
|
// Determine the density-dependent image sizes.
|
||||||
imageSizeDefault = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight();
|
imageSizeDefault = context.getResources().getDrawable(R.drawable.unknown_album).getIntrinsicHeight();
|
||||||
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||||
imageSizeLarge = Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
|
imageSizeLarge = Math.round(Math.min(metrics.widthPixels, metrics.heightPixels));
|
||||||
|
|
||||||
cache = new LruCache<String, Bitmap>(cacheSize) {
|
cache = new LruCache<String, Bitmap>(cacheSize) {
|
||||||
@Override
|
@Override
|
||||||
protected int sizeOf(String key, Bitmap bitmap) {
|
protected int sizeOf(String key, Bitmap bitmap) {
|
||||||
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
|
return bitmap.getRowBytes() * bitmap.getHeight() / 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
|
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
|
||||||
if(evicted) {
|
if(evicted) {
|
||||||
if((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) {
|
if((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) {
|
||||||
oldBitmap.recycle();
|
oldBitmap.recycle();
|
||||||
} else if(oldBitmap != newBitmap) {
|
} else if(oldBitmap != newBitmap) {
|
||||||
cache.put(key, oldBitmap);
|
cache.put(key, oldBitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearCache() {
|
public void clearCache() {
|
||||||
nowPlaying = null;
|
nowPlaying = null;
|
||||||
nowPlayingSmall = null;
|
nowPlayingSmall = null;
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
clearingCache = true;
|
clearingCache = true;
|
||||||
cache.evictAll();
|
cache.evictAll();
|
||||||
clearingCache = false;
|
clearingCache = false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
public void onLowMemory(float percent) {
|
public void onLowMemory(float percent) {
|
||||||
Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize());
|
Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize());
|
||||||
cache.resize(Math.round(cacheSize * (1 - percent)));
|
cache.resize(Math.round(cacheSize * (1 - percent)));
|
||||||
}
|
}
|
||||||
public void onUIVisible() {
|
public void onUIVisible() {
|
||||||
if(cache.maxSize() != cacheSize) {
|
if(cache.maxSize() != cacheSize) {
|
||||||
Log.i(TAG, "Returned to full cache size");
|
Log.i(TAG, "Returned to full cache size");
|
||||||
cache.resize(cacheSize);
|
cache.resize(cacheSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNowPlayingSmall(Bitmap bitmap) {
|
public void setNowPlayingSmall(Bitmap bitmap) {
|
||||||
nowPlayingSmall = bitmap;
|
nowPlayingSmall = bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) {
|
private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) {
|
||||||
String key;
|
String key;
|
||||||
int color;
|
int color;
|
||||||
if(entry == null) {
|
if(entry == null) {
|
||||||
key = getKey("unknown", size);
|
key = getKey("unknown", size);
|
||||||
color = COLORS[0];
|
color = COLORS[0];
|
||||||
|
|
||||||
return getUnknownImage(key, size, color, null, null);
|
return getUnknownImage(key, size, color, null, null);
|
||||||
} else {
|
} else {
|
||||||
key = getKey(entry.getId() + "unknown", size);
|
key = getKey(entry.getId() + "unknown", size);
|
||||||
String hash;
|
String hash;
|
||||||
if(entry.getAlbum() != null) {
|
if(entry.getAlbum() != null) {
|
||||||
hash = entry.getAlbum();
|
hash = entry.getAlbum();
|
||||||
} else if(entry.getArtist() != null) {
|
} else if(entry.getArtist() != null) {
|
||||||
hash = entry.getArtist();
|
hash = entry.getArtist();
|
||||||
} else {
|
} else {
|
||||||
hash = entry.getId();
|
hash = entry.getId();
|
||||||
}
|
}
|
||||||
color = COLORS[Math.abs(hash.hashCode()) % COLORS.length];
|
color = COLORS[Math.abs(hash.hashCode()) % COLORS.length];
|
||||||
|
|
||||||
return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist());
|
return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) {
|
private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) {
|
||||||
Bitmap bitmap = cache.get(key);
|
Bitmap bitmap = cache.get(key);
|
||||||
if(bitmap == null) {
|
if(bitmap == null) {
|
||||||
bitmap = createUnknownImage(size, color, topText, bottomText);
|
bitmap = createUnknownImage(size, color, topText, bottomText);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) {
|
private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) {
|
||||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
|
||||||
Paint color = new Paint();
|
Paint color = new Paint();
|
||||||
color.setColor(primaryColor);
|
color.setColor(primaryColor);
|
||||||
canvas.drawRect(0, 0, size, size * 2.0f / 3.0f, color);
|
canvas.drawRect(0, 0, size, size * 2.0f / 3.0f, color);
|
||||||
|
|
||||||
color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR));
|
color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR));
|
||||||
canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color);
|
canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color);
|
||||||
|
|
||||||
if(topText != null || bottomText != null) {
|
if(topText != null || bottomText != null) {
|
||||||
Paint font = new Paint();
|
Paint font = new Paint();
|
||||||
font.setFlags(Paint.ANTI_ALIAS_FLAG);
|
font.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||||
font.setColor(Color.WHITE);
|
font.setColor(Color.WHITE);
|
||||||
font.setTextSize(3.0f + size * 0.07f);
|
font.setTextSize(3.0f + size * 0.07f);
|
||||||
|
|
||||||
if(topText != null) {
|
if(topText != null) {
|
||||||
canvas.drawText(topText, size * 0.05f, size * 0.6f, font);
|
canvas.drawText(topText, size * 0.05f, size * 0.6f, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bottomText != null) {
|
if(bottomText != null) {
|
||||||
canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font);
|
canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bitmap getCachedImage(Context context, MusicDirectory.Entry entry, boolean large) {
|
public Bitmap getCachedImage(Context context, MusicDirectory.Entry entry, boolean large) {
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
if(entry == null || entry.getCoverArt() == null) {
|
if(entry == null || entry.getCoverArt() == null) {
|
||||||
return getUnknownImage(entry, size);
|
return getUnknownImage(entry, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
Bitmap bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
||||||
if(bitmap == null || bitmap.isRecycled()) {
|
if(bitmap == null || bitmap.isRecycled()) {
|
||||||
bitmap = FileUtil.getAlbumArtBitmap(context, entry, size);
|
bitmap = FileUtil.getAlbumArtBitmap(context, entry, size);
|
||||||
String key = getKey(entry.getCoverArt(), size);
|
String key = getKey(entry.getCoverArt(), size);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
cache.get(key);
|
cache.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bitmap != null && bitmap.isRecycled()) {
|
if(bitmap != null && bitmap.isRecycled()) {
|
||||||
bitmap = null;
|
bitmap = null;
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
|
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, boolean crossfade) {
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
return loadImage(view, entry, large, size, crossfade);
|
return loadImage(view, entry, large, size, crossfade);
|
||||||
}
|
}
|
||||||
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
|
public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) {
|
||||||
// If we know this a artist, try to load artist info instead
|
// If we know this a artist, try to load artist info instead
|
||||||
if(entry != null && !entry.isAlbum() && !Util.isOffline(context)) {
|
if(entry != null && !entry.isAlbum() && !Util.isOffline(context)) {
|
||||||
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
||||||
task.execute();
|
task.execute();
|
||||||
return task;
|
return task;
|
||||||
} else if(entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) {
|
} else if(entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) {
|
||||||
// Try to lookup child cover art
|
// Try to lookup child cover art
|
||||||
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, entry, true);
|
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, entry, true);
|
||||||
if(firstChild != null) {
|
if(firstChild != null) {
|
||||||
entry.setCoverArt(firstChild.getCoverArt());
|
entry.setCoverArt(firstChild.getCoverArt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap bitmap;
|
Bitmap bitmap;
|
||||||
if (entry == null || entry.getCoverArt() == null) {
|
if (entry == null || entry.getCoverArt() == null) {
|
||||||
bitmap = getUnknownImage(entry, size);
|
bitmap = getUnknownImage(entry, size);
|
||||||
setImage(view, Util.createDrawableFromBitmap(context, bitmap), crossfade);
|
setImage(view, Util.createDrawableFromBitmap(context, bitmap), crossfade);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
bitmap = cache.get(getKey(entry.getCoverArt(), size));
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
||||||
setImage(view, drawable, crossfade);
|
setImage(view, drawable, crossfade);
|
||||||
if(large) {
|
if(large) {
|
||||||
nowPlaying = bitmap;
|
nowPlaying = bitmap;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!large) {
|
if (!large) {
|
||||||
setImage(view, null, false);
|
setImage(view, null, false);
|
||||||
}
|
}
|
||||||
ImageTask task = new ViewImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
ImageTask task = new ViewImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade);
|
||||||
task.execute();
|
task.execute();
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SilentBackgroundTask<Void> loadImage(View view, String url, boolean large) {
|
public SilentBackgroundTask<Void> loadImage(View view, String url, boolean large) {
|
||||||
Bitmap bitmap;
|
Bitmap bitmap;
|
||||||
int size = large ? imageSizeLarge : imageSizeDefault;
|
int size = large ? imageSizeLarge : imageSizeDefault;
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
String key = getKey(url + "unknown", size);
|
String key = getKey(url + "unknown", size);
|
||||||
int color = COLORS[Math.abs(key.hashCode()) % COLORS.length];
|
int color = COLORS[Math.abs(key.hashCode()) % COLORS.length];
|
||||||
bitmap = getUnknownImage(key, size, color, null, null);
|
bitmap = getUnknownImage(key, size, color, null, null);
|
||||||
setImage(view, Util.createDrawableFromBitmap(context, bitmap), true);
|
setImage(view, Util.createDrawableFromBitmap(context, bitmap), true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap = cache.get(getKey(url, size));
|
bitmap = cache.get(getKey(url, size));
|
||||||
if (bitmap != null && !bitmap.isRecycled()) {
|
if (bitmap != null && !bitmap.isRecycled()) {
|
||||||
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap);
|
||||||
setImage(view, drawable, true);
|
setImage(view, drawable, true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
setImage(view, null, false);
|
setImage(view, null, false);
|
||||||
|
|
||||||
SilentBackgroundTask<Void> task = new ViewUrlTask(view.getContext(), view, url, size);
|
SilentBackgroundTask<Void> task = new ViewUrlTask(view.getContext(), view, url, size);
|
||||||
task.execute();
|
task.execute();
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SilentBackgroundTask loadImage(View view, Playlist playlist, boolean large, boolean crossfade) {
|
public SilentBackgroundTask loadImage(View view, Playlist playlist, boolean large, boolean crossfade) {
|
||||||
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
MusicDirectory.Entry entry = new MusicDirectory.Entry();
|
||||||
String id;
|
String id;
|
||||||
if(Util.isOffline(context)) {
|
if(Util.isOffline(context)) {
|
||||||
id = PLAYLIST_PREFIX + playlist.getName();
|
id = PLAYLIST_PREFIX + playlist.getName();
|
||||||
entry.setTitle(playlist.getComment());
|
entry.setTitle(playlist.getComment());
|
||||||
} else {
|
} else {
|
||||||
id = PLAYLIST_PREFIX + playlist.getId();
|
id = PLAYLIST_PREFIX + playlist.getId();
|
||||||
entry.setTitle(playlist.getName());
|
entry.setTitle(playlist.getName());
|
||||||
}
|
}
|
||||||
entry.setId(id);
|
entry.setId(id);
|
||||||
entry.setCoverArt(id);
|
entry.setCoverArt(id);
|
||||||
// So this isn't treated as a artist
|
// So this isn't treated as a artist
|
||||||
entry.setParent("");
|
entry.setParent("");
|
||||||
|
|
||||||
return loadImage(view, entry, large, crossfade);
|
return loadImage(view, entry, large, crossfade);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getKey(String coverArtId, int size) {
|
private String getKey(String coverArtId, int size) {
|
||||||
return coverArtId + size;
|
return coverArtId + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setImage(View view, final Drawable drawable, boolean crossfade) {
|
private void setImage(View view, final Drawable drawable, boolean crossfade) {
|
||||||
if (view instanceof TextView) {
|
if (view instanceof TextView) {
|
||||||
// Cross-fading is not implemented for TextView since it's not in use. It would be easy to add it, though.
|
// Cross-fading is not implemented for TextView since it's not in use. It would be easy to add it, though.
|
||||||
TextView textView = (TextView) view;
|
TextView textView = (TextView) view;
|
||||||
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
|
||||||
} else if (view instanceof ImageView) {
|
} else if (view instanceof ImageView) {
|
||||||
final ImageView imageView = (ImageView) view;
|
final ImageView imageView = (ImageView) view;
|
||||||
if (crossfade && drawable != null) {
|
if (crossfade && drawable != null) {
|
||||||
Drawable existingDrawable = imageView.getDrawable();
|
Drawable existingDrawable = imageView.getDrawable();
|
||||||
if (existingDrawable == null) {
|
if (existingDrawable == null) {
|
||||||
Bitmap emptyImage;
|
Bitmap emptyImage;
|
||||||
if(drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
|
if(drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) {
|
||||||
emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||||
} else {
|
} else {
|
||||||
emptyImage = Bitmap.createBitmap(imageSizeDefault, imageSizeDefault, Bitmap.Config.ARGB_8888);
|
emptyImage = Bitmap.createBitmap(imageSizeDefault, imageSizeDefault, Bitmap.Config.ARGB_8888);
|
||||||
}
|
}
|
||||||
existingDrawable = new BitmapDrawable(context.getResources(), emptyImage);
|
existingDrawable = new BitmapDrawable(context.getResources(), emptyImage);
|
||||||
} else if(existingDrawable instanceof TransitionDrawable) {
|
} else if(existingDrawable instanceof TransitionDrawable) {
|
||||||
// This should only ever be used if user is skipping through many songs quickly
|
// This should only ever be used if user is skipping through many songs quickly
|
||||||
TransitionDrawable tmp = (TransitionDrawable) existingDrawable;
|
TransitionDrawable tmp = (TransitionDrawable) existingDrawable;
|
||||||
existingDrawable = tmp.getDrawable(tmp.getNumberOfLayers() - 1);
|
existingDrawable = tmp.getDrawable(tmp.getNumberOfLayers() - 1);
|
||||||
}
|
}
|
||||||
if(existingDrawable != null && drawable != null) {
|
if(existingDrawable != null && drawable != null) {
|
||||||
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
Drawable[] layers = new Drawable[]{existingDrawable, drawable};
|
||||||
final TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
final TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
||||||
imageView.setImageDrawable(transitionDrawable);
|
imageView.setImageDrawable(transitionDrawable);
|
||||||
transitionDrawable.startTransition(250);
|
transitionDrawable.startTransition(250);
|
||||||
|
|
||||||
// Get rid of transition drawable after transition occurs
|
// Get rid of transition drawable after transition occurs
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// Only execute if still on same transition drawable
|
// Only execute if still on same transition drawable
|
||||||
if (imageView.getDrawable() == transitionDrawable) {
|
if (imageView.getDrawable() == transitionDrawable) {
|
||||||
imageView.setImageDrawable(drawable);
|
imageView.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 500L);
|
}, 500L);
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageDrawable(drawable);
|
imageView.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageDrawable(drawable);
|
imageView.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class ImageTask extends SilentBackgroundTask<Void> {
|
public abstract class ImageTask extends SilentBackgroundTask<Void> {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
protected final MusicDirectory.Entry mEntry;
|
protected final MusicDirectory.Entry mEntry;
|
||||||
private final int mSize;
|
private final int mSize;
|
||||||
private final int mSaveSize;
|
private final int mSaveSize;
|
||||||
private final boolean mIsNowPlaying;
|
private final boolean mIsNowPlaying;
|
||||||
protected Drawable mDrawable;
|
protected Drawable mDrawable;
|
||||||
|
|
||||||
public ImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying) {
|
public ImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
mSize = size;
|
mSize = size;
|
||||||
mSaveSize = saveSize;
|
mSaveSize = saveSize;
|
||||||
mIsNowPlaying = isNowPlaying;
|
mIsNowPlaying = isNowPlaying;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
||||||
Bitmap bitmap = musicService.getCoverArt(mContext, mEntry, mSize, null, this);
|
Bitmap bitmap = musicService.getCoverArt(mContext, mEntry, mSize, null, this);
|
||||||
if(bitmap != null) {
|
if(bitmap != null) {
|
||||||
String key = getKey(mEntry.getCoverArt(), mSize);
|
String key = getKey(mEntry.getCoverArt(), mSize);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
// Make sure key is the most recently "used"
|
// Make sure key is the most recently "used"
|
||||||
cache.get(key);
|
cache.get(key);
|
||||||
if (mIsNowPlaying) {
|
if (mIsNowPlaying) {
|
||||||
nowPlaying = bitmap;
|
nowPlaying = bitmap;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bitmap = getUnknownImage(mEntry, mSize);
|
bitmap = getUnknownImage(mEntry, mSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
|
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.e(TAG, "Failed to download album art.", x);
|
Log.e(TAG, "Failed to download album art.", x);
|
||||||
cancelled.set(true);
|
cancelled.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ViewImageTask extends ImageTask {
|
private class ViewImageTask extends ImageTask {
|
||||||
protected boolean mCrossfade;
|
protected boolean mCrossfade;
|
||||||
private View mView;
|
private View mView;
|
||||||
|
|
||||||
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
||||||
super(context, entry, size, saveSize, isNowPlaying);
|
super(context, entry, size, saveSize, isNowPlaying);
|
||||||
|
|
||||||
mView = view;
|
mView = view;
|
||||||
mCrossfade = crossfade;
|
mCrossfade = crossfade;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
setImage(mView, mDrawable, mCrossfade);
|
setImage(mView, mDrawable, mCrossfade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ArtistImageTask extends SilentBackgroundTask<Void> {
|
private class ArtistImageTask extends SilentBackgroundTask<Void> {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final MusicDirectory.Entry mEntry;
|
private final MusicDirectory.Entry mEntry;
|
||||||
private final int mSize;
|
private final int mSize;
|
||||||
private final int mSaveSize;
|
private final int mSaveSize;
|
||||||
private final boolean mIsNowPlaying;
|
private final boolean mIsNowPlaying;
|
||||||
private Drawable mDrawable;
|
private Drawable mDrawable;
|
||||||
private boolean mCrossfade;
|
private boolean mCrossfade;
|
||||||
private View mView;
|
private View mView;
|
||||||
|
|
||||||
private SilentBackgroundTask subTask;
|
private SilentBackgroundTask subTask;
|
||||||
|
|
||||||
public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
mSize = size;
|
mSize = size;
|
||||||
mSaveSize = saveSize;
|
mSaveSize = saveSize;
|
||||||
mIsNowPlaying = isNowPlaying;
|
mIsNowPlaying = isNowPlaying;
|
||||||
mView = view;
|
mView = view;
|
||||||
mCrossfade = crossfade;
|
mCrossfade = crossfade;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
||||||
|
|
||||||
// Figure out whether we are going to get a artist image or the standard image
|
// Figure out whether we are going to get a artist image or the standard image
|
||||||
if (mEntry != null && mEntry.getCoverArt() == null && mEntry.isDirectory() && !Util.isOffline(context)) {
|
if (mEntry != null && mEntry.getCoverArt() == null && mEntry.isDirectory() && !Util.isOffline(context)) {
|
||||||
// Try to lookup child cover art
|
// Try to lookup child cover art
|
||||||
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, mEntry, true);
|
MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, mEntry, true);
|
||||||
@ -451,72 +451,72 @@ public class ImageLoader {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute whichever way we decided to go
|
// Execute whichever way we decided to go
|
||||||
subTask.doInBackground();
|
subTask.doInBackground();
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.e(TAG, "Failed to get artist info", x);
|
Log.e(TAG, "Failed to get artist info", x);
|
||||||
cancelled.set(true);
|
cancelled.set(true);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done(Void result) {
|
public void done(Void result) {
|
||||||
if(subTask != null) {
|
if(subTask != null) {
|
||||||
subTask.done(result);
|
subTask.done(result);
|
||||||
} else if(mDrawable != null) {
|
} else if(mDrawable != null) {
|
||||||
setImage(mView, mDrawable, mCrossfade);
|
setImage(mView, mDrawable, mCrossfade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ViewUrlTask extends SilentBackgroundTask<Void> {
|
private class ViewUrlTask extends SilentBackgroundTask<Void> {
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final String mUrl;
|
private final String mUrl;
|
||||||
private final ImageView mView;
|
private final ImageView mView;
|
||||||
private Drawable mDrawable;
|
private Drawable mDrawable;
|
||||||
private int mSize;
|
private int mSize;
|
||||||
|
|
||||||
public ViewUrlTask(Context context, View view, String url, int size) {
|
public ViewUrlTask(Context context, View view, String url, int size) {
|
||||||
super(context);
|
super(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mView = (ImageView) view;
|
mView = (ImageView) view;
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
mSize = size;
|
mSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
try {
|
try {
|
||||||
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
MusicService musicService = MusicServiceFactory.getMusicService(mContext);
|
||||||
Bitmap bitmap = musicService.getBitmap(mUrl, mSize, mContext, null, this);
|
Bitmap bitmap = musicService.getBitmap(mUrl, mSize, mContext, null, this);
|
||||||
if(bitmap != null) {
|
if(bitmap != null) {
|
||||||
String key = getKey(mUrl, mSize);
|
String key = getKey(mUrl, mSize);
|
||||||
cache.put(key, bitmap);
|
cache.put(key, bitmap);
|
||||||
// Make sure key is the most recently "used"
|
// Make sure key is the most recently "used"
|
||||||
cache.get(key);
|
cache.get(key);
|
||||||
|
|
||||||
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
|
mDrawable = Util.createDrawableFromBitmap(mContext, bitmap);
|
||||||
}
|
}
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
Log.e(TAG, "Failed to download from url " + mUrl, x);
|
Log.e(TAG, "Failed to download from url " + mUrl, x);
|
||||||
cancelled.set(true);
|
cancelled.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
if(mDrawable != null) {
|
if(mDrawable != null) {
|
||||||
mView.setImageDrawable(mDrawable);
|
mView.setImageDrawable(mDrawable);
|
||||||
} else {
|
} else {
|
||||||
failedToDownload();
|
failedToDownload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void failedToDownload() {
|
protected void failedToDownload() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,61 +13,61 @@ import net.nullsum.audinaut.activity.SubsonicActivity;
|
|||||||
public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
public abstract class LoadingTask<T> extends BackgroundTask<T> {
|
||||||
|
|
||||||
private final Activity tabActivity;
|
private final Activity tabActivity;
|
||||||
private ProgressDialog loading;
|
private ProgressDialog loading;
|
||||||
private final boolean cancellable;
|
private final boolean cancellable;
|
||||||
|
|
||||||
public LoadingTask(Activity activity) {
|
public LoadingTask(Activity activity) {
|
||||||
super(activity);
|
super(activity);
|
||||||
tabActivity = activity;
|
tabActivity = activity;
|
||||||
this.cancellable = true;
|
this.cancellable = true;
|
||||||
}
|
}
|
||||||
public LoadingTask(Activity activity, final boolean cancellable) {
|
public LoadingTask(Activity activity, final boolean cancellable) {
|
||||||
super(activity);
|
super(activity);
|
||||||
tabActivity = activity;
|
tabActivity = activity;
|
||||||
this.cancellable = cancellable;
|
this.cancellable = cancellable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() {
|
loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() {
|
||||||
public void onCancel(DialogInterface dialog) {
|
public void onCancel(DialogInterface dialog) {
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
queue.offer(task = new Task() {
|
queue.offer(task = new Task() {
|
||||||
@Override
|
@Override
|
||||||
public void onDone(T result) {
|
public void onDone(T result) {
|
||||||
if(loading.isShowing()) {
|
if(loading.isShowing()) {
|
||||||
loading.dismiss();
|
loading.dismiss();
|
||||||
}
|
}
|
||||||
done(result);
|
done(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
if(loading.isShowing()) {
|
if(loading.isShowing()) {
|
||||||
loading.dismiss();
|
loading.dismiss();
|
||||||
}
|
}
|
||||||
error(t);
|
error(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return (tabActivity instanceof SubsonicActivity && ((SubsonicActivity) tabActivity).isDestroyedCompat()) || cancelled.get();
|
return (tabActivity instanceof SubsonicActivity && ((SubsonicActivity) tabActivity).isDestroyedCompat()) || cancelled.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(final String message) {
|
public void updateProgress(final String message) {
|
||||||
if(!cancelled.get()) {
|
if(!cancelled.get()) {
|
||||||
getHandler().post(new Runnable() {
|
getHandler().post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
loading.setMessage(message);
|
loading.setMessage(message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -31,53 +31,53 @@ import net.nullsum.audinaut.view.SongView;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public final class MenuUtil {
|
public final class MenuUtil {
|
||||||
private final static String TAG = MenuUtil.class.getSimpleName();
|
private final static String TAG = MenuUtil.class.getSimpleName();
|
||||||
|
|
||||||
public static void hideMenuItems(Context context, Menu menu, UpdateView updateView) {
|
public static void hideMenuItems(Context context, Menu menu, UpdateView updateView) {
|
||||||
if(!Util.isOffline(context)) {
|
if(!Util.isOffline(context)) {
|
||||||
// If we are looking at a standard song view, get downloadFile to cache what options to show
|
// If we are looking at a standard song view, get downloadFile to cache what options to show
|
||||||
if(updateView instanceof SongView) {
|
if(updateView instanceof SongView) {
|
||||||
SongView songView = (SongView) updateView;
|
SongView songView = (SongView) updateView;
|
||||||
DownloadFile downloadFile = songView.getDownloadFile();
|
DownloadFile downloadFile = songView.getDownloadFile();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(downloadFile != null) {
|
if(downloadFile != null) {
|
||||||
if(downloadFile.isWorkDone()) {
|
if(downloadFile.isWorkDone()) {
|
||||||
// Remove permanent cache menu if already perma cached
|
// Remove permanent cache menu if already perma cached
|
||||||
if(downloadFile.isSaved()) {
|
if(downloadFile.isSaved()) {
|
||||||
menu.setGroupVisible(R.id.hide_pin, false);
|
menu.setGroupVisible(R.id.hide_pin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove cache option no matter what if already downloaded
|
// Remove cache option no matter what if already downloaded
|
||||||
menu.setGroupVisible(R.id.hide_download, false);
|
menu.setGroupVisible(R.id.hide_download, false);
|
||||||
} else {
|
} else {
|
||||||
// Remove delete option if nothing to delete
|
// Remove delete option if nothing to delete
|
||||||
menu.setGroupVisible(R.id.hide_delete, false);
|
menu.setGroupVisible(R.id.hide_delete, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to lookup downloadFile info", e);
|
Log.w(TAG, "Failed to lookup downloadFile info", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Apply similar logic to album views
|
// Apply similar logic to album views
|
||||||
else if(updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) {
|
else if(updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) {
|
||||||
File folder = null;
|
File folder = null;
|
||||||
if(updateView instanceof AlbumView) {
|
if(updateView instanceof AlbumView) {
|
||||||
folder = ((AlbumView) updateView).getFile();
|
folder = ((AlbumView) updateView).getFile();
|
||||||
} else if(updateView instanceof ArtistView) {
|
} else if(updateView instanceof ArtistView) {
|
||||||
folder = ((ArtistView) updateView).getFile();
|
folder = ((ArtistView) updateView).getFile();
|
||||||
} else if(updateView instanceof ArtistEntryView) {
|
} else if(updateView instanceof ArtistEntryView) {
|
||||||
folder = ((ArtistEntryView) updateView).getFile();
|
folder = ((ArtistEntryView) updateView).getFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(folder != null && !folder.exists()) {
|
if(folder != null && !folder.exists()) {
|
||||||
menu.setGroupVisible(R.id.hide_delete, false);
|
menu.setGroupVisible(R.id.hide_delete, false);
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Failed to lookup album directory info", e);
|
Log.w(TAG, "Failed to lookup album directory info", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,5 +24,5 @@ package net.nullsum.audinaut.util;
|
|||||||
public interface ProgressListener {
|
public interface ProgressListener {
|
||||||
void updateProgress(String message);
|
void updateProgress(String message);
|
||||||
void updateProgress(int messageId);
|
void updateProgress(int messageId);
|
||||||
void updateCache(int changeCode);
|
void updateCache(int changeCode);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of ServerProxy.
|
This file is part of ServerProxy.
|
||||||
SocketProxy is free software: you can redistribute it and/or modify
|
SocketProxy is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -40,192 +40,192 @@ import android.net.wifi.WifiManager;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public abstract class ServerProxy implements Runnable {
|
public abstract class ServerProxy implements Runnable {
|
||||||
private static final String TAG = ServerProxy.class.getSimpleName();
|
private static final String TAG = ServerProxy.class.getSimpleName();
|
||||||
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
protected boolean isRunning;
|
protected boolean isRunning;
|
||||||
private ServerSocket socket;
|
private ServerSocket socket;
|
||||||
private int port;
|
private int port;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
public ServerProxy(Context context) {
|
public ServerProxy(Context context) {
|
||||||
// Create listening socket
|
// Create listening socket
|
||||||
try {
|
try {
|
||||||
socket = new ServerSocket(0);
|
socket = new ServerSocket(0);
|
||||||
socket.setSoTimeout(5000);
|
socket.setSoTimeout(5000);
|
||||||
port = socket.getLocalPort();
|
port = socket.getLocalPort();
|
||||||
this.context = context;
|
this.context = context;
|
||||||
} catch (UnknownHostException e) { // impossible
|
} catch (UnknownHostException e) { // impossible
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "IOException initializing server", e);
|
Log.e(TAG, "IOException initializing server", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
if(socket.isBound()) {
|
if(socket.isBound()) {
|
||||||
thread = new Thread(this, "Socket Proxy");
|
thread = new Thread(this, "Socket Proxy");
|
||||||
thread.start();
|
thread.start();
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Attempting to start a non-initialized proxy");
|
Log.e(TAG, "Attempting to start a non-initialized proxy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
if(thread != null) {
|
if(thread != null) {
|
||||||
thread.interrupt();
|
thread.interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrivateAddress(String request) {
|
public String getPrivateAddress(String request) {
|
||||||
return getAddress("127.0.0.1", request);
|
return getAddress("127.0.0.1", request);
|
||||||
}
|
}
|
||||||
public String getPublicAddress(String request) {
|
public String getPublicAddress(String request) {
|
||||||
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||||
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
int ipAddress = wifiManager.getConnectionInfo().getIpAddress();
|
||||||
|
|
||||||
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
|
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
|
||||||
ipAddress = Integer.reverseBytes(ipAddress);
|
ipAddress = Integer.reverseBytes(ipAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray();
|
byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray();
|
||||||
String ipAddressString = null;
|
String ipAddressString = null;
|
||||||
try {
|
try {
|
||||||
ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress();
|
ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress();
|
||||||
} catch(UnknownHostException ex) {
|
} catch(UnknownHostException ex) {
|
||||||
Log.e(TAG, "Unable to get host address.");
|
Log.e(TAG, "Unable to get host address.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return getAddress(ipAddressString, request);
|
return getAddress(ipAddressString, request);
|
||||||
}
|
}
|
||||||
private String getAddress(String host, String request) {
|
private String getAddress(String host, String request) {
|
||||||
try {
|
try {
|
||||||
return String.format("http://%s:%d/%s", host, port, URLEncoder.encode(request, "UTF-8"));
|
return String.format("http://%s:%d/%s", host, port, URLEncoder.encode(request, "UTF-8"));
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
while (isRunning) {
|
while (isRunning) {
|
||||||
try {
|
try {
|
||||||
Socket client = socket.accept();
|
Socket client = socket.accept();
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "client connected");
|
Log.i(TAG, "client connected");
|
||||||
|
|
||||||
ProxyTask task = getTask(client);
|
ProxyTask task = getTask(client);
|
||||||
if (task.processRequest()) {
|
if (task.processRequest()) {
|
||||||
new Thread(task, "ProxyTask").start();
|
new Thread(task, "ProxyTask").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (SocketTimeoutException e) {
|
} catch (SocketTimeoutException e) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Error connecting to client", e);
|
Log.e(TAG, "Error connecting to client", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Proxy interrupted. Shutting down.");
|
Log.i(TAG, "Proxy interrupted. Shutting down.");
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract ProxyTask getTask(Socket client);
|
abstract ProxyTask getTask(Socket client);
|
||||||
|
|
||||||
protected abstract class ProxyTask implements Runnable {
|
protected abstract class ProxyTask implements Runnable {
|
||||||
protected Socket client;
|
protected Socket client;
|
||||||
protected String path;
|
protected String path;
|
||||||
protected int cbSkip = 0;
|
protected int cbSkip = 0;
|
||||||
protected Map<String, String> requestHeaders = new HashMap<>();
|
protected Map<String, String> requestHeaders = new HashMap<>();
|
||||||
|
|
||||||
public ProxyTask(Socket client) {
|
public ProxyTask(Socket client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean readRequest() {
|
protected boolean readRequest() {
|
||||||
InputStream is;
|
InputStream is;
|
||||||
String firstLine;
|
String firstLine;
|
||||||
BufferedReader reader;
|
BufferedReader reader;
|
||||||
try {
|
try {
|
||||||
is = client.getInputStream();
|
is = client.getInputStream();
|
||||||
reader = new BufferedReader(new InputStreamReader(is), 8192);
|
reader = new BufferedReader(new InputStreamReader(is), 8192);
|
||||||
firstLine = reader.readLine();
|
firstLine = reader.readLine();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Error parsing request", e);
|
Log.e(TAG, "Error parsing request", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstLine == null) {
|
if (firstLine == null) {
|
||||||
Log.i(TAG, "Proxy client closed connection without a request.");
|
Log.i(TAG, "Proxy client closed connection without a request.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTokenizer st = new StringTokenizer(firstLine);
|
StringTokenizer st = new StringTokenizer(firstLine);
|
||||||
if(!st.hasMoreTokens()) {
|
if(!st.hasMoreTokens()) {
|
||||||
Log.w(TAG, "Unknown request with no tokens");
|
Log.w(TAG, "Unknown request with no tokens");
|
||||||
return false;
|
return false;
|
||||||
} else if(st.countTokens() < 2) {
|
} else if(st.countTokens() < 2) {
|
||||||
Log.w(TAG, "Unknown request with no uri: \"" + firstLine + '"');
|
Log.w(TAG, "Unknown request with no uri: \"" + firstLine + '"');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String method = st.nextToken();
|
String method = st.nextToken();
|
||||||
String uri = st.nextToken();
|
String uri = st.nextToken();
|
||||||
String realUri = uri.substring(1);
|
String realUri = uri.substring(1);
|
||||||
|
|
||||||
// Process path
|
// Process path
|
||||||
try {
|
try {
|
||||||
path = URLDecoder.decode(realUri, "UTF-8");
|
path = URLDecoder.decode(realUri, "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
Log.e(TAG, "Unsupported encoding", e);
|
Log.e(TAG, "Unsupported encoding", e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all of the headers
|
// Get all of the headers
|
||||||
try {
|
try {
|
||||||
String line;
|
String line;
|
||||||
while((line = reader.readLine()) != null && !"".equals(line)) {
|
while((line = reader.readLine()) != null && !"".equals(line)) {
|
||||||
int index = line.indexOf(':');
|
int index = line.indexOf(':');
|
||||||
// Ignore headers without ':' or where ':' is the last thing in the string
|
// Ignore headers without ':' or where ':' is the last thing in the string
|
||||||
if(index != -1 && (index + 2) < line.length()) {
|
if(index != -1 && (index + 2) < line.length()) {
|
||||||
String headerName = line.substring(0, index);
|
String headerName = line.substring(0, index);
|
||||||
String headerValue = line.substring(index + 2);
|
String headerValue = line.substring(index + 2);
|
||||||
|
|
||||||
requestHeaders.put(headerName, headerValue);
|
requestHeaders.put(headerName, headerValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
// Don't really care once past first line
|
// Don't really care once past first line
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Log.w(TAG, "Exception reading request", e);
|
Log.w(TAG, "Exception reading request", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean processRequest() {
|
public boolean processRequest() {
|
||||||
if (!readRequest()) {
|
if (!readRequest()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Processing request for " + path);
|
Log.i(TAG, "Processing request for " + path);
|
||||||
|
|
||||||
// Try to get range requested
|
// Try to get range requested
|
||||||
String range = requestHeaders.get("Range");
|
String range = requestHeaders.get("Range");
|
||||||
if(range != null) {
|
if(range != null) {
|
||||||
int index = range.indexOf("=");
|
int index = range.indexOf("=");
|
||||||
if(index >= 0) {
|
if(index >= 0) {
|
||||||
range = range.substring(index + 1);
|
range = range.substring(index + 1);
|
||||||
|
|
||||||
index = range.indexOf("-");
|
index = range.indexOf("-");
|
||||||
if(index > 0) {
|
if(index > 0) {
|
||||||
range = range.substring(0, index);
|
range = range.substring(0, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
cbSkip = Integer.parseInt(range);
|
cbSkip = Integer.parseInt(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2009 (C) Sindre Mehus
|
Copyright 2009 (C) Sindre Mehus
|
||||||
*/
|
*/
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
|
|
||||||
@ -29,16 +29,16 @@ import java.io.IOException;
|
|||||||
import net.nullsum.audinaut.util.Constants;
|
import net.nullsum.audinaut.util.Constants;
|
||||||
|
|
||||||
public class SettingsBackupAgent extends BackupAgentHelper {
|
public class SettingsBackupAgent extends BackupAgentHelper {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, Constants.PREFERENCES_FILE_NAME);
|
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, Constants.PREFERENCES_FILE_NAME);
|
||||||
addHelper("mypreferences", helper);
|
addHelper("mypreferences", helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException{
|
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException{
|
||||||
super.onRestore(data, appVersionCode, newState);
|
super.onRestore(data, appVersionCode, newState);
|
||||||
Util.getPreferences(this).edit().remove(Constants.PREFERENCES_KEY_CACHE_LOCATION).apply();
|
Util.getPreferences(this).edit().remove(Constants.PREFERENCES_KEY_CACHE_LOCATION).apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,173 +40,173 @@ import net.nullsum.audinaut.util.FileUtil;
|
|||||||
*/
|
*/
|
||||||
public class ShufflePlayBuffer {
|
public class ShufflePlayBuffer {
|
||||||
|
|
||||||
private static final String TAG = ShufflePlayBuffer.class.getSimpleName();
|
private static final String TAG = ShufflePlayBuffer.class.getSimpleName();
|
||||||
private static final String CACHE_FILENAME = "shuffleBuffer.ser";
|
private static final String CACHE_FILENAME = "shuffleBuffer.ser";
|
||||||
|
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
private Runnable runnable;
|
private Runnable runnable;
|
||||||
private boolean firstRun = true;
|
private boolean firstRun = true;
|
||||||
private final ArrayList<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
|
private final ArrayList<MusicDirectory.Entry> buffer = new ArrayList<MusicDirectory.Entry>();
|
||||||
private int lastCount = -1;
|
private int lastCount = -1;
|
||||||
private DownloadService context;
|
private DownloadService context;
|
||||||
private boolean awaitingResults = false;
|
private boolean awaitingResults = false;
|
||||||
private int capacity;
|
private int capacity;
|
||||||
private int refillThreshold;
|
private int refillThreshold;
|
||||||
|
|
||||||
private SharedPreferences.OnSharedPreferenceChangeListener listener;
|
private SharedPreferences.OnSharedPreferenceChangeListener listener;
|
||||||
private int currentServer;
|
private int currentServer;
|
||||||
private String currentFolder = "";
|
private String currentFolder = "";
|
||||||
private String genre = "";
|
private String genre = "";
|
||||||
private String startYear = "";
|
private String startYear = "";
|
||||||
private String endYear = "";
|
private String endYear = "";
|
||||||
|
|
||||||
public ShufflePlayBuffer(DownloadService context) {
|
public ShufflePlayBuffer(DownloadService context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
runnable = new Runnable() {
|
runnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
refill();
|
refill();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS);
|
executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS);
|
||||||
|
|
||||||
// Calculate out the capacity and refill threshold based on the user's random size preference
|
// Calculate out the capacity and refill threshold based on the user's random size preference
|
||||||
int shuffleListSize = Math.max(1, Integer.parseInt(Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_RANDOM_SIZE, "20")));
|
int shuffleListSize = Math.max(1, Integer.parseInt(Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_RANDOM_SIZE, "20")));
|
||||||
// ex: default 20 -> 50
|
// ex: default 20 -> 50
|
||||||
capacity = shuffleListSize * 5 / 2;
|
capacity = shuffleListSize * 5 / 2;
|
||||||
capacity = Math.min(500, capacity);
|
capacity = Math.min(500, capacity);
|
||||||
|
|
||||||
// ex: default 20 -> 40
|
// ex: default 20 -> 40
|
||||||
refillThreshold = capacity * 4 / 5;
|
refillThreshold = capacity * 4 / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MusicDirectory.Entry> get(int size) {
|
public List<MusicDirectory.Entry> get(int size) {
|
||||||
clearBufferIfnecessary();
|
clearBufferIfnecessary();
|
||||||
// Make sure fetcher is running if needed
|
// Make sure fetcher is running if needed
|
||||||
restart();
|
restart();
|
||||||
|
|
||||||
List<MusicDirectory.Entry> result = new ArrayList<MusicDirectory.Entry>(size);
|
List<MusicDirectory.Entry> result = new ArrayList<MusicDirectory.Entry>(size);
|
||||||
synchronized (buffer) {
|
synchronized (buffer) {
|
||||||
boolean removed = false;
|
boolean removed = false;
|
||||||
while (!buffer.isEmpty() && result.size() < size) {
|
while (!buffer.isEmpty() && result.size() < size) {
|
||||||
result.add(buffer.remove(buffer.size() - 1));
|
result.add(buffer.remove(buffer.size() - 1));
|
||||||
removed = true;
|
removed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-cache if anything is taken out
|
// Re-cache if anything is taken out
|
||||||
if(removed) {
|
if(removed) {
|
||||||
FileUtil.serialize(context, buffer, CACHE_FILENAME);
|
FileUtil.serialize(context, buffer, CACHE_FILENAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Taking " + result.size() + " songs from shuffle play buffer. " + buffer.size() + " remaining.");
|
Log.i(TAG, "Taking " + result.size() + " songs from shuffle play buffer. " + buffer.size() + " remaining.");
|
||||||
if(result.isEmpty()) {
|
if(result.isEmpty()) {
|
||||||
awaitingResults = true;
|
awaitingResults = true;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
Util.getPreferences(context).unregisterOnSharedPreferenceChangeListener(listener);
|
Util.getPreferences(context).unregisterOnSharedPreferenceChangeListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restart() {
|
private void restart() {
|
||||||
synchronized(buffer) {
|
synchronized(buffer) {
|
||||||
if(buffer.size() <= refillThreshold && lastCount != 0 && executorService.isShutdown()) {
|
if(buffer.size() <= refillThreshold && lastCount != 0 && executorService.isShutdown()) {
|
||||||
executorService = Executors.newSingleThreadScheduledExecutor();
|
executorService = Executors.newSingleThreadScheduledExecutor();
|
||||||
executorService.scheduleWithFixedDelay(runnable, 0, 10, TimeUnit.SECONDS);
|
executorService.scheduleWithFixedDelay(runnable, 0, 10, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refill() {
|
private void refill() {
|
||||||
// Check if active server has changed.
|
// Check if active server has changed.
|
||||||
clearBufferIfnecessary();
|
clearBufferIfnecessary();
|
||||||
|
|
||||||
if (buffer != null && (buffer.size() > refillThreshold || (!Util.isNetworkConnected(context) && !Util.isOffline(context)) || lastCount == 0)) {
|
if (buffer != null && (buffer.size() > refillThreshold || (!Util.isNetworkConnected(context) && !Util.isOffline(context)) || lastCount == 0)) {
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MusicService service = MusicServiceFactory.getMusicService(context);
|
MusicService service = MusicServiceFactory.getMusicService(context);
|
||||||
|
|
||||||
// Get capacity based
|
// Get capacity based
|
||||||
int n = capacity - buffer.size();
|
int n = capacity - buffer.size();
|
||||||
String folder = null;
|
String folder = null;
|
||||||
if(!Util.isTagBrowsing(context)) {
|
if(!Util.isTagBrowsing(context)) {
|
||||||
folder = Util.getSelectedMusicFolderId(context);
|
folder = Util.getSelectedMusicFolderId(context);
|
||||||
}
|
}
|
||||||
MusicDirectory songs = service.getRandomSongs(n, folder, genre, startYear, endYear, context, null);
|
MusicDirectory songs = service.getRandomSongs(n, folder, genre, startYear, endYear, context, null);
|
||||||
|
|
||||||
synchronized (buffer) {
|
synchronized (buffer) {
|
||||||
lastCount = 0;
|
lastCount = 0;
|
||||||
for(MusicDirectory.Entry entry: songs.getChildren()) {
|
for(MusicDirectory.Entry entry: songs.getChildren()) {
|
||||||
if(!buffer.contains(entry)) {
|
if(!buffer.contains(entry)) {
|
||||||
buffer.add(entry);
|
buffer.add(entry);
|
||||||
lastCount++;
|
lastCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.i(TAG, "Refilled shuffle play buffer with " + lastCount + " songs.");
|
Log.i(TAG, "Refilled shuffle play buffer with " + lastCount + " songs.");
|
||||||
|
|
||||||
// Cache buffer
|
// Cache buffer
|
||||||
FileUtil.serialize(context, buffer, CACHE_FILENAME);
|
FileUtil.serialize(context, buffer, CACHE_FILENAME);
|
||||||
}
|
}
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
// Give it one more try before quitting
|
// Give it one more try before quitting
|
||||||
if(lastCount != -2) {
|
if(lastCount != -2) {
|
||||||
lastCount = -2;
|
lastCount = -2;
|
||||||
} else if(lastCount == -2) {
|
} else if(lastCount == -2) {
|
||||||
lastCount = 0;
|
lastCount = 0;
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Failed to refill shuffle play buffer.", x);
|
Log.w(TAG, "Failed to refill shuffle play buffer.", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(awaitingResults) {
|
if(awaitingResults) {
|
||||||
awaitingResults = false;
|
awaitingResults = false;
|
||||||
context.checkDownloads();
|
context.checkDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearBufferIfnecessary() {
|
private void clearBufferIfnecessary() {
|
||||||
synchronized (buffer) {
|
synchronized (buffer) {
|
||||||
final SharedPreferences prefs = Util.getPreferences(context);
|
final SharedPreferences prefs = Util.getPreferences(context);
|
||||||
if (currentServer != Util.getActiveServer(context)
|
if (currentServer != Util.getActiveServer(context)
|
||||||
|| !Util.equals(currentFolder, Util.getSelectedMusicFolderId(context))
|
|| !Util.equals(currentFolder, Util.getSelectedMusicFolderId(context))
|
||||||
|| (genre != null && !genre.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, "")))
|
|| (genre != null && !genre.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, "")))
|
||||||
|| (startYear != null && !startYear.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, "")))
|
|| (startYear != null && !startYear.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, "")))
|
||||||
|| (endYear != null && !endYear.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, "")))) {
|
|| (endYear != null && !endYear.equals(prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, "")))) {
|
||||||
lastCount = -1;
|
lastCount = -1;
|
||||||
currentServer = Util.getActiveServer(context);
|
currentServer = Util.getActiveServer(context);
|
||||||
currentFolder = Util.getSelectedMusicFolderId(context);
|
currentFolder = Util.getSelectedMusicFolderId(context);
|
||||||
genre = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, "");
|
genre = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, "");
|
||||||
startYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, "");
|
startYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, "");
|
||||||
endYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, "");
|
endYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, "");
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
|
|
||||||
if(firstRun) {
|
if(firstRun) {
|
||||||
ArrayList cacheList = FileUtil.deserialize(context, CACHE_FILENAME, ArrayList.class);
|
ArrayList cacheList = FileUtil.deserialize(context, CACHE_FILENAME, ArrayList.class);
|
||||||
if(cacheList != null) {
|
if(cacheList != null) {
|
||||||
buffer.addAll(cacheList);
|
buffer.addAll(cacheList);
|
||||||
}
|
}
|
||||||
|
|
||||||
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
listener = new SharedPreferences.OnSharedPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||||
clearBufferIfnecessary();
|
clearBufferIfnecessary();
|
||||||
restart();
|
restart();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
prefs.registerOnSharedPreferenceChangeListener(listener);
|
prefs.registerOnSharedPreferenceChangeListener(listener);
|
||||||
firstRun = false;
|
firstRun = false;
|
||||||
} else {
|
} else {
|
||||||
// Clear cache
|
// Clear cache
|
||||||
File file = new File(context.getCacheDir(), CACHE_FILENAME);
|
File file = new File(context.getCacheDir(), CACHE_FILENAME);
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,13 +30,13 @@ public abstract class SilentBackgroundTask<T> extends BackgroundTask<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
queue.offer(task = new Task());
|
queue.offer(task = new Task());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(T result) {
|
protected void done(T result) {
|
||||||
// Don't do anything unless overriden
|
// Don't do anything unless overriden
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(int messageId) {
|
public void updateProgress(int messageId) {
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -25,17 +25,17 @@ import net.nullsum.audinaut.service.MusicService;
|
|||||||
import net.nullsum.audinaut.service.MusicServiceFactory;
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
||||||
|
|
||||||
public abstract class SilentServiceTask<T> extends SilentBackgroundTask<T> {
|
public abstract class SilentServiceTask<T> extends SilentBackgroundTask<T> {
|
||||||
protected MusicService musicService;
|
protected MusicService musicService;
|
||||||
|
|
||||||
public SilentServiceTask(Context context) {
|
public SilentServiceTask(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected T doInBackground() throws Throwable {
|
protected T doInBackground() throws Throwable {
|
||||||
musicService = MusicServiceFactory.getMusicService(getContext());
|
musicService = MusicServiceFactory.getMusicService(getContext());
|
||||||
return doInBackground(musicService);
|
return doInBackground(musicService);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T doInBackground(MusicService musicService) throws Throwable;
|
protected abstract T doInBackground(MusicService musicService) throws Throwable;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -29,235 +29,235 @@ import net.nullsum.audinaut.domain.MusicDirectory;
|
|||||||
import net.nullsum.audinaut.service.DownloadFile;
|
import net.nullsum.audinaut.service.DownloadFile;
|
||||||
|
|
||||||
public class SongDBHandler extends SQLiteOpenHelper {
|
public class SongDBHandler extends SQLiteOpenHelper {
|
||||||
private static final String TAG = SongDBHandler.class.getSimpleName();
|
private static final String TAG = SongDBHandler.class.getSimpleName();
|
||||||
private static SongDBHandler dbHandler;
|
private static SongDBHandler dbHandler;
|
||||||
|
|
||||||
private static final int DATABASE_VERSION = 2;
|
private static final int DATABASE_VERSION = 2;
|
||||||
public static final String DATABASE_NAME = "SongsDB";
|
public static final String DATABASE_NAME = "SongsDB";
|
||||||
|
|
||||||
public static final String TABLE_SONGS = "RegisteredSongs";
|
public static final String TABLE_SONGS = "RegisteredSongs";
|
||||||
public static final String SONGS_ID = "id";
|
public static final String SONGS_ID = "id";
|
||||||
public static final String SONGS_SERVER_KEY = "serverKey";
|
public static final String SONGS_SERVER_KEY = "serverKey";
|
||||||
public static final String SONGS_SERVER_ID = "serverId";
|
public static final String SONGS_SERVER_ID = "serverId";
|
||||||
public static final String SONGS_COMPLETE_PATH = "completePath";
|
public static final String SONGS_COMPLETE_PATH = "completePath";
|
||||||
public static final String SONGS_LAST_PLAYED = "lastPlayed";
|
public static final String SONGS_LAST_PLAYED = "lastPlayed";
|
||||||
public static final String SONGS_LAST_COMPLETED = "lastCompleted";
|
public static final String SONGS_LAST_COMPLETED = "lastCompleted";
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
private SongDBHandler(Context context) {
|
private SongDBHandler(Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(SQLiteDatabase db) {
|
public void onCreate(SQLiteDatabase db) {
|
||||||
db.execSQL("CREATE TABLE " + TABLE_SONGS + " ( " +
|
db.execSQL("CREATE TABLE " + TABLE_SONGS + " ( " +
|
||||||
SONGS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
SONGS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||||
SONGS_SERVER_KEY + " INTEGER NOT NULL, " +
|
SONGS_SERVER_KEY + " INTEGER NOT NULL, " +
|
||||||
SONGS_SERVER_ID + " TEXT NOT NULL, " +
|
SONGS_SERVER_ID + " TEXT NOT NULL, " +
|
||||||
SONGS_COMPLETE_PATH + " TEXT NOT NULL, " +
|
SONGS_COMPLETE_PATH + " TEXT NOT NULL, " +
|
||||||
SONGS_LAST_PLAYED + " INTEGER, " +
|
SONGS_LAST_PLAYED + " INTEGER, " +
|
||||||
SONGS_LAST_COMPLETED + " INTEGER, " +
|
SONGS_LAST_COMPLETED + " INTEGER, " +
|
||||||
"UNIQUE(" + SONGS_SERVER_KEY + ", " + SONGS_SERVER_ID + "))");
|
"UNIQUE(" + SONGS_SERVER_KEY + ", " + SONGS_SERVER_ID + "))");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_SONGS);
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_SONGS);
|
||||||
this.onCreate(db);
|
this.onCreate(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void addSong(DownloadFile downloadFile) {
|
public synchronized void addSong(DownloadFile downloadFile) {
|
||||||
addSong(Util.getMostRecentActiveServer(context), downloadFile);
|
addSong(Util.getMostRecentActiveServer(context), downloadFile);
|
||||||
}
|
}
|
||||||
public synchronized void addSong(int instance, DownloadFile downloadFile) {
|
public synchronized void addSong(int instance, DownloadFile downloadFile) {
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
addSong(db, instance, downloadFile);
|
addSong(db, instance, downloadFile);
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
protected synchronized void addSong(SQLiteDatabase db, DownloadFile downloadFile) {
|
protected synchronized void addSong(SQLiteDatabase db, DownloadFile downloadFile) {
|
||||||
addSong(db, Util.getMostRecentActiveServer(context), downloadFile);
|
addSong(db, Util.getMostRecentActiveServer(context), downloadFile);
|
||||||
}
|
}
|
||||||
protected synchronized void addSong(SQLiteDatabase db, int instance, DownloadFile downloadFile) {
|
protected synchronized void addSong(SQLiteDatabase db, int instance, DownloadFile downloadFile) {
|
||||||
addSong(db, instance, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath());
|
addSong(db, instance, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void addSong(SQLiteDatabase db, String id, String absolutePath) {
|
protected synchronized void addSong(SQLiteDatabase db, String id, String absolutePath) {
|
||||||
addSong(db, Util.getMostRecentActiveServer(context), id, absolutePath);
|
addSong(db, Util.getMostRecentActiveServer(context), id, absolutePath);
|
||||||
}
|
}
|
||||||
protected synchronized void addSong(SQLiteDatabase db, int instance, String id, String absolutePath) {
|
protected synchronized void addSong(SQLiteDatabase db, int instance, String id, String absolutePath) {
|
||||||
addSongImpl(db, Util.getRestUrlHash(context, instance), id, absolutePath);
|
addSongImpl(db, Util.getRestUrlHash(context, instance), id, absolutePath);
|
||||||
}
|
}
|
||||||
protected synchronized void addSongImpl(SQLiteDatabase db, int serverKey, String id, String absolutePath) {
|
protected synchronized void addSongImpl(SQLiteDatabase db, int serverKey, String id, String absolutePath) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(SONGS_SERVER_KEY, serverKey);
|
values.put(SONGS_SERVER_KEY, serverKey);
|
||||||
values.put(SONGS_SERVER_ID, id);
|
values.put(SONGS_SERVER_ID, id);
|
||||||
values.put(SONGS_COMPLETE_PATH, absolutePath);
|
values.put(SONGS_COMPLETE_PATH, absolutePath);
|
||||||
|
|
||||||
db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_IGNORE);
|
db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_IGNORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void addSongs(int instance, List<MusicDirectory.Entry> entries) {
|
public synchronized void addSongs(int instance, List<MusicDirectory.Entry> entries) {
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
|
|
||||||
List<Pair<String, String>> pairs = new ArrayList<>();
|
List<Pair<String, String>> pairs = new ArrayList<>();
|
||||||
for(MusicDirectory.Entry entry: entries) {
|
for(MusicDirectory.Entry entry: entries) {
|
||||||
pairs.add(new Pair<>(entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath()));
|
pairs.add(new Pair<>(entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath()));
|
||||||
}
|
}
|
||||||
addSongs(db, instance, pairs);
|
addSongs(db, instance, pairs);
|
||||||
|
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
public synchronized void addSongs(SQLiteDatabase db, int instance, List<Pair<String, String>> entries) {
|
public synchronized void addSongs(SQLiteDatabase db, int instance, List<Pair<String, String>> entries) {
|
||||||
addSongsImpl(db, Util.getRestUrlHash(context, instance), entries);
|
addSongsImpl(db, Util.getRestUrlHash(context, instance), entries);
|
||||||
}
|
}
|
||||||
protected synchronized void addSongsImpl(SQLiteDatabase db, int serverKey, List<Pair<String, String>> entries) {
|
protected synchronized void addSongsImpl(SQLiteDatabase db, int serverKey, List<Pair<String, String>> entries) {
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
try {
|
try {
|
||||||
for (Pair<String, String> entry : entries) {
|
for (Pair<String, String> entry : entries) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(SONGS_SERVER_KEY, serverKey);
|
values.put(SONGS_SERVER_KEY, serverKey);
|
||||||
values.put(SONGS_SERVER_ID, entry.getFirst());
|
values.put(SONGS_SERVER_ID, entry.getFirst());
|
||||||
values.put(SONGS_COMPLETE_PATH, entry.getSecond());
|
values.put(SONGS_COMPLETE_PATH, entry.getSecond());
|
||||||
// Util.sleepQuietly(10000);
|
// Util.sleepQuietly(10000);
|
||||||
|
|
||||||
db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_IGNORE);
|
db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_IGNORE);
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
} catch(Exception e) {}
|
} catch(Exception e) {}
|
||||||
|
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setSongPlayed(DownloadFile downloadFile, boolean submission) {
|
public synchronized void setSongPlayed(DownloadFile downloadFile, boolean submission) {
|
||||||
// TODO: In case of offline want to update all matches
|
// TODO: In case of offline want to update all matches
|
||||||
Pair<Integer, String> pair = getOnlineSongId(downloadFile);
|
Pair<Integer, String> pair = getOnlineSongId(downloadFile);
|
||||||
if(pair == null) {
|
if(pair == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int serverKey = pair.getFirst();
|
int serverKey = pair.getFirst();
|
||||||
String id = pair.getSecond();
|
String id = pair.getSecond();
|
||||||
|
|
||||||
// Open and make sure song is in db
|
// Open and make sure song is in db
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
addSongImpl(db, serverKey, id, downloadFile.getSaveFile().getAbsolutePath());
|
addSongImpl(db, serverKey, id, downloadFile.getSaveFile().getAbsolutePath());
|
||||||
|
|
||||||
// Update song's last played
|
// Update song's last played
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(submission ? SONGS_LAST_COMPLETED : SONGS_LAST_PLAYED, System.currentTimeMillis());
|
values.put(submission ? SONGS_LAST_COMPLETED : SONGS_LAST_PLAYED, System.currentTimeMillis());
|
||||||
db.update(TABLE_SONGS, values, SONGS_SERVER_KEY + " = ? AND " + SONGS_SERVER_ID + " = ?", new String[]{Integer.toString(serverKey), id});
|
db.update(TABLE_SONGS, values, SONGS_SERVER_KEY + " = ? AND " + SONGS_SERVER_ID + " = ?", new String[]{Integer.toString(serverKey), id});
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBeenPlayed(MusicDirectory.Entry entry) {
|
public boolean hasBeenPlayed(MusicDirectory.Entry entry) {
|
||||||
Long[] lastPlayed = getLastPlayed(entry);
|
Long[] lastPlayed = getLastPlayed(entry);
|
||||||
return lastPlayed != null && lastPlayed[0] != null && lastPlayed[0] > 0;
|
return lastPlayed != null && lastPlayed[0] != null && lastPlayed[0] > 0;
|
||||||
}
|
}
|
||||||
public boolean hasBeenCompleted(MusicDirectory.Entry entry) {
|
public boolean hasBeenCompleted(MusicDirectory.Entry entry) {
|
||||||
Long[] lastPlayed = getLastPlayed(entry);
|
Long[] lastPlayed = getLastPlayed(entry);
|
||||||
return lastPlayed != null && lastPlayed[1] != null && lastPlayed[1] > 0;
|
return lastPlayed != null && lastPlayed[1] != null && lastPlayed[1] > 0;
|
||||||
}
|
}
|
||||||
public synchronized Long[] getLastPlayed(MusicDirectory.Entry entry) {
|
public synchronized Long[] getLastPlayed(MusicDirectory.Entry entry) {
|
||||||
return getLastPlayed(getOnlineSongId(entry));
|
return getLastPlayed(getOnlineSongId(entry));
|
||||||
}
|
}
|
||||||
protected synchronized Long[] getLastPlayed(Pair<Integer, String> pair) {
|
protected synchronized Long[] getLastPlayed(Pair<Integer, String> pair) {
|
||||||
if(pair == null) {
|
if(pair == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return getLastPlayed(pair.getFirst(), pair.getSecond());
|
return getLastPlayed(pair.getFirst(), pair.getSecond());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public synchronized Long[] getLastPlayed(int serverKey, String id) {
|
public synchronized Long[] getLastPlayed(int serverKey, String id) {
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
|
||||||
String[] columns = {SONGS_LAST_PLAYED, SONGS_LAST_COMPLETED};
|
String[] columns = {SONGS_LAST_PLAYED, SONGS_LAST_COMPLETED};
|
||||||
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_SERVER_ID + " = ?", new String[]{Integer.toString(serverKey), id}, null, null, null, null);
|
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_SERVER_ID + " = ?", new String[]{Integer.toString(serverKey), id}, null, null, null, null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor.moveToFirst();
|
cursor.moveToFirst();
|
||||||
|
|
||||||
Long[] dates = new Long[2];
|
Long[] dates = new Long[2];
|
||||||
dates[0] = cursor.getLong(0);
|
dates[0] = cursor.getLong(0);
|
||||||
dates[1] = cursor.getLong(1);
|
dates[1] = cursor.getLong(1);
|
||||||
return dates;
|
return dates;
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
cursor.close();
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Pair<Integer, String> getOnlineSongId(MusicDirectory.Entry entry) {
|
|
||||||
return getOnlineSongId(Util.getRestUrlHash(context), entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath(), Util.isOffline(context) ? false : true);
|
|
||||||
}
|
|
||||||
public synchronized Pair<Integer, String> getOnlineSongId(DownloadFile downloadFile) {
|
|
||||||
return getOnlineSongId(Util.getRestUrlHash(context), downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), Util.isOffline(context) ? false : true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, MusicDirectory.Entry entry) {
|
|
||||||
return getOnlineSongId(serverKey, new DownloadFile(context, entry, true));
|
|
||||||
}
|
|
||||||
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, DownloadFile downloadFile) {
|
|
||||||
return getOnlineSongId(serverKey, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), true);
|
|
||||||
}
|
|
||||||
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, String id, String savePath, boolean requireServerKey) {
|
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
|
||||||
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
|
||||||
if(cacheLocn != null && id.indexOf(cacheLocn) != -1) {
|
|
||||||
if(requireServerKey) {
|
|
||||||
return getIdFromPath(serverKey, savePath);
|
|
||||||
} else {
|
|
||||||
return getIdFromPath(savePath);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new Pair<>(serverKey, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Pair<Integer, String> getIdFromPath(String path) {
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
|
|
||||||
String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID};
|
|
||||||
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_COMPLETE_PATH + " = ?", new String[] { path }, null, null, SONGS_LAST_PLAYED + " DESC", null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
cursor.moveToFirst();
|
|
||||||
return new Pair(cursor.getInt(0), cursor.getString(1));
|
|
||||||
} catch(Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
cursor.close();
|
cursor.close();
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public synchronized Pair<Integer, String> getIdFromPath(int serverKey, String path) {
|
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
|
||||||
|
|
||||||
String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID};
|
public synchronized Pair<Integer, String> getOnlineSongId(MusicDirectory.Entry entry) {
|
||||||
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_COMPLETE_PATH + " = ?", new String[] {Integer.toString(serverKey), path }, null, null, null, null);
|
return getOnlineSongId(Util.getRestUrlHash(context), entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath(), Util.isOffline(context) ? false : true);
|
||||||
|
}
|
||||||
|
public synchronized Pair<Integer, String> getOnlineSongId(DownloadFile downloadFile) {
|
||||||
|
return getOnlineSongId(Util.getRestUrlHash(context), downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), Util.isOffline(context) ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, MusicDirectory.Entry entry) {
|
||||||
cursor.moveToFirst();
|
return getOnlineSongId(serverKey, new DownloadFile(context, entry, true));
|
||||||
return new Pair(cursor.getInt(0), cursor.getString(1));
|
}
|
||||||
} catch(Exception e) {
|
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, DownloadFile downloadFile) {
|
||||||
return null;
|
return getOnlineSongId(serverKey, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), true);
|
||||||
}
|
}
|
||||||
finally {
|
public synchronized Pair<Integer, String> getOnlineSongId(int serverKey, String id, String savePath, boolean requireServerKey) {
|
||||||
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
|
String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
||||||
|
if(cacheLocn != null && id.indexOf(cacheLocn) != -1) {
|
||||||
|
if(requireServerKey) {
|
||||||
|
return getIdFromPath(serverKey, savePath);
|
||||||
|
} else {
|
||||||
|
return getIdFromPath(savePath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new Pair<>(serverKey, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Pair<Integer, String> getIdFromPath(String path) {
|
||||||
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
|
||||||
|
String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID};
|
||||||
|
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_COMPLETE_PATH + " = ?", new String[] { path }, null, null, SONGS_LAST_PLAYED + " DESC", null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
cursor.moveToFirst();
|
||||||
|
return new Pair(cursor.getInt(0), cursor.getString(1));
|
||||||
|
} catch(Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public synchronized Pair<Integer, String> getIdFromPath(int serverKey, String path) {
|
||||||
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
|
||||||
public static SongDBHandler getHandler(Context context) {
|
String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID};
|
||||||
if(dbHandler == null) {
|
Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_COMPLETE_PATH + " = ?", new String[] {Integer.toString(serverKey), path }, null, null, null, null);
|
||||||
dbHandler = new SongDBHandler(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbHandler;
|
try {
|
||||||
}
|
cursor.moveToFirst();
|
||||||
|
return new Pair(cursor.getInt(0), cursor.getString(1));
|
||||||
|
} catch(Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
cursor.close();
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SongDBHandler getHandler(Context context) {
|
||||||
|
if(dbHandler == null) {
|
||||||
|
dbHandler = new SongDBHandler(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dbHandler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,139 +18,139 @@ import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
|||||||
* Created by Scott on 11/24/13.
|
* Created by Scott on 11/24/13.
|
||||||
*/
|
*/
|
||||||
public final class SyncUtil {
|
public final class SyncUtil {
|
||||||
private static String TAG = SyncUtil.class.getSimpleName();
|
private static String TAG = SyncUtil.class.getSimpleName();
|
||||||
private static ArrayList<SyncSet> syncedPlaylists;
|
private static ArrayList<SyncSet> syncedPlaylists;
|
||||||
private static String url;
|
private static String url;
|
||||||
|
|
||||||
private static void checkRestURL(Context context) {
|
private static void checkRestURL(Context context) {
|
||||||
int instance = Util.getActiveServer(context);
|
int instance = Util.getActiveServer(context);
|
||||||
String newURL = Util.getRestUrl(context, null, instance, false);
|
String newURL = Util.getRestUrl(context, null, instance, false);
|
||||||
if(url == null || !url.equals(newURL)) {
|
if(url == null || !url.equals(newURL)) {
|
||||||
syncedPlaylists = null;
|
syncedPlaylists = null;
|
||||||
url = newURL;
|
url = newURL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Playlist sync
|
// Playlist sync
|
||||||
public static boolean isSyncedPlaylist(Context context, String playlistId) {
|
public static boolean isSyncedPlaylist(Context context, String playlistId) {
|
||||||
checkRestURL(context);
|
checkRestURL(context);
|
||||||
if(syncedPlaylists == null) {
|
if(syncedPlaylists == null) {
|
||||||
syncedPlaylists = getSyncedPlaylists(context);
|
syncedPlaylists = getSyncedPlaylists(context);
|
||||||
}
|
}
|
||||||
return syncedPlaylists.contains(new SyncSet(playlistId));
|
return syncedPlaylists.contains(new SyncSet(playlistId));
|
||||||
}
|
}
|
||||||
public static ArrayList<SyncSet> getSyncedPlaylists(Context context) {
|
public static ArrayList<SyncSet> getSyncedPlaylists(Context context) {
|
||||||
return getSyncedPlaylists(context, Util.getActiveServer(context));
|
return getSyncedPlaylists(context, Util.getActiveServer(context));
|
||||||
}
|
}
|
||||||
public static ArrayList<SyncSet> getSyncedPlaylists(Context context, int instance) {
|
public static ArrayList<SyncSet> getSyncedPlaylists(Context context, int instance) {
|
||||||
String syncFile = getPlaylistSyncFile(context, instance);
|
String syncFile = getPlaylistSyncFile(context, instance);
|
||||||
ArrayList<SyncSet> playlists = FileUtil.deserializeCompressed(context, syncFile, ArrayList.class);
|
ArrayList<SyncSet> playlists = FileUtil.deserializeCompressed(context, syncFile, ArrayList.class);
|
||||||
if(playlists == null) {
|
if(playlists == null) {
|
||||||
playlists = new ArrayList<SyncSet>();
|
playlists = new ArrayList<SyncSet>();
|
||||||
|
|
||||||
// Try to convert old style into new style
|
// Try to convert old style into new style
|
||||||
ArrayList<String> oldPlaylists = FileUtil.deserialize(context, syncFile, ArrayList.class);
|
ArrayList<String> oldPlaylists = FileUtil.deserialize(context, syncFile, ArrayList.class);
|
||||||
// If exists, time to convert!
|
// If exists, time to convert!
|
||||||
if(oldPlaylists != null) {
|
if(oldPlaylists != null) {
|
||||||
for(String id: oldPlaylists) {
|
for(String id: oldPlaylists) {
|
||||||
playlists.add(new SyncSet(id));
|
playlists.add(new SyncSet(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileUtil.serializeCompressed(context, playlists, syncFile);
|
FileUtil.serializeCompressed(context, playlists, syncFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return playlists;
|
return playlists;
|
||||||
}
|
}
|
||||||
public static void setSyncedPlaylists(Context context, int instance, ArrayList<SyncSet> playlists) {
|
public static void setSyncedPlaylists(Context context, int instance, ArrayList<SyncSet> playlists) {
|
||||||
FileUtil.serializeCompressed(context, playlists, getPlaylistSyncFile(context, instance));
|
FileUtil.serializeCompressed(context, playlists, getPlaylistSyncFile(context, instance));
|
||||||
}
|
}
|
||||||
public static void addSyncedPlaylist(Context context, String playlistId) {
|
public static void addSyncedPlaylist(Context context, String playlistId) {
|
||||||
String playlistFile = getPlaylistSyncFile(context);
|
String playlistFile = getPlaylistSyncFile(context);
|
||||||
ArrayList<SyncSet> playlists = getSyncedPlaylists(context);
|
ArrayList<SyncSet> playlists = getSyncedPlaylists(context);
|
||||||
SyncSet set = new SyncSet(playlistId);
|
SyncSet set = new SyncSet(playlistId);
|
||||||
if(!playlists.contains(set)) {
|
if(!playlists.contains(set)) {
|
||||||
playlists.add(set);
|
playlists.add(set);
|
||||||
}
|
}
|
||||||
FileUtil.serializeCompressed(context, playlists, playlistFile);
|
FileUtil.serializeCompressed(context, playlists, playlistFile);
|
||||||
syncedPlaylists = playlists;
|
syncedPlaylists = playlists;
|
||||||
}
|
}
|
||||||
public static void removeSyncedPlaylist(Context context, String playlistId) {
|
public static void removeSyncedPlaylist(Context context, String playlistId) {
|
||||||
int instance = Util.getActiveServer(context);
|
int instance = Util.getActiveServer(context);
|
||||||
removeSyncedPlaylist(context, playlistId, instance);
|
removeSyncedPlaylist(context, playlistId, instance);
|
||||||
}
|
}
|
||||||
public static void removeSyncedPlaylist(Context context, String playlistId, int instance) {
|
public static void removeSyncedPlaylist(Context context, String playlistId, int instance) {
|
||||||
String playlistFile = getPlaylistSyncFile(context, instance);
|
String playlistFile = getPlaylistSyncFile(context, instance);
|
||||||
ArrayList<SyncSet> playlists = getSyncedPlaylists(context, instance);
|
ArrayList<SyncSet> playlists = getSyncedPlaylists(context, instance);
|
||||||
SyncSet set = new SyncSet(playlistId);
|
SyncSet set = new SyncSet(playlistId);
|
||||||
if(playlists.contains(set)) {
|
if(playlists.contains(set)) {
|
||||||
playlists.remove(set);
|
playlists.remove(set);
|
||||||
FileUtil.serializeCompressed(context, playlists, playlistFile);
|
FileUtil.serializeCompressed(context, playlists, playlistFile);
|
||||||
syncedPlaylists = playlists;
|
syncedPlaylists = playlists;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static String getPlaylistSyncFile(Context context) {
|
public static String getPlaylistSyncFile(Context context) {
|
||||||
int instance = Util.getActiveServer(context);
|
int instance = Util.getActiveServer(context);
|
||||||
return getPlaylistSyncFile(context, instance);
|
return getPlaylistSyncFile(context, instance);
|
||||||
}
|
}
|
||||||
public static String getPlaylistSyncFile(Context context, int instance) {
|
public static String getPlaylistSyncFile(Context context, int instance) {
|
||||||
return "sync-playlist-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser";
|
return "sync-playlist-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most Recently Added
|
// Most Recently Added
|
||||||
public static ArrayList<String> getSyncedMostRecent(Context context, int instance) {
|
public static ArrayList<String> getSyncedMostRecent(Context context, int instance) {
|
||||||
ArrayList<String> list = FileUtil.deserialize(context, getMostRecentSyncFile(context, instance), ArrayList.class);
|
ArrayList<String> list = FileUtil.deserialize(context, getMostRecentSyncFile(context, instance), ArrayList.class);
|
||||||
if(list == null) {
|
if(list == null) {
|
||||||
list = new ArrayList<String>();
|
list = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
public static void removeMostRecentSyncFiles(Context context) {
|
public static void removeMostRecentSyncFiles(Context context) {
|
||||||
int total = Util.getServerCount(context);
|
int total = Util.getServerCount(context);
|
||||||
for(int i = 0; i < total; i++) {
|
for(int i = 0; i < total; i++) {
|
||||||
File file = new File(context.getCacheDir(), getMostRecentSyncFile(context, i));
|
File file = new File(context.getCacheDir(), getMostRecentSyncFile(context, i));
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static String getMostRecentSyncFile(Context context, int instance) {
|
public static String getMostRecentSyncFile(Context context, int instance) {
|
||||||
return "sync-most_recent-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser";
|
return "sync-most_recent-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String joinNames(List<String> names) {
|
public static String joinNames(List<String> names) {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (String val : names) {
|
for (String val : names) {
|
||||||
builder.append(val).append(", ");
|
builder.append(val).append(", ");
|
||||||
}
|
}
|
||||||
builder.setLength(builder.length() - 2);
|
builder.setLength(builder.length() - 2);
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SyncSet implements Serializable {
|
public static class SyncSet implements Serializable {
|
||||||
public String id;
|
public String id;
|
||||||
public List<String> synced;
|
public List<String> synced;
|
||||||
|
|
||||||
protected SyncSet() {
|
protected SyncSet() {
|
||||||
|
|
||||||
}
|
}
|
||||||
public SyncSet(String id) {
|
public SyncSet(String id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
public SyncSet(String id, List<String> synced) {
|
public SyncSet(String id, List<String> synced) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.synced = synced;
|
this.synced = synced;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if(obj instanceof SyncSet) {
|
if(obj instanceof SyncSet) {
|
||||||
return this.id.equals(((SyncSet)obj).id);
|
return this.id.equals(((SyncSet)obj).id);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return id.hashCode();
|
return id.hashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,22 @@ public abstract class TabBackgroundTask<T> extends BackgroundTask<T> {
|
|||||||
public void execute() {
|
public void execute() {
|
||||||
tabFragment.setProgressVisible(true);
|
tabFragment.setProgressVisible(true);
|
||||||
|
|
||||||
queue.offer(task = new Task() {
|
queue.offer(task = new Task() {
|
||||||
@Override
|
@Override
|
||||||
public void onDone(T result) {
|
public void onDone(T result) {
|
||||||
tabFragment.setProgressVisible(false);
|
tabFragment.setProgressVisible(false);
|
||||||
done(result);
|
done(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Throwable t) {
|
public void onError(Throwable t) {
|
||||||
tabFragment.setProgressVisible(false);
|
tabFragment.setProgressVisible(false);
|
||||||
error(t);
|
error(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return !tabFragment.isAdded() || cancelled.get();
|
return !tabFragment.isAdded() || cancelled.get();
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2016 (C) Scott Jackson
|
Copyright 2016 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -26,73 +26,73 @@ import net.nullsum.audinaut.activity.SettingsActivity;
|
|||||||
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
|
||||||
|
|
||||||
public final class ThemeUtil {
|
public final class ThemeUtil {
|
||||||
public static final String THEME_DARK = "dark";
|
public static final String THEME_DARK = "dark";
|
||||||
public static final String THEME_BLACK = "black";
|
public static final String THEME_BLACK = "black";
|
||||||
public static final String THEME_LIGHT = "light";
|
public static final String THEME_LIGHT = "light";
|
||||||
public static final String THEME_DAY_NIGHT = "day/night";
|
public static final String THEME_DAY_NIGHT = "day/night";
|
||||||
public static final String THEME_DAY_BLACK_NIGHT = "day/black";
|
public static final String THEME_DAY_BLACK_NIGHT = "day/black";
|
||||||
|
|
||||||
public static String getTheme(Context context) {
|
public static String getTheme(Context context) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
String theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
|
String theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
|
||||||
|
|
||||||
if(THEME_DAY_NIGHT.equals(theme)) {
|
if(THEME_DAY_NIGHT.equals(theme)) {
|
||||||
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||||
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
|
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
|
||||||
theme = THEME_DARK;
|
theme = THEME_DARK;
|
||||||
} else {
|
} else {
|
||||||
theme = THEME_LIGHT;
|
theme = THEME_LIGHT;
|
||||||
}
|
}
|
||||||
} else if(THEME_DAY_BLACK_NIGHT.equals(theme)) {
|
} else if(THEME_DAY_BLACK_NIGHT.equals(theme)) {
|
||||||
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||||
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
|
if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
|
||||||
theme = THEME_BLACK;
|
theme = THEME_BLACK;
|
||||||
} else {
|
} else {
|
||||||
theme = THEME_LIGHT;
|
theme = THEME_LIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
public static int getThemeRes(Context context) {
|
public static int getThemeRes(Context context) {
|
||||||
return getThemeRes(context, getTheme(context));
|
return getThemeRes(context, getTheme(context));
|
||||||
}
|
}
|
||||||
public static int getThemeRes(Context context, String theme) {
|
public static int getThemeRes(Context context, String theme) {
|
||||||
if(context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) {
|
if(context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) {
|
||||||
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) {
|
||||||
if (THEME_DARK.equals(theme)) {
|
if (THEME_DARK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Dark_No_Actionbar;
|
return R.style.Theme_Audinaut_Dark_No_Actionbar;
|
||||||
} else if (THEME_BLACK.equals(theme)) {
|
} else if (THEME_BLACK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Black_No_Actionbar;
|
return R.style.Theme_Audinaut_Black_No_Actionbar;
|
||||||
} else {
|
} else {
|
||||||
return R.style.Theme_Audinaut_Light_No_Actionbar;
|
return R.style.Theme_Audinaut_Light_No_Actionbar;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (THEME_DARK.equals(theme)) {
|
if (THEME_DARK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Dark_No_Color;
|
return R.style.Theme_Audinaut_Dark_No_Color;
|
||||||
} else if (THEME_BLACK.equals(theme)) {
|
} else if (THEME_BLACK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Black_No_Color;
|
return R.style.Theme_Audinaut_Black_No_Color;
|
||||||
} else {
|
} else {
|
||||||
return R.style.Theme_Audinaut_Light_No_Color;
|
return R.style.Theme_Audinaut_Light_No_Color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (THEME_DARK.equals(theme)) {
|
if (THEME_DARK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Dark;
|
return R.style.Theme_Audinaut_Dark;
|
||||||
} else if (THEME_BLACK.equals(theme)) {
|
} else if (THEME_BLACK.equals(theme)) {
|
||||||
return R.style.Theme_Audinaut_Black;
|
return R.style.Theme_Audinaut_Black;
|
||||||
} else {
|
} else {
|
||||||
return R.style.Theme_Audinaut_Light;
|
return R.style.Theme_Audinaut_Light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void setTheme(Context context, String theme) {
|
public static void setTheme(Context context, String theme) {
|
||||||
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
SharedPreferences.Editor editor = Util.getPreferences(context).edit();
|
||||||
editor.putString(Constants.PREFERENCES_KEY_THEME, theme);
|
editor.putString(Constants.PREFERENCES_KEY_THEME, theme);
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void applyTheme(Context context, String theme) {
|
public static void applyTheme(Context context, String theme) {
|
||||||
context.setTheme(getThemeRes(context, theme));
|
context.setTheme(getThemeRes(context, theme));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
|
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Copyright 2015 (C) Scott Jackson
|
Copyright 2015 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -43,50 +43,50 @@ import net.nullsum.audinaut.service.OfflineException;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public final class UpdateHelper {
|
public final class UpdateHelper {
|
||||||
private static final String TAG = UpdateHelper.class.getSimpleName();
|
private static final String TAG = UpdateHelper.class.getSimpleName();
|
||||||
|
|
||||||
public static abstract class EntryInstanceUpdater {
|
public static abstract class EntryInstanceUpdater {
|
||||||
private Entry entry;
|
private Entry entry;
|
||||||
protected int metadataUpdate = DownloadService.METADATA_UPDATED_ALL;
|
protected int metadataUpdate = DownloadService.METADATA_UPDATED_ALL;
|
||||||
|
|
||||||
public EntryInstanceUpdater(Entry entry) {
|
public EntryInstanceUpdater(Entry entry) {
|
||||||
this.entry = entry;
|
this.entry = entry;
|
||||||
}
|
}
|
||||||
public EntryInstanceUpdater(Entry entry, int metadataUpdate) {
|
public EntryInstanceUpdater(Entry entry, int metadataUpdate) {
|
||||||
this.entry = entry;
|
this.entry = entry;
|
||||||
this.metadataUpdate = metadataUpdate;
|
this.metadataUpdate = metadataUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void update(Entry found);
|
public abstract void update(Entry found);
|
||||||
|
|
||||||
public void execute() {
|
public void execute() {
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
if(downloadService != null && !entry.isDirectory()) {
|
if(downloadService != null && !entry.isDirectory()) {
|
||||||
boolean serializeChanges = false;
|
boolean serializeChanges = false;
|
||||||
List<DownloadFile> downloadFiles = downloadService.getDownloads();
|
List<DownloadFile> downloadFiles = downloadService.getDownloads();
|
||||||
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
|
||||||
|
|
||||||
for(DownloadFile file: downloadFiles) {
|
for(DownloadFile file: downloadFiles) {
|
||||||
Entry check = file.getSong();
|
Entry check = file.getSong();
|
||||||
if(entry.getId().equals(check.getId())) {
|
if(entry.getId().equals(check.getId())) {
|
||||||
update(check);
|
update(check);
|
||||||
serializeChanges = true;
|
serializeChanges = true;
|
||||||
|
|
||||||
if(currentPlaying != null && currentPlaying.getSong() != null && currentPlaying.getSong().getId().equals(entry.getId())) {
|
if(currentPlaying != null && currentPlaying.getSong() != null && currentPlaying.getSong().getId().equals(entry.getId())) {
|
||||||
downloadService.onMetadataUpdate(metadataUpdate);
|
downloadService.onMetadataUpdate(metadataUpdate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(serializeChanges) {
|
if(serializeChanges) {
|
||||||
downloadService.serializeQueue();
|
downloadService.serializeQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry find = UpdateView.findEntry(entry);
|
Entry find = UpdateView.findEntry(entry);
|
||||||
if(find != null) {
|
if(find != null) {
|
||||||
update(find);
|
update(find);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Subsonic.
|
This file is part of Subsonic.
|
||||||
Subsonic is free software: you can redistribute it and/or modify
|
Subsonic is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
Subsonic is distributed in the hope that it will be useful,
|
Subsonic is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
Copyright 2014 (C) Scott Jackson
|
Copyright 2014 (C) Scott Jackson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.nullsum.audinaut.util;
|
package net.nullsum.audinaut.util;
|
||||||
@ -43,80 +43,80 @@ import net.nullsum.audinaut.adapter.SettingsAdapter;
|
|||||||
import net.nullsum.audinaut.view.UpdateView;
|
import net.nullsum.audinaut.view.UpdateView;
|
||||||
|
|
||||||
public final class UserUtil {
|
public final class UserUtil {
|
||||||
private static final String TAG = UserUtil.class.getSimpleName();
|
private static final String TAG = UserUtil.class.getSimpleName();
|
||||||
private static final long MIN_VERIFY_DURATION = 1000L * 60L * 60L;
|
private static final long MIN_VERIFY_DURATION = 1000L * 60L * 60L;
|
||||||
|
|
||||||
private static int instance = -1;
|
private static int instance = -1;
|
||||||
private static int instanceHash = -1;
|
private static int instanceHash = -1;
|
||||||
private static User currentUser;
|
private static User currentUser;
|
||||||
private static long lastVerifiedTime = 0;
|
private static long lastVerifiedTime = 0;
|
||||||
|
|
||||||
public static void refreshCurrentUser(Context context, boolean forceRefresh) {
|
public static void refreshCurrentUser(Context context, boolean forceRefresh) {
|
||||||
refreshCurrentUser(context, forceRefresh, false);
|
refreshCurrentUser(context, forceRefresh, false);
|
||||||
}
|
}
|
||||||
public static void refreshCurrentUser(Context context, boolean forceRefresh, boolean unAuth) {
|
public static void refreshCurrentUser(Context context, boolean forceRefresh, boolean unAuth) {
|
||||||
currentUser = null;
|
currentUser = null;
|
||||||
if(unAuth) {
|
if(unAuth) {
|
||||||
lastVerifiedTime = 0;
|
lastVerifiedTime = 0;
|
||||||
}
|
}
|
||||||
seedCurrentUser(context, forceRefresh);
|
seedCurrentUser(context, forceRefresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void seedCurrentUser(Context context) {
|
public static void seedCurrentUser(Context context) {
|
||||||
seedCurrentUser(context, false);
|
seedCurrentUser(context, false);
|
||||||
}
|
}
|
||||||
public static void seedCurrentUser(final Context context, final boolean refresh) {
|
public static void seedCurrentUser(final Context context, final boolean refresh) {
|
||||||
// Only try to seed if online
|
// Only try to seed if online
|
||||||
if(Util.isOffline(context)) {
|
if(Util.isOffline(context)) {
|
||||||
currentUser = null;
|
currentUser = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int instance = Util.getActiveServer(context);
|
final int instance = Util.getActiveServer(context);
|
||||||
final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context, null).hashCode();
|
final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context, null).hashCode();
|
||||||
if(UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) {
|
if(UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
UserUtil.instance = instance;
|
UserUtil.instance = instance;
|
||||||
UserUtil.instanceHash = instanceHash;
|
UserUtil.instanceHash = instanceHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
new SilentBackgroundTask<Void>(context) {
|
new SilentBackgroundTask<Void>(context) {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() throws Throwable {
|
protected Void doInBackground() throws Throwable {
|
||||||
currentUser = MusicServiceFactory.getMusicService(context).getUser(refresh, getCurrentUsername(context, instance), context, null);
|
currentUser = MusicServiceFactory.getMusicService(context).getUser(refresh, getCurrentUsername(context, instance), context, null);
|
||||||
|
|
||||||
// If running, redo cast selector
|
// If running, redo cast selector
|
||||||
DownloadService downloadService = DownloadService.getInstance();
|
DownloadService downloadService = DownloadService.getInstance();
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void done(Void result) {
|
protected void done(Void result) {
|
||||||
if(context instanceof AppCompatActivity) {
|
if(context instanceof AppCompatActivity) {
|
||||||
((AppCompatActivity) context).supportInvalidateOptionsMenu();
|
((AppCompatActivity) context).supportInvalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void error(Throwable error) {
|
protected void error(Throwable error) {
|
||||||
// Don't do anything, supposed to be background pull
|
// Don't do anything, supposed to be background pull
|
||||||
Log.e(TAG, "Failed to seed user information");
|
Log.e(TAG, "Failed to seed user information");
|
||||||
}
|
}
|
||||||
}.execute();
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User getCurrentUser() {
|
public static User getCurrentUser() {
|
||||||
return currentUser;
|
return currentUser;
|
||||||
}
|
}
|
||||||
public static String getCurrentUsername(Context context, int instance) {
|
public static String getCurrentUsername(Context context, int instance) {
|
||||||
SharedPreferences prefs = Util.getPreferences(context);
|
SharedPreferences prefs = Util.getPreferences(context);
|
||||||
return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
|
return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getCurrentUsername(Context context) {
|
public static String getCurrentUsername(Context context) {
|
||||||
return getCurrentUsername(context, Util.getActiveServer(context));
|
return getCurrentUsername(context, Util.getActiveServer(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user