2017-10-13 03:22:25 +02:00
|
|
|
package org.schabi.newpipe.player;
|
|
|
|
|
2022-03-15 18:32:39 +01:00
|
|
|
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
|
|
|
|
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
|
|
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
import android.content.ComponentName;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.ServiceConnection;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.IBinder;
|
|
|
|
import android.provider.Settings;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
2018-08-15 20:59:06 +02:00
|
|
|
import android.view.ViewGroup;
|
2017-10-13 03:22:25 +02:00
|
|
|
import android.widget.SeekBar;
|
|
|
|
|
2021-06-05 12:24:53 +02:00
|
|
|
import androidx.annotation.Nullable;
|
2020-04-01 09:08:03 +02:00
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
|
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
import com.google.android.exoplayer2.PlaybackParameters;
|
|
|
|
|
|
|
|
import org.schabi.newpipe.R;
|
2020-10-31 11:03:00 +01:00
|
|
|
import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding;
|
2017-10-13 03:22:25 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
2017-11-04 04:32:10 +01:00
|
|
|
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
2017-10-13 03:22:25 +02:00
|
|
|
import org.schabi.newpipe.player.event.PlayerEventListener;
|
2018-03-21 08:11:54 +01:00
|
|
|
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
|
2020-07-14 19:21:32 +02:00
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueAdapter;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
|
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
|
2017-10-13 03:22:25 +02:00
|
|
|
import org.schabi.newpipe.util.Localization;
|
|
|
|
import org.schabi.newpipe.util.NavigationHelper;
|
2020-10-31 20:26:09 +01:00
|
|
|
import org.schabi.newpipe.util.PermissionHelper;
|
2021-08-04 18:41:23 +02:00
|
|
|
import org.schabi.newpipe.util.ServiceHelper;
|
2017-10-13 03:22:25 +02:00
|
|
|
import org.schabi.newpipe.util.ThemeHelper;
|
|
|
|
|
2021-01-12 21:15:06 +01:00
|
|
|
public final class PlayQueueActivity extends AppCompatActivity
|
2018-03-21 08:11:54 +01:00
|
|
|
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener,
|
|
|
|
View.OnClickListener, PlaybackParameterDialog.Callback {
|
2021-01-12 21:15:06 +01:00
|
|
|
|
|
|
|
private static final String TAG = PlayQueueActivity.class.getSimpleName();
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
private static final int SMOOTH_SCROLL_MAXIMUM_DISTANCE = 80;
|
2020-04-02 13:51:10 +02:00
|
|
|
|
2021-01-08 18:35:33 +01:00
|
|
|
protected Player player;
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
private boolean serviceBound;
|
|
|
|
private ServiceConnection serviceConnection;
|
|
|
|
|
|
|
|
private boolean seeking;
|
2020-04-02 13:51:10 +02:00
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Views
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2020-10-31 11:03:00 +01:00
|
|
|
private ActivityPlayerQueueControlBinding queueControlBinding;
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
private ItemTouchHelper itemTouchHelper;
|
|
|
|
|
2020-03-03 00:01:19 +01:00
|
|
|
private Menu menu;
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Activity Lifecycle
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
protected void onCreate(final Bundle savedInstanceState) {
|
2020-01-28 20:48:42 +01:00
|
|
|
assureCorrectAppLanguage(this);
|
2017-10-13 03:22:25 +02:00
|
|
|
super.onCreate(savedInstanceState);
|
2021-08-04 18:41:23 +02:00
|
|
|
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));
|
2017-10-13 03:22:25 +02:00
|
|
|
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding = ActivityPlayerQueueControlBinding.inflate(getLayoutInflater());
|
|
|
|
setContentView(queueControlBinding.getRoot());
|
|
|
|
|
|
|
|
setSupportActionBar(queueControlBinding.toolbar);
|
2017-10-13 03:22:25 +02:00
|
|
|
if (getSupportActionBar() != null) {
|
|
|
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
2021-01-12 21:15:06 +01:00
|
|
|
getSupportActionBar().setTitle(R.string.title_activity_play_queue);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
serviceConnection = getServiceConnection();
|
|
|
|
bind();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public boolean onCreateOptionsMenu(final Menu m) {
|
|
|
|
this.menu = m;
|
|
|
|
getMenuInflater().inflate(R.menu.menu_play_queue, m);
|
2021-01-12 21:15:06 +01:00
|
|
|
getMenuInflater().inflate(R.menu.menu_play_queue_bg, m);
|
2020-03-03 00:01:19 +01:00
|
|
|
onMaybeMuteChanged();
|
2021-01-11 15:12:44 +01:00
|
|
|
onPlaybackParameterChanged(player.getPlaybackParameters());
|
2017-10-13 03:22:25 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-29 22:15:01 +01:00
|
|
|
// Allow to setup visibility of menuItems
|
|
|
|
@Override
|
2020-07-14 19:21:32 +02:00
|
|
|
public boolean onPrepareOptionsMenu(final Menu m) {
|
2021-01-12 21:15:06 +01:00
|
|
|
if (player != null) {
|
|
|
|
menu.findItem(R.id.action_switch_popup)
|
|
|
|
.setVisible(!player.popupPlayerSelected());
|
|
|
|
menu.findItem(R.id.action_switch_background)
|
|
|
|
.setVisible(!player.audioPlayerSelected());
|
|
|
|
}
|
2020-07-14 19:21:32 +02:00
|
|
|
return super.onPrepareOptionsMenu(m);
|
2019-12-29 22:15:01 +01:00
|
|
|
}
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
2017-10-13 03:22:25 +02:00
|
|
|
switch (item.getItemId()) {
|
|
|
|
case android.R.id.home:
|
|
|
|
finish();
|
|
|
|
return true;
|
2020-02-22 10:36:10 +01:00
|
|
|
case R.id.action_settings:
|
|
|
|
NavigationHelper.openSettings(this);
|
|
|
|
return true;
|
2018-01-22 04:32:49 +01:00
|
|
|
case R.id.action_append_playlist:
|
2022-03-15 18:32:39 +01:00
|
|
|
player.onAddToPlaylistClicked(getSupportFragmentManager());
|
2017-10-13 03:22:25 +02:00
|
|
|
return true;
|
2020-06-14 15:16:04 +02:00
|
|
|
case R.id.action_playback_speed:
|
|
|
|
openPlaybackParameterDialog();
|
|
|
|
return true;
|
2020-03-02 22:52:58 +01:00
|
|
|
case R.id.action_mute:
|
|
|
|
player.onMuteUnmuteButtonClicked();
|
2017-10-13 03:22:25 +02:00
|
|
|
return true;
|
|
|
|
case R.id.action_system_audio:
|
|
|
|
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
|
|
|
|
return true;
|
2018-01-04 07:53:31 +01:00
|
|
|
case R.id.action_switch_main:
|
|
|
|
this.player.setRecovery();
|
2020-10-31 20:26:09 +01:00
|
|
|
NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true);
|
|
|
|
return true;
|
|
|
|
case R.id.action_switch_popup:
|
|
|
|
if (PermissionHelper.isPopupEnabled(this)) {
|
|
|
|
this.player.setRecovery();
|
2021-01-08 18:35:33 +01:00
|
|
|
NavigationHelper.playOnPopupPlayer(this, player.getPlayQueue(), true);
|
2020-10-31 20:26:09 +01:00
|
|
|
} else {
|
|
|
|
PermissionHelper.showPopupEnablementToast(this);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
case R.id.action_switch_background:
|
|
|
|
this.player.setRecovery();
|
2021-01-08 18:35:33 +01:00
|
|
|
NavigationHelper.playOnBackgroundPlayer(this, player.getPlayQueue(), true);
|
2018-01-04 07:53:31 +01:00
|
|
|
return true;
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
2020-10-31 20:26:09 +01:00
|
|
|
return super.onOptionsItemSelected(item);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onDestroy() {
|
|
|
|
super.onDestroy();
|
|
|
|
unbind();
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Service Connection
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
private void bind() {
|
2021-01-12 21:15:06 +01:00
|
|
|
final Intent bindIntent = new Intent(this, MainPlayer.class);
|
|
|
|
final boolean success = bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
|
2017-10-13 03:22:25 +02:00
|
|
|
if (!success) {
|
|
|
|
unbindService(serviceConnection);
|
|
|
|
}
|
|
|
|
serviceBound = success;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void unbind() {
|
2020-03-03 00:01:19 +01:00
|
|
|
if (serviceBound) {
|
2017-10-13 03:22:25 +02:00
|
|
|
unbindService(serviceConnection);
|
|
|
|
serviceBound = false;
|
2021-01-12 21:15:06 +01:00
|
|
|
if (player != null) {
|
|
|
|
player.removeActivityListener(this);
|
|
|
|
}
|
2018-02-17 20:55:45 +01:00
|
|
|
|
|
|
|
if (player != null && player.getPlayQueueAdapter() != null) {
|
|
|
|
player.getPlayQueueAdapter().unsetSelectedListener();
|
|
|
|
}
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.playQueue.setAdapter(null);
|
2020-03-31 19:20:15 +02:00
|
|
|
if (itemTouchHelper != null) {
|
|
|
|
itemTouchHelper.attachToRecyclerView(null);
|
|
|
|
}
|
2018-02-17 20:55:45 +01:00
|
|
|
|
|
|
|
itemTouchHelper = null;
|
2017-10-13 03:22:25 +02:00
|
|
|
player = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private ServiceConnection getServiceConnection() {
|
|
|
|
return new ServiceConnection() {
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onServiceDisconnected(final ComponentName name) {
|
2021-01-12 21:15:06 +01:00
|
|
|
Log.d(TAG, "Player service is disconnected");
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onServiceConnected(final ComponentName name, final IBinder service) {
|
2021-01-12 21:15:06 +01:00
|
|
|
Log.d(TAG, "Player service is connected");
|
2017-10-26 22:42:50 +02:00
|
|
|
|
|
|
|
if (service instanceof PlayerServiceBinder) {
|
|
|
|
player = ((PlayerServiceBinder) service).getPlayerInstance();
|
2019-12-29 22:15:01 +01:00
|
|
|
} else if (service instanceof MainPlayer.LocalBinder) {
|
|
|
|
player = ((MainPlayer.LocalBinder) service).getPlayer();
|
2017-10-26 22:42:50 +02:00
|
|
|
}
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (player == null || player.getPlayQueue() == null
|
2021-01-08 18:35:33 +01:00
|
|
|
|| player.getPlayQueueAdapter() == null || player.exoPlayerIsNull()) {
|
2017-10-13 03:22:25 +02:00
|
|
|
unbind();
|
2017-10-23 03:58:01 +02:00
|
|
|
finish();
|
2017-10-13 03:22:25 +02:00
|
|
|
} else {
|
|
|
|
buildComponents();
|
2021-01-12 21:15:06 +01:00
|
|
|
if (player != null) {
|
|
|
|
player.setActivityListener(PlayQueueActivity.this);
|
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Component Building
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
private void buildComponents() {
|
|
|
|
buildQueue();
|
|
|
|
buildMetadata();
|
|
|
|
buildSeekBar();
|
|
|
|
buildControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void buildQueue() {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.playQueue.setLayoutManager(new LinearLayoutManager(this));
|
|
|
|
queueControlBinding.playQueue.setAdapter(player.getPlayQueueAdapter());
|
|
|
|
queueControlBinding.playQueue.setClickable(true);
|
|
|
|
queueControlBinding.playQueue.setLongClickable(true);
|
|
|
|
queueControlBinding.playQueue.clearOnScrollListeners();
|
|
|
|
queueControlBinding.playQueue.addOnScrollListener(getQueueScrollListener());
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
2020-10-31 11:03:00 +01:00
|
|
|
itemTouchHelper.attachToRecyclerView(queueControlBinding.playQueue);
|
2017-10-13 03:22:25 +02:00
|
|
|
|
2017-10-27 04:59:25 +02:00
|
|
|
player.getPlayQueueAdapter().setSelectedListener(getOnSelectedListener());
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void buildMetadata() {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.metadata.setOnClickListener(this);
|
|
|
|
queueControlBinding.songName.setSelected(true);
|
|
|
|
queueControlBinding.artistName.setSelected(true);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void buildSeekBar() {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekBar.setOnSeekBarChangeListener(this);
|
|
|
|
queueControlBinding.liveSync.setOnClickListener(this);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private void buildControls() {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlRepeat.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlBackward.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlFastRewind.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlPlayPause.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlFastForward.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlForward.setOnClickListener(this);
|
|
|
|
queueControlBinding.controlShuffle.setOnClickListener(this);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Component Helpers
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2017-11-04 04:32:10 +01:00
|
|
|
private OnScrollBelowItemsListener getQueueScrollListener() {
|
|
|
|
return new OnScrollBelowItemsListener() {
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onScrolledDown(final RecyclerView recyclerView) {
|
|
|
|
if (player != null && player.getPlayQueue() != null
|
|
|
|
&& !player.getPlayQueue().isComplete()) {
|
2017-11-04 04:32:10 +01:00
|
|
|
player.getPlayQueue().fetch();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else {
|
|
|
|
queueControlBinding.playQueue.clearOnScrollListeners();
|
2017-11-04 04:32:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
2018-03-14 04:25:22 +01:00
|
|
|
return new PlayQueueItemTouchCallback() {
|
2018-02-17 20:55:45 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onMove(final int sourceIndex, final int targetIndex) {
|
|
|
|
if (player != null) {
|
|
|
|
player.getPlayQueue().move(sourceIndex, targetIndex);
|
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
2018-11-30 20:05:27 +01:00
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onSwiped(final int index) {
|
|
|
|
if (index != -1) {
|
|
|
|
player.getPlayQueue().remove(index);
|
|
|
|
}
|
2018-11-30 20:05:27 +01:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private PlayQueueItemBuilder.OnSelectedListener getOnSelectedListener() {
|
|
|
|
return new PlayQueueItemBuilder.OnSelectedListener() {
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void selected(final PlayQueueItem item, final View view) {
|
|
|
|
if (player != null) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.selectQueueItem(item);
|
2020-03-31 19:20:15 +02:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void held(final PlayQueueItem item, final View view) {
|
2021-08-25 11:04:15 +02:00
|
|
|
if (player != null && player.getPlayQueue().indexOf(item) != -1) {
|
|
|
|
openPopupMenu(player.getPlayQueue(), item, view, false,
|
|
|
|
getSupportFragmentManager(), PlayQueueActivity.this);
|
2020-03-31 19:20:15 +02:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onStartDrag(final PlayQueueItemHolder viewHolder) {
|
|
|
|
if (itemTouchHelper != null) {
|
|
|
|
itemTouchHelper.startDrag(viewHolder);
|
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private void scrollToSelected() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (player == null) {
|
|
|
|
return;
|
|
|
|
}
|
2017-11-04 04:32:10 +01:00
|
|
|
|
|
|
|
final int currentPlayingIndex = player.getPlayQueue().getIndex();
|
|
|
|
final int currentVisibleIndex;
|
2020-10-31 11:03:00 +01:00
|
|
|
if (queueControlBinding.playQueue.getLayoutManager() instanceof LinearLayoutManager) {
|
|
|
|
final LinearLayoutManager layout =
|
|
|
|
(LinearLayoutManager) queueControlBinding.playQueue.getLayoutManager();
|
2017-11-04 04:32:10 +01:00
|
|
|
currentVisibleIndex = layout.findFirstVisibleItemPosition();
|
|
|
|
} else {
|
|
|
|
currentVisibleIndex = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
final int distance = Math.abs(currentPlayingIndex - currentVisibleIndex);
|
|
|
|
if (distance < SMOOTH_SCROLL_MAXIMUM_DISTANCE) {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.playQueue.smoothScrollToPosition(currentPlayingIndex);
|
2017-11-04 04:32:10 +01:00
|
|
|
} else {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.playQueue.scrollToPosition(currentPlayingIndex);
|
2017-11-04 04:32:10 +01:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Component On-Click Listener
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onClick(final View view) {
|
|
|
|
if (player == null) {
|
|
|
|
return;
|
|
|
|
}
|
2017-11-11 23:47:34 +01:00
|
|
|
|
2020-10-31 11:03:00 +01:00
|
|
|
if (view.getId() == queueControlBinding.controlRepeat.getId()) {
|
2017-11-11 23:47:34 +01:00
|
|
|
player.onRepeatClicked();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlBackward.getId()) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.playPrevious();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlFastRewind.getId()) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.fastRewind();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlPlayPause.getId()) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.playPause();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlFastForward.getId()) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.fastForward();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlForward.getId()) {
|
2021-01-08 18:35:33 +01:00
|
|
|
player.playNext();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.controlShuffle.getId()) {
|
2017-11-11 23:47:34 +01:00
|
|
|
player.onShuffleClicked();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.metadata.getId()) {
|
2017-10-27 04:59:25 +02:00
|
|
|
scrollToSelected();
|
2020-10-31 11:03:00 +01:00
|
|
|
} else if (view.getId() == queueControlBinding.liveSync.getId()) {
|
2018-02-27 04:57:59 +01:00
|
|
|
player.seekToDefault();
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 08:11:54 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
2018-03-23 02:44:03 +01:00
|
|
|
// Playback Parameters
|
2018-03-21 08:11:54 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-03-23 02:44:03 +01:00
|
|
|
private void openPlaybackParameterDialog() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (player == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-05-08 20:24:42 +02:00
|
|
|
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
|
2021-01-12 21:15:06 +01:00
|
|
|
player.getPlaybackSkipSilence(), this).show(getSupportFragmentManager(), TAG);
|
2018-03-23 02:44:03 +01:00
|
|
|
}
|
|
|
|
|
2018-03-21 08:11:54 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onPlaybackParameterChanged(final float playbackTempo, final float playbackPitch,
|
|
|
|
final boolean playbackSkipSilence) {
|
2018-05-08 20:24:42 +02:00
|
|
|
if (player != null) {
|
|
|
|
player.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
|
2021-06-05 12:24:53 +02:00
|
|
|
onPlaybackParameterChanged(player.getPlaybackParameters());
|
2018-05-08 20:24:42 +02:00
|
|
|
}
|
2018-03-21 08:11:54 +01:00
|
|
|
}
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Seekbar Listener
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onProgressChanged(final SeekBar seekBar, final int progress,
|
|
|
|
final boolean fromUser) {
|
2017-10-27 04:59:25 +02:00
|
|
|
if (fromUser) {
|
|
|
|
final String seekTime = Localization.getDurationString(progress / 1000);
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.currentTime.setText(seekTime);
|
|
|
|
queueControlBinding.seekDisplay.setText(seekTime);
|
2017-10-27 04:59:25 +02:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onStartTrackingTouch(final SeekBar seekBar) {
|
2017-10-13 03:22:25 +02:00
|
|
|
seeking = true;
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekDisplay.setVisibility(View.VISIBLE);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onStopTrackingTouch(final SeekBar seekBar) {
|
|
|
|
if (player != null) {
|
|
|
|
player.seekTo(seekBar.getProgress());
|
|
|
|
}
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekDisplay.setVisibility(View.GONE);
|
2017-10-13 03:22:25 +02:00
|
|
|
seeking = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Binding Service Listener
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2020-01-06 11:39:01 +01:00
|
|
|
@Override
|
2020-07-14 19:21:32 +02:00
|
|
|
public void onQueueUpdate(final PlayQueue queue) {
|
2020-01-06 11:39:01 +01:00
|
|
|
}
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onPlaybackUpdate(final int state, final int repeatMode, final boolean shuffled,
|
|
|
|
final PlaybackParameters parameters) {
|
2017-10-13 03:22:25 +02:00
|
|
|
onStateChanged(state);
|
|
|
|
onPlayModeChanged(repeatMode, shuffled);
|
|
|
|
onPlaybackParameterChanged(parameters);
|
2018-03-25 19:15:55 +02:00
|
|
|
onMaybePlaybackAdapterChanged();
|
2020-02-23 23:44:16 +01:00
|
|
|
onMaybeMuteChanged();
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onProgressUpdate(final int currentProgress, final int duration,
|
|
|
|
final int bufferPercent) {
|
2017-10-13 03:22:25 +02:00
|
|
|
// Set buffer progress
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekBar.setSecondaryProgress((int) (queueControlBinding.seekBar.getMax()
|
2020-03-31 19:20:15 +02:00
|
|
|
* ((float) bufferPercent / 100)));
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
// Set Duration
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekBar.setMax(duration);
|
|
|
|
queueControlBinding.endTime.setText(Localization.getDurationString(duration / 1000));
|
2017-10-13 03:22:25 +02:00
|
|
|
|
|
|
|
// Set current time if not seeking
|
|
|
|
if (!seeking) {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.seekBar.setProgress(currentProgress);
|
|
|
|
queueControlBinding.currentTime.setText(Localization
|
|
|
|
.getDurationString(currentProgress / 1000));
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
2018-03-21 08:11:54 +01:00
|
|
|
|
|
|
|
if (player != null) {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.liveSync.setClickable(!player.isLiveEdge());
|
2018-03-21 08:11:54 +01:00
|
|
|
}
|
2018-08-15 20:59:06 +02:00
|
|
|
|
2020-11-22 10:39:00 +01:00
|
|
|
// this will make sure progressCurrentTime has the same width as progressEndTime
|
2020-10-31 11:03:00 +01:00
|
|
|
final ViewGroup.LayoutParams currentTimeParams =
|
|
|
|
queueControlBinding.currentTime.getLayoutParams();
|
|
|
|
currentTimeParams.width = queueControlBinding.endTime.getWidth();
|
|
|
|
queueControlBinding.currentTime.setLayoutParams(currentTimeParams);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-07-13 03:17:21 +02:00
|
|
|
public void onMetadataUpdate(final StreamInfo info, final PlayQueue queue) {
|
2017-10-13 03:22:25 +02:00
|
|
|
if (info != null) {
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.songName.setText(info.getName());
|
|
|
|
queueControlBinding.artistName.setText(info.getUploaderName());
|
2018-02-27 04:57:59 +01:00
|
|
|
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.endTime.setVisibility(View.GONE);
|
|
|
|
queueControlBinding.liveSync.setVisibility(View.GONE);
|
2018-02-27 04:57:59 +01:00
|
|
|
switch (info.getStreamType()) {
|
|
|
|
case LIVE_STREAM:
|
|
|
|
case AUDIO_LIVE_STREAM:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.liveSync.setVisibility(View.VISIBLE);
|
2018-02-27 04:57:59 +01:00
|
|
|
break;
|
|
|
|
default:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.endTime.setVisibility(View.VISIBLE);
|
2018-02-27 04:57:59 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-10-13 03:22:25 +02:00
|
|
|
scrollToSelected();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onServiceStopped() {
|
|
|
|
unbind();
|
2017-10-23 03:58:01 +02:00
|
|
|
finish();
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Binding Service Helper
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
private void onStateChanged(final int state) {
|
|
|
|
switch (state) {
|
2021-01-08 18:35:33 +01:00
|
|
|
case Player.STATE_PAUSED:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlPlayPause
|
2021-03-27 15:45:49 +01:00
|
|
|
.setImageResource(R.drawable.ic_play_arrow);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
2021-01-08 18:35:33 +01:00
|
|
|
case Player.STATE_PLAYING:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlPlayPause
|
2021-03-27 15:45:49 +01:00
|
|
|
.setImageResource(R.drawable.ic_pause);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
2021-01-08 18:35:33 +01:00
|
|
|
case Player.STATE_COMPLETED:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlPlayPause
|
2021-03-27 15:45:49 +01:00
|
|
|
.setImageResource(R.drawable.ic_replay);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (state) {
|
2021-01-08 18:35:33 +01:00
|
|
|
case Player.STATE_PAUSED:
|
|
|
|
case Player.STATE_PLAYING:
|
|
|
|
case Player.STATE_COMPLETED:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlPlayPause.setClickable(true);
|
|
|
|
queueControlBinding.controlPlayPause.setVisibility(View.VISIBLE);
|
2020-12-23 15:36:02 +01:00
|
|
|
queueControlBinding.controlProgressBar.setVisibility(View.GONE);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
|
|
|
default:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlPlayPause.setClickable(false);
|
|
|
|
queueControlBinding.controlPlayPause.setVisibility(View.INVISIBLE);
|
2020-12-23 15:36:02 +01:00
|
|
|
queueControlBinding.controlProgressBar.setVisibility(View.VISIBLE);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onPlayModeChanged(final int repeatMode, final boolean shuffled) {
|
|
|
|
switch (repeatMode) {
|
2021-01-08 18:35:33 +01:00
|
|
|
case com.google.android.exoplayer2.Player.REPEAT_MODE_OFF:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlRepeat
|
|
|
|
.setImageResource(R.drawable.exo_controls_repeat_off);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
2021-01-08 18:35:33 +01:00
|
|
|
case com.google.android.exoplayer2.Player.REPEAT_MODE_ONE:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlRepeat
|
|
|
|
.setImageResource(R.drawable.exo_controls_repeat_one);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
2021-01-08 18:35:33 +01:00
|
|
|
case com.google.android.exoplayer2.Player.REPEAT_MODE_ALL:
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlRepeat
|
|
|
|
.setImageResource(R.drawable.exo_controls_repeat_all);
|
2017-10-13 03:22:25 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
final int shuffleAlpha = shuffled ? 255 : 77;
|
2020-10-31 11:03:00 +01:00
|
|
|
queueControlBinding.controlShuffle.setImageAlpha(shuffleAlpha);
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
|
2021-06-05 12:24:53 +02:00
|
|
|
private void onPlaybackParameterChanged(@Nullable final PlaybackParameters parameters) {
|
2017-10-13 03:22:25 +02:00
|
|
|
if (parameters != null) {
|
2020-06-14 15:16:04 +02:00
|
|
|
if (menu != null && player != null) {
|
2020-06-14 19:52:58 +02:00
|
|
|
final MenuItem item = menu.findItem(R.id.action_playback_speed);
|
2020-06-14 15:16:04 +02:00
|
|
|
item.setTitle(formatSpeed(parameters.speed));
|
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
2018-03-25 19:15:55 +02:00
|
|
|
|
|
|
|
private void onMaybePlaybackAdapterChanged() {
|
2020-10-31 11:03:00 +01:00
|
|
|
if (player == null) {
|
2020-03-31 19:20:15 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-03-25 19:15:55 +02:00
|
|
|
final PlayQueueAdapter maybeNewAdapter = player.getPlayQueueAdapter();
|
2020-10-31 11:03:00 +01:00
|
|
|
if (maybeNewAdapter != null
|
|
|
|
&& queueControlBinding.playQueue.getAdapter() != maybeNewAdapter) {
|
|
|
|
queueControlBinding.playQueue.setAdapter(maybeNewAdapter);
|
2018-03-25 19:15:55 +02:00
|
|
|
}
|
|
|
|
}
|
2020-02-23 23:44:16 +01:00
|
|
|
|
2020-03-03 00:01:19 +01:00
|
|
|
private void onMaybeMuteChanged() {
|
2020-03-04 18:37:04 +01:00
|
|
|
if (menu != null && player != null) {
|
2020-08-16 10:24:58 +02:00
|
|
|
final MenuItem item = menu.findItem(R.id.action_mute);
|
2020-03-04 18:53:17 +01:00
|
|
|
|
|
|
|
//Change the mute-button item in ActionBar
|
|
|
|
//1) Text change:
|
|
|
|
item.setTitle(player.isMuted() ? R.string.unmute : R.string.mute);
|
|
|
|
|
|
|
|
//2) Icon change accordingly to current App Theme
|
2020-04-01 09:08:03 +02:00
|
|
|
// using rootView.getContext() because getApplicationContext() didn't work
|
2021-03-27 15:45:49 +01:00
|
|
|
item.setIcon(player.isMuted() ? R.drawable.ic_volume_off : R.drawable.ic_volume_up);
|
2020-03-03 00:01:19 +01:00
|
|
|
}
|
2020-02-23 23:44:16 +01:00
|
|
|
}
|
2017-10-13 03:22:25 +02:00
|
|
|
}
|