2016-12-18 18:41:30 +01:00
|
|
|
/*
|
|
|
|
This file is part of Subsonic.
|
|
|
|
|
|
|
|
Subsonic is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Subsonic is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Copyright 2009 (C) Sindre Mehus
|
|
|
|
*/
|
2017-01-09 08:01:12 +01:00
|
|
|
package net.nullsum.audinaut.activity;
|
2016-12-18 18:41:30 +01:00
|
|
|
|
|
|
|
import android.accounts.Account;
|
|
|
|
import android.accounts.AccountManager;
|
|
|
|
import android.app.Dialog;
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.content.res.TypedArray;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Handler;
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
import android.support.v4.app.FragmentManager;
|
|
|
|
import android.support.v4.app.FragmentTransaction;
|
|
|
|
import android.support.v7.app.AlertDialog;
|
|
|
|
import android.support.v7.widget.Toolbar;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.widget.CheckBox;
|
|
|
|
import android.widget.ImageButton;
|
|
|
|
import android.widget.ImageView;
|
|
|
|
import android.widget.TextView;
|
|
|
|
|
2017-03-05 07:30:37 +01:00
|
|
|
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
|
2016-12-18 18:41:30 +01:00
|
|
|
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
import java.util.Date;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
2017-01-09 08:01:12 +01:00
|
|
|
import net.nullsum.audinaut.R;
|
|
|
|
import net.nullsum.audinaut.domain.MusicDirectory;
|
|
|
|
import net.nullsum.audinaut.domain.PlayerQueue;
|
|
|
|
import net.nullsum.audinaut.domain.PlayerState;
|
|
|
|
import net.nullsum.audinaut.fragments.DownloadFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.NowPlayingFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.SearchFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.SelectArtistFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.SelectDirectoryFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.SelectPlaylistFragment;
|
|
|
|
import net.nullsum.audinaut.fragments.SubsonicFragment;
|
|
|
|
import net.nullsum.audinaut.service.DownloadFile;
|
|
|
|
import net.nullsum.audinaut.service.DownloadService;
|
|
|
|
import net.nullsum.audinaut.service.MusicService;
|
|
|
|
import net.nullsum.audinaut.service.MusicServiceFactory;
|
|
|
|
import net.nullsum.audinaut.updates.Updater;
|
|
|
|
import net.nullsum.audinaut.util.Constants;
|
|
|
|
import net.nullsum.audinaut.util.FileUtil;
|
|
|
|
import net.nullsum.audinaut.util.SilentBackgroundTask;
|
|
|
|
import net.nullsum.audinaut.util.UserUtil;
|
|
|
|
import net.nullsum.audinaut.util.Util;
|
2016-12-18 18:41:30 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by Scott on 10/14/13.
|
|
|
|
*/
|
|
|
|
public class SubsonicFragmentActivity extends SubsonicActivity implements DownloadService.OnSongChangedListener {
|
|
|
|
private static String TAG = SubsonicFragmentActivity.class.getSimpleName();
|
|
|
|
private static boolean infoDialogDisplayed;
|
|
|
|
private static boolean sessionInitialized = false;
|
|
|
|
private static long ALLOWED_SKEW = 30000L;
|
|
|
|
|
|
|
|
private SlidingUpPanelLayout slideUpPanel;
|
|
|
|
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
|
|
|
|
private boolean isPanelClosing = false;
|
|
|
|
private NowPlayingFragment nowPlayingFragment;
|
|
|
|
private SubsonicFragment secondaryFragment;
|
|
|
|
private Toolbar mainToolbar;
|
|
|
|
private Toolbar nowPlayingToolbar;
|
|
|
|
|
|
|
|
private View bottomBar;
|
|
|
|
private ImageView coverArtView;
|
|
|
|
private TextView trackView;
|
|
|
|
private TextView artistView;
|
|
|
|
private ImageButton startButton;
|
|
|
|
private long lastBackPressTime = 0;
|
|
|
|
private DownloadFile currentPlaying;
|
|
|
|
private PlayerState currentState;
|
|
|
|
private ImageButton previousButton;
|
|
|
|
private ImageButton nextButton;
|
|
|
|
private ImageButton rewindButton;
|
|
|
|
private ImageButton fastforwardButton;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
if(savedInstanceState == null) {
|
|
|
|
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
|
|
|
boolean firstRun = false;
|
|
|
|
if (fragmentType == null) {
|
|
|
|
fragmentType = Util.openToTab(this);
|
|
|
|
if (fragmentType != null) {
|
|
|
|
firstRun = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ("".equals(fragmentType) || fragmentType == null || firstRun) {
|
|
|
|
// Initial startup stuff
|
|
|
|
if (!sessionInitialized) {
|
|
|
|
loadSession();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_EXIT)) {
|
|
|
|
stopService(new Intent(this, DownloadService.class));
|
|
|
|
finish();
|
|
|
|
getImageLoader().clearCache();
|
|
|
|
} else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) {
|
|
|
|
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Download");
|
|
|
|
lastSelectedPosition = R.id.drawer_downloading;
|
|
|
|
}
|
|
|
|
setContentView(R.layout.abstract_fragment_activity);
|
|
|
|
|
|
|
|
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
|
|
|
|
String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE);
|
|
|
|
if(fragmentType == null) {
|
|
|
|
fragmentType = Util.openToTab(this);
|
|
|
|
if(fragmentType != null) {
|
|
|
|
getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType);
|
|
|
|
lastSelectedPosition = getDrawerItemId(fragmentType);
|
|
|
|
} else {
|
|
|
|
lastSelectedPosition = R.id.drawer_library;
|
|
|
|
}
|
|
|
|
|
|
|
|
MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition);
|
|
|
|
if(item != null) {
|
|
|
|
item.setChecked(true);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lastSelectedPosition = getDrawerItemId(fragmentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
currentFragment = getNewFragment(fragmentType);
|
|
|
|
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ID)) {
|
|
|
|
Bundle currentArguments = currentFragment.getArguments();
|
|
|
|
if(currentArguments == null) {
|
|
|
|
currentArguments = new Bundle();
|
|
|
|
}
|
|
|
|
currentArguments.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
|
|
|
currentFragment.setArguments(currentArguments);
|
|
|
|
}
|
|
|
|
currentFragment.setPrimaryFragment(true);
|
|
|
|
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit();
|
|
|
|
|
|
|
|
if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
|
|
|
SearchFragment fragment = new SearchFragment();
|
|
|
|
replaceFragment(fragment, fragment.getSupportTag());
|
|
|
|
}
|
|
|
|
|
|
|
|
// If a album type is set, switch to that album type view
|
|
|
|
String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE);
|
|
|
|
if(albumType != null) {
|
|
|
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
|
|
|
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
args.putString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE, albumType);
|
|
|
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 20);
|
|
|
|
args.putInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET, 0);
|
|
|
|
|
|
|
|
fragment.setArguments(args);
|
|
|
|
replaceFragment(fragment, fragment.getSupportTag());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
slideUpPanel = (SlidingUpPanelLayout) findViewById(R.id.slide_up_panel);
|
|
|
|
panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() {
|
|
|
|
@Override
|
|
|
|
public void onPanelSlide(View panel, float slideOffset) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-03-05 07:30:37 +01:00
|
|
|
@Override
|
|
|
|
public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) {
|
|
|
|
if (newState == PanelState.COLLAPSED) {
|
|
|
|
isPanelClosing = false;
|
|
|
|
if(bottomBar.getVisibility() == View.GONE) {
|
|
|
|
bottomBar.setVisibility(View.VISIBLE);
|
|
|
|
nowPlayingToolbar.setVisibility(View.GONE);
|
|
|
|
nowPlayingFragment.setPrimaryFragment(false);
|
|
|
|
setSupportActionBar(mainToolbar);
|
|
|
|
recreateSpinner();
|
|
|
|
}
|
|
|
|
} else if (newState == PanelState.EXPANDED) {
|
|
|
|
isPanelClosing = false;
|
|
|
|
currentFragment.stopActionMode();
|
|
|
|
|
|
|
|
// Disable custom view before switching
|
|
|
|
getSupportActionBar().setDisplayShowCustomEnabled(false);
|
|
|
|
getSupportActionBar().setDisplayShowTitleEnabled(true);
|
|
|
|
|
|
|
|
bottomBar.setVisibility(View.GONE);
|
|
|
|
nowPlayingToolbar.setVisibility(View.VISIBLE);
|
|
|
|
setSupportActionBar(nowPlayingToolbar);
|
|
|
|
|
|
|
|
if(secondaryFragment == null) {
|
|
|
|
nowPlayingFragment.setPrimaryFragment(true);
|
|
|
|
} else {
|
|
|
|
secondaryFragment.setPrimaryFragment(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
drawerToggle.setDrawerIndicatorEnabled(false);
|
|
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
2016-12-18 18:41:30 +01:00
|
|
|
};
|
2017-03-05 07:30:37 +01:00
|
|
|
slideUpPanel.addPanelSlideListener(panelSlideListener);
|
2016-12-18 18:41:30 +01:00
|
|
|
|
|
|
|
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) {
|
|
|
|
// Post this later so it actually runs
|
|
|
|
handler.postDelayed(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
openNowPlaying();
|
|
|
|
}
|
|
|
|
}, 200);
|
|
|
|
|
|
|
|
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD);
|
|
|
|
}
|
|
|
|
|
|
|
|
bottomBar = findViewById(R.id.bottom_bar);
|
|
|
|
mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
|
|
|
|
nowPlayingToolbar = (Toolbar) findViewById(R.id.now_playing_toolbar);
|
|
|
|
coverArtView = (ImageView) bottomBar.findViewById(R.id.album_art);
|
|
|
|
trackView = (TextView) bottomBar.findViewById(R.id.track_name);
|
|
|
|
artistView = (TextView) bottomBar.findViewById(R.id.artist_name);
|
|
|
|
|
|
|
|
setSupportActionBar(mainToolbar);
|
|
|
|
|
|
|
|
if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) {
|
|
|
|
nowPlayingFragment = new NowPlayingFragment();
|
|
|
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
|
|
trans.add(R.id.now_playing_fragment_container, nowPlayingFragment, nowPlayingFragment.getTag() + "");
|
|
|
|
trans.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
rewindButton = (ImageButton) findViewById(R.id.download_rewind);
|
|
|
|
rewindButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
if (getDownloadService() == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDownloadService().rewind();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
previousButton = (ImageButton) findViewById(R.id.download_previous);
|
|
|
|
previousButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
if(getDownloadService() == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDownloadService().previous();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
startButton = (ImageButton) findViewById(R.id.download_start);
|
|
|
|
startButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
PlayerState state = getDownloadService().getPlayerState();
|
|
|
|
if(state == PlayerState.STARTED) {
|
|
|
|
getDownloadService().pause();
|
|
|
|
} else {
|
|
|
|
getDownloadService().start();
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
nextButton = (ImageButton) findViewById(R.id.download_next);
|
|
|
|
nextButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
if(getDownloadService() == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDownloadService().next();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
fastforwardButton = (ImageButton) findViewById(R.id.download_fastforward);
|
|
|
|
fastforwardButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
@Override
|
|
|
|
public void onClick(View v) {
|
|
|
|
new SilentBackgroundTask<Void>(SubsonicFragmentActivity.this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
if (getDownloadService() == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDownloadService().fastForward();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostCreate(Bundle bundle) {
|
|
|
|
super.onPostCreate(bundle);
|
|
|
|
|
|
|
|
showInfoDialog();
|
|
|
|
checkUpdates();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onNewIntent(Intent intent) {
|
|
|
|
super.onNewIntent(intent);
|
|
|
|
|
|
|
|
if(currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
closeNowPlaying();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(currentFragment instanceof SearchFragment) {
|
|
|
|
String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
|
|
|
boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false);
|
|
|
|
|
|
|
|
if (query != null) {
|
|
|
|
((SearchFragment)currentFragment).search(query, autoplay);
|
|
|
|
}
|
|
|
|
getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_QUERY);
|
|
|
|
} else {
|
|
|
|
setIntent(intent);
|
|
|
|
|
|
|
|
SearchFragment fragment = new SearchFragment();
|
|
|
|
replaceFragment(fragment, fragment.getSupportTag());
|
|
|
|
}
|
|
|
|
} else if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, false)) {
|
|
|
|
if(slideUpPanel.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
openNowPlaying();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
closeNowPlaying();
|
|
|
|
}
|
|
|
|
setIntent(intent);
|
|
|
|
}
|
|
|
|
if(drawer != null) {
|
|
|
|
drawer.closeDrawers();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onResume() {
|
|
|
|
super.onResume();
|
|
|
|
|
|
|
|
if(getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) {
|
|
|
|
SubsonicFragment fragment = new SelectDirectoryFragment();
|
|
|
|
Bundle args = new Bundle();
|
|
|
|
args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID));
|
|
|
|
args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME));
|
|
|
|
args.putString(Constants.INTENT_EXTRA_SEARCH_SONG, getIntent().getStringExtra(Constants.INTENT_EXTRA_SEARCH_SONG));
|
|
|
|
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ARTIST)) {
|
|
|
|
args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true);
|
|
|
|
}
|
|
|
|
if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)) {
|
|
|
|
args.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID));
|
|
|
|
}
|
|
|
|
fragment.setArguments(args);
|
|
|
|
|
|
|
|
replaceFragment(fragment, fragment.getSupportTag());
|
|
|
|
getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM);
|
|
|
|
}
|
|
|
|
|
|
|
|
UserUtil.seedCurrentUser(this);
|
|
|
|
createAccount();
|
|
|
|
runWhenServiceAvailable(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this, true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
DownloadService downloadService = getDownloadService();
|
|
|
|
if(downloadService != null) {
|
|
|
|
downloadService.removeOnSongChangeListener(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
|
|
|
super.onSaveInstanceState(savedInstanceState);
|
|
|
|
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag());
|
|
|
|
if(secondaryFragment != null) {
|
|
|
|
savedInstanceState.putString(Constants.MAIN_NOW_PLAYING_SECONDARY, secondaryFragment.getTag());
|
|
|
|
}
|
|
|
|
savedInstanceState.putInt(Constants.MAIN_SLIDE_PANEL_STATE, slideUpPanel.getPanelState().hashCode());
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
|
|
|
super.onRestoreInstanceState(savedInstanceState);
|
|
|
|
|
|
|
|
String id = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING);
|
|
|
|
FragmentManager fm = getSupportFragmentManager();
|
|
|
|
nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id);
|
|
|
|
|
|
|
|
String secondaryId = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING_SECONDARY);
|
|
|
|
if(secondaryId != null) {
|
|
|
|
secondaryFragment = (SubsonicFragment) fm.findFragmentByTag(secondaryId);
|
|
|
|
|
|
|
|
nowPlayingFragment.setPrimaryFragment(false);
|
|
|
|
secondaryFragment.setPrimaryFragment(true);
|
|
|
|
|
|
|
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
|
|
trans.hide(nowPlayingFragment);
|
|
|
|
trans.commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(drawerToggle != null && backStack.size() > 0) {
|
|
|
|
drawerToggle.setDrawerIndicatorEnabled(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) {
|
2017-03-05 07:30:37 +01:00
|
|
|
panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED);
|
2016-12-18 18:41:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setContentView(int viewId) {
|
|
|
|
super.setContentView(viewId);
|
|
|
|
if(drawerToggle != null){
|
|
|
|
drawerToggle.setDrawerIndicatorEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment == null) {
|
|
|
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
|
|
|
} else if(onBackPressedSupport()) {
|
|
|
|
finish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onBackPressedSupport() {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
removeCurrent();
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return super.onBackPressedSupport();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public SubsonicFragment getCurrentFragment() {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
if(secondaryFragment == null) {
|
|
|
|
return nowPlayingFragment;
|
|
|
|
} else {
|
|
|
|
return secondaryFragment;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return super.getCurrentFragment();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) {
|
|
|
|
if(slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) {
|
|
|
|
secondaryFragment = fragment;
|
|
|
|
nowPlayingFragment.setPrimaryFragment(false);
|
|
|
|
secondaryFragment.setPrimaryFragment(true);
|
|
|
|
supportInvalidateOptionsMenu();
|
|
|
|
|
|
|
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
|
|
trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
|
|
|
|
trans.hide(nowPlayingFragment);
|
|
|
|
trans.add(R.id.now_playing_fragment_container, secondaryFragment, tag + "");
|
|
|
|
trans.commit();
|
|
|
|
} else {
|
|
|
|
super.replaceFragment(fragment, tag, replaceCurrent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
public void removeCurrent() {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment != null) {
|
|
|
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
|
|
trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
|
|
|
|
trans.remove(secondaryFragment);
|
|
|
|
trans.show(nowPlayingFragment);
|
|
|
|
trans.commit();
|
|
|
|
|
|
|
|
secondaryFragment = null;
|
|
|
|
nowPlayingFragment.setPrimaryFragment(true);
|
|
|
|
supportInvalidateOptionsMenu();
|
|
|
|
} else {
|
|
|
|
super.removeCurrent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setTitle(CharSequence title) {
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
getSupportActionBar().setTitle(title);
|
|
|
|
} else {
|
|
|
|
super.setTitle(title);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void drawerItemSelected(String fragmentType) {
|
|
|
|
super.drawerItemSelected(fragmentType);
|
|
|
|
|
|
|
|
if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) {
|
|
|
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void startFragmentActivity(String fragmentType) {
|
|
|
|
// Create a transaction that does all of this
|
|
|
|
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
|
|
|
|
|
|
|
|
// Clear existing stack
|
|
|
|
for(int i = backStack.size() - 1; i >= 0; i--) {
|
|
|
|
trans.remove(backStack.get(i));
|
|
|
|
}
|
|
|
|
trans.remove(currentFragment);
|
|
|
|
backStack.clear();
|
|
|
|
|
|
|
|
// Create new stack
|
|
|
|
currentFragment = getNewFragment(fragmentType);
|
|
|
|
currentFragment.setPrimaryFragment(true);
|
|
|
|
trans.add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "");
|
|
|
|
|
|
|
|
// Done, cleanup
|
|
|
|
trans.commit();
|
|
|
|
supportInvalidateOptionsMenu();
|
|
|
|
recreateSpinner();
|
|
|
|
if(drawer != null) {
|
|
|
|
drawer.closeDrawers();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(secondaryContainer != null) {
|
|
|
|
secondaryContainer.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
if(drawerToggle != null) {
|
|
|
|
drawerToggle.setDrawerIndicatorEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void openNowPlaying() {
|
|
|
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
public void closeNowPlaying() {
|
|
|
|
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
|
|
|
|
isPanelClosing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private SubsonicFragment getNewFragment(String fragmentType) {
|
|
|
|
if("Artist".equals(fragmentType)) {
|
|
|
|
return new SelectArtistFragment();
|
|
|
|
} else if("Playlist".equals(fragmentType)) {
|
|
|
|
return new SelectPlaylistFragment();
|
|
|
|
} else if("Download".equals(fragmentType)) {
|
|
|
|
return new DownloadFragment();
|
|
|
|
} else {
|
|
|
|
return new SelectArtistFragment();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void checkUpdates() {
|
|
|
|
try {
|
|
|
|
String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
|
|
|
|
int ver = Integer.parseInt(version.replace(".", ""));
|
|
|
|
Updater updater = new Updater(ver);
|
|
|
|
updater.checkUpdates(this);
|
|
|
|
}
|
|
|
|
catch(Exception e) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadSession() {
|
|
|
|
loadSettings();
|
|
|
|
// If we are on Subsonic 5.2+, save play queue
|
|
|
|
if(!Util.isOffline(this)) {
|
|
|
|
loadRemotePlayQueue();
|
|
|
|
}
|
|
|
|
|
|
|
|
sessionInitialized = true;
|
|
|
|
}
|
|
|
|
private void loadSettings() {
|
|
|
|
PreferenceManager.setDefaultValues(this, R.xml.settings_appearance, false);
|
|
|
|
PreferenceManager.setDefaultValues(this, R.xml.settings_cache, false);
|
|
|
|
PreferenceManager.setDefaultValues(this, R.xml.settings_playback, false);
|
|
|
|
|
|
|
|
SharedPreferences prefs = Util.getPreferences(this);
|
|
|
|
if (!prefs.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION) || prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null) == null) {
|
|
|
|
resetCacheLocation(prefs);
|
|
|
|
} else {
|
|
|
|
String path = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
|
|
|
File cacheLocation = new File(path);
|
|
|
|
if(!FileUtil.verifyCanWrite(cacheLocation)) {
|
|
|
|
// Only warn user if there is a difference saved
|
|
|
|
if(resetCacheLocation(prefs)) {
|
|
|
|
Util.info(this, R.string.common_warning, R.string.settings_cache_location_reset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!prefs.contains(Constants.PREFERENCES_KEY_OFFLINE)) {
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(Constants.PREFERENCES_KEY_OFFLINE, false);
|
|
|
|
|
|
|
|
editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + 1, "Demo Server");
|
|
|
|
editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + 1, "http://demo.subsonic.org");
|
2017-03-12 07:58:17 +01:00
|
|
|
editor.putString(Constants.PREFERENCES_KEY_USERNAME + 1, "guest5");
|
2016-12-18 18:41:30 +01:00
|
|
|
editor.putString(Constants.PREFERENCES_KEY_PASSWORD + 1, "guest");
|
|
|
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
|
2017-06-11 17:09:09 +02:00
|
|
|
editor.apply();
|
2016-12-18 18:41:30 +01:00
|
|
|
}
|
|
|
|
if(!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) {
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1);
|
2017-06-11 17:09:09 +02:00
|
|
|
editor.apply();
|
2016-12-18 18:41:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean resetCacheLocation(SharedPreferences prefs) {
|
|
|
|
String newDirectory = FileUtil.getDefaultMusicDirectory(this).getPath();
|
|
|
|
String oldDirectory = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null);
|
|
|
|
if(newDirectory == null || (oldDirectory != null && newDirectory.equals(oldDirectory))) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, newDirectory);
|
2017-06-11 17:09:09 +02:00
|
|
|
editor.apply();
|
2016-12-18 18:41:30 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadRemotePlayQueue() {
|
|
|
|
if(Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER, false)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
final SubsonicActivity context = this;
|
|
|
|
new SilentBackgroundTask<Void>(this) {
|
|
|
|
private PlayerQueue playerQueue;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
try {
|
|
|
|
MusicService musicService = MusicServiceFactory.getMusicService(context);
|
|
|
|
PlayerQueue remoteState = musicService.getPlayQueue(context, null);
|
|
|
|
|
|
|
|
// Make sure we wait until download service is ready
|
|
|
|
DownloadService downloadService = getDownloadService();
|
|
|
|
while(downloadService == null || !downloadService.isInitialized()) {
|
|
|
|
Util.sleepQuietly(100L);
|
|
|
|
downloadService = getDownloadService();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we had a remote state and it's changed is more recent than our existing state
|
|
|
|
if(remoteState != null && remoteState.changed != null) {
|
|
|
|
// Check if changed + 30 seconds since some servers have slight skew
|
|
|
|
Date remoteChange = new Date(remoteState.changed.getTime() - ALLOWED_SKEW);
|
|
|
|
Date localChange = downloadService.getLastStateChanged();
|
|
|
|
if(localChange == null || localChange.before(remoteChange)) {
|
|
|
|
playerQueue = remoteState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(TAG, "Failed to get playing queue to server", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void createAccount() {
|
|
|
|
final Context context = this;
|
|
|
|
|
|
|
|
new SilentBackgroundTask<Void>(this) {
|
|
|
|
@Override
|
|
|
|
protected Void doInBackground() throws Throwable {
|
|
|
|
AccountManager accountManager = (AccountManager) context.getSystemService(ACCOUNT_SERVICE);
|
|
|
|
Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE);
|
|
|
|
accountManager.addAccountExplicitly(account, null, null);
|
|
|
|
|
|
|
|
SharedPreferences prefs = Util.getPreferences(context);
|
|
|
|
boolean syncEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SYNC_ENABLED, true);
|
|
|
|
int syncInterval = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_SYNC_INTERVAL, "60"));
|
|
|
|
|
|
|
|
// Add enabled/frequency to playlist syncing
|
|
|
|
ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled);
|
|
|
|
ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval);
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void done(Void result) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void showInfoDialog() {
|
|
|
|
if (!infoDialogDisplayed) {
|
|
|
|
infoDialogDisplayed = true;
|
|
|
|
if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) {
|
|
|
|
Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Toolbar getActiveToolbar() {
|
|
|
|
return slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED ? nowPlayingToolbar : mainToolbar;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex) {
|
|
|
|
this.currentPlaying = currentPlaying;
|
|
|
|
|
|
|
|
MusicDirectory.Entry song = null;
|
|
|
|
if (currentPlaying != null) {
|
|
|
|
song = currentPlaying.getSong();
|
|
|
|
trackView.setText(song.getTitle());
|
|
|
|
|
|
|
|
if(song.getArtist() != null) {
|
|
|
|
artistView.setVisibility(View.VISIBLE);
|
|
|
|
artistView.setText(song.getArtist());
|
|
|
|
} else {
|
|
|
|
artistView.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
trackView.setText(R.string.main_title);
|
|
|
|
artistView.setText(R.string.main_artist);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coverArtView != null) {
|
|
|
|
int height = coverArtView.getHeight();
|
|
|
|
if (height <= 0) {
|
|
|
|
int[] attrs = new int[]{R.attr.actionBarSize};
|
|
|
|
TypedArray typedArray = this.obtainStyledAttributes(attrs);
|
|
|
|
height = typedArray.getDimensionPixelSize(0, 0);
|
|
|
|
typedArray.recycle();
|
|
|
|
}
|
|
|
|
getImageLoader().loadImage(coverArtView, song, false, height, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
previousButton.setVisibility(View.VISIBLE);
|
|
|
|
nextButton.setVisibility(View.VISIBLE);
|
|
|
|
|
|
|
|
rewindButton.setVisibility(View.GONE);
|
|
|
|
fastforwardButton.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSongsChanged(List<DownloadFile> songs, DownloadFile currentPlaying, int currentPlayingIndex) {
|
|
|
|
if(this.currentPlaying != currentPlaying || this.currentPlaying == null) {
|
|
|
|
onSongChanged(currentPlaying, currentPlayingIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSongProgress(DownloadFile currentPlaying, int millisPlayed, Integer duration, boolean isSeekable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStateUpdate(DownloadFile downloadFile, PlayerState playerState) {
|
|
|
|
int[] attrs = new int[]{(playerState == PlayerState.STARTED) ? R.attr.actionbar_pause : R.attr.actionbar_start};
|
|
|
|
TypedArray typedArray = this.obtainStyledAttributes(attrs);
|
|
|
|
startButton.setImageResource(typedArray.getResourceId(0, 0));
|
|
|
|
typedArray.recycle();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onMetadataUpdate(MusicDirectory.Entry song, int fieldChange) {
|
|
|
|
if(song != null && coverArtView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) {
|
|
|
|
int height = coverArtView.getHeight();
|
|
|
|
if (height <= 0) {
|
|
|
|
int[] attrs = new int[]{R.attr.actionBarSize};
|
|
|
|
TypedArray typedArray = this.obtainStyledAttributes(attrs);
|
|
|
|
height = typedArray.getDimensionPixelSize(0, 0);
|
|
|
|
typedArray.recycle();
|
|
|
|
}
|
|
|
|
getImageLoader().loadImage(coverArtView, song, false, height, false);
|
|
|
|
|
|
|
|
// We need to update it immediately since it won't update if updater is not running for it
|
|
|
|
if(nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
|
|
|
|
nowPlayingFragment.onMetadataUpdate(song, fieldChange);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|