-Changed play queue item building to shrink thumbnail before caching.
-Renamed refactor directory in player to helper. -Fixed background player notification update causing lag on older spec models. -Fixed service activity theme not changing after user setting is changed. -Fixed NPE on popup player fling to close. -Fixed audio reactor volume and max volume mixup. -Added correct toast for each player error case. -Fixed button coloring for play queue service activity on landscape. -Changed title and uploader text to marquee for vertical service activity. -Removed cache clearing on every thumbnail load.
This commit is contained in:
parent
f284a799ef
commit
1fb3774e03
|
@ -34,7 +34,6 @@ import android.support.annotation.Nullable;
|
|||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
|
@ -46,12 +45,12 @@ import org.schabi.newpipe.extractor.MediaFormat;
|
|||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
||||
import org.schabi.newpipe.player.refactor.LockManager;
|
||||
import org.schabi.newpipe.player.helper.LockManager;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.getTimeString;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -163,9 +162,7 @@ public final class BackgroundPlayer extends Service {
|
|||
private void onScreenOnOff(boolean on) {
|
||||
if (DEBUG) Log.d(TAG, "onScreenOnOff() called with: on = [" + on + "]");
|
||||
shouldUpdateOnProgress = on;
|
||||
if (on) {
|
||||
basePlayerImpl.triggerProgressUpdate();
|
||||
}
|
||||
basePlayerImpl.triggerProgressUpdate();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -207,9 +204,9 @@ public final class BackgroundPlayer extends Service {
|
|||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
||||
remoteViews.setOnClickPendingIntent(R.id.notificationFRewind,
|
||||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
remoteViews.setOnClickPendingIntent(R.id.notificationFForward,
|
||||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
remoteViews.setOnClickPendingIntent(R.id.notificationFForward,
|
||||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
||||
setRepeatModeIcon(remoteViews, basePlayerImpl.getRepeatMode());
|
||||
}
|
||||
|
@ -299,7 +296,6 @@ public final class BackgroundPlayer extends Service {
|
|||
|
||||
updateNotification(-1);
|
||||
}
|
||||
clearThumbnailCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -317,7 +313,9 @@ public final class BackgroundPlayer extends Service {
|
|||
@Override
|
||||
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
|
||||
updateProgress(currentProgress, duration, bufferPercent);
|
||||
|
||||
if (!shouldUpdateOnProgress) return;
|
||||
resetNotification();
|
||||
if (bigNotRemoteView != null) {
|
||||
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
||||
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
|
||||
|
@ -325,7 +323,6 @@ public final class BackgroundPlayer extends Service {
|
|||
if (notRemoteView != null) {
|
||||
notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
|
||||
}
|
||||
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
|
@ -348,29 +345,6 @@ public final class BackgroundPlayer extends Service {
|
|||
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast == null) {
|
||||
errorToast = Toast.makeText(context, R.string.player_audio_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnrecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast != null) {
|
||||
errorToast.cancel();
|
||||
}
|
||||
errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ExoPlayer Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -388,6 +362,7 @@ public final class BackgroundPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public void onRepeatModeChanged(int i) {
|
||||
resetNotification();
|
||||
setRepeatModeIcon(notRemoteView, i);
|
||||
setRepeatModeIcon(bigNotRemoteView, i);
|
||||
updateNotification(-1);
|
||||
|
|
|
@ -65,12 +65,13 @@ import com.google.android.exoplayer2.util.Util;
|
|||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.playback.MediaSourceManager;
|
||||
import org.schabi.newpipe.player.playback.PlaybackListener;
|
||||
import org.schabi.newpipe.player.refactor.AudioReactor;
|
||||
import org.schabi.newpipe.player.refactor.CacheFactory;
|
||||
import org.schabi.newpipe.player.refactor.LoadController;
|
||||
import org.schabi.newpipe.player.helper.AudioReactor;
|
||||
import org.schabi.newpipe.player.helper.CacheFactory;
|
||||
import org.schabi.newpipe.player.helper.LoadController;
|
||||
import org.schabi.newpipe.playlist.PlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueueAdapter;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
|
@ -85,7 +86,7 @@ import io.reactivex.disposables.Disposable;
|
|||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Predicate;
|
||||
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.getTimeString;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
||||
|
||||
/**
|
||||
* Base for the players, joining the common properties
|
||||
|
@ -194,7 +195,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
|
||||
public void initListeners() {}
|
||||
|
||||
protected Disposable getProgressReactor() {
|
||||
private Disposable getProgressReactor() {
|
||||
return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.filter(new Predicate<Long>() {
|
||||
|
@ -249,7 +250,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
playbackManager = new MediaSourceManager(this, playQueue);
|
||||
|
||||
if (playQueueAdapter != null) playQueueAdapter.dispose();
|
||||
playQueueAdapter = new PlayQueueAdapter(playQueue);
|
||||
playQueueAdapter = new PlayQueueAdapter(context, playQueue);
|
||||
}
|
||||
|
||||
public void initThumbnail(final String url) {
|
||||
|
@ -536,7 +537,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
case Player.STATE_ENDED: // 4
|
||||
// Ensure the current window has actually ended
|
||||
// since single windows that are still loading may produce an ended state
|
||||
if (simpleExoPlayer.getDuration() > 0 && simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration()) {
|
||||
if (isCurrentWindowValid() && simpleExoPlayer.getCurrentPosition() >= simpleExoPlayer.getDuration()) {
|
||||
changeState(STATE_COMPLETED);
|
||||
isPrepared = false;
|
||||
}
|
||||
|
@ -549,10 +550,9 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
* There are multiple types of errors: <br><br>
|
||||
*
|
||||
* {@link ExoPlaybackException#TYPE_SOURCE TYPE_SOURCE}: <br><br>
|
||||
* If the current {@link com.google.android.exoplayer2.Timeline.Window window} has
|
||||
* duration and position greater than 0, then we know the current window is working correctly
|
||||
* and the error is produced by transitioning into a bad window, therefore we report an error
|
||||
* to the play queue based on if the current error can be skipped.
|
||||
* If the current {@link com.google.android.exoplayer2.Timeline.Window window} is valid,
|
||||
* then we know the error is produced by transitioning into a bad window, therefore we report
|
||||
* an error to the play queue based on if the current error can be skipped.
|
||||
*
|
||||
* This is done because ExoPlayer reports the source exceptions before window is
|
||||
* transitioned on seamless playback.
|
||||
|
@ -579,9 +579,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
|
||||
switch (error.type) {
|
||||
case ExoPlaybackException.TYPE_SOURCE:
|
||||
final boolean skippable = simpleExoPlayer.getDuration() >= 0 && simpleExoPlayer.getCurrentPosition() >= 0;
|
||||
playQueue.error(skippable);
|
||||
onRecoverableError(error);
|
||||
playQueue.error(isCurrentWindowValid());
|
||||
onStreamError(error);
|
||||
break;
|
||||
case ExoPlaybackException.TYPE_UNEXPECTED:
|
||||
onRecoverableError(error);
|
||||
|
@ -670,9 +669,35 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
// General Player
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public abstract void onRecoverableError(Exception exception);
|
||||
public void onStreamError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
public abstract void onUnrecoverableError(Exception exception);
|
||||
if (errorToast == null) {
|
||||
errorToast = Toast.makeText(context, R.string.player_stream_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void onRecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast == null) {
|
||||
errorToast = Toast.makeText(context, R.string.player_recoverable_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnrecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast != null) {
|
||||
errorToast.cancel();
|
||||
}
|
||||
errorToast = Toast.makeText(context, R.string.player_unrecoverable_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
public void onPrepared(boolean playWhenReady) {
|
||||
if (DEBUG) Log.d(TAG, "onPrepared() called with: playWhenReady = [" + playWhenReady + "]");
|
||||
|
@ -754,6 +779,11 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
|||
simpleExoPlayer.seekTo(progress);
|
||||
}
|
||||
|
||||
public boolean isCurrentWindowValid() {
|
||||
return simpleExoPlayer != null && simpleExoPlayer.getDuration() >= 0
|
||||
&& simpleExoPlayer.getCurrentPosition() >= 0;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
|
@ -23,7 +23,6 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
@ -50,7 +49,7 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
|||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.player.refactor.PlayerHelper;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItemBuilder;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItemHolder;
|
||||
|
@ -288,12 +287,6 @@ public final class MainVideoPlayer extends Activity {
|
|||
screenRotationButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onThumbnailReceived(Bitmap thumbnail) {
|
||||
super.onThumbnailReceived(thumbnail);
|
||||
clearThumbnailCache();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ExoPlayer Video Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -439,29 +432,6 @@ public final class MainVideoPlayer extends Activity {
|
|||
if (isPlaying()) hideControls(300, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast == null) {
|
||||
errorToast = Toast.makeText(context, R.string.player_video_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnrecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast != null) {
|
||||
errorToast.cancel();
|
||||
}
|
||||
errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) {
|
||||
return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
|
||||
|
@ -763,11 +733,12 @@ public final class MainVideoPlayer extends Activity {
|
|||
|
||||
if (e1.getX() > playerImpl.getRootView().getWidth() / 2) {
|
||||
double floor = Math.floor(up ? stepVolume : -stepVolume);
|
||||
currentVolume = (int) (playerImpl.getAudioReactor().getMaxVolume() + floor);
|
||||
currentVolume = (int) (playerImpl.getAudioReactor().getVolume() + floor);
|
||||
if (currentVolume >= maxVolume) currentVolume = maxVolume;
|
||||
if (currentVolume <= minVolume) currentVolume = (int) minVolume;
|
||||
playerImpl.getAudioReactor().setMaxVolume(currentVolume);
|
||||
playerImpl.getAudioReactor().setVolume(currentVolume);
|
||||
|
||||
currentVolume = playerImpl.getAudioReactor().getVolume();
|
||||
if (DEBUG) Log.d(TAG, "onScroll().volumeControl, currentVolume = " + currentVolume);
|
||||
final String volumeText = volumeUnicode + " " + Math.round((((float) currentVolume) / maxVolume) * 100) + "%";
|
||||
playerImpl.getVolumeTextView().setText(volumeText);
|
||||
|
|
|
@ -66,7 +66,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
|
|||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.refactor.LockManager;
|
||||
import org.schabi.newpipe.player.helper.LockManager;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
|
@ -85,7 +85,7 @@ import io.reactivex.disposables.Disposable;
|
|||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.isUsingOldPlayer;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isUsingOldPlayer;
|
||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
|
||||
/**
|
||||
|
@ -366,7 +366,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
}
|
||||
|
||||
private void updatePopupSize(int width, int height) {
|
||||
//if (DEBUG) Log.d(TAG, "updatePopupSize() called with: width = [" + width + "], height = [" + height + "]");
|
||||
if (DEBUG) Log.d(TAG, "updatePopupSize() called with: width = [" + width + "], height = [" + height + "]");
|
||||
|
||||
width = (int) (width > maximumWidth ? maximumWidth : width < minimumWidth ? minimumWidth : width);
|
||||
|
||||
|
@ -440,7 +440,6 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
updateNotification(-1);
|
||||
}
|
||||
clearThumbnailCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -481,29 +480,6 @@ public final class PopupVideoPlayer extends Service {
|
|||
if (isPlaying()) hideControls(500, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast == null) {
|
||||
errorToast = Toast.makeText(context, R.string.player_video_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnrecoverableError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
|
||||
if (errorToast != null) {
|
||||
errorToast.cancel();
|
||||
}
|
||||
errorToast = Toast.makeText(context, R.string.player_unexpected_failure, Toast.LENGTH_SHORT);
|
||||
errorToast.show();
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
super.onStopTrackingTouch(seekBar);
|
||||
|
@ -737,7 +713,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
public boolean onDoubleTap(MotionEvent e) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY());
|
||||
if (!playerImpl.isPlaying() || !playerImpl.isPlayerReady()) return false;
|
||||
if (playerImpl == null || !playerImpl.isPlaying() || !playerImpl.isPlayerReady()) return false;
|
||||
|
||||
if (e.getX() > popupWidth / 2) {
|
||||
playerImpl.onFastForward();
|
||||
|
@ -751,7 +727,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
if (DEBUG) Log.d(TAG, "onSingleTapConfirmed() called with: e = [" + e + "]");
|
||||
if (playerImpl.getPlayer() == null) return false;
|
||||
if (playerImpl == null || playerImpl.getPlayer() == null) return false;
|
||||
playerImpl.onVideoPlayPause();
|
||||
return true;
|
||||
}
|
||||
|
@ -776,7 +752,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
||||
if (isResizing) return super.onScroll(e1, e2, distanceX, distanceY);
|
||||
if (isResizing || playerImpl == null) return super.onScroll(e1, e2, distanceX, distanceY);
|
||||
|
||||
if (playerImpl.getCurrentState() != BasePlayer.STATE_BUFFERING
|
||||
&& (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0);
|
||||
|
@ -807,6 +783,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
private void onScrollEnd() {
|
||||
if (DEBUG) Log.d(TAG, "onScrollEnd() called");
|
||||
if (playerImpl == null) return;
|
||||
if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == BasePlayer.STATE_PLAYING) {
|
||||
playerImpl.hideControls(300, VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME);
|
||||
}
|
||||
|
@ -814,6 +791,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
if (playerImpl == null) return false;
|
||||
if (Math.abs(velocityX) > SHUTDOWN_FLING_VELOCITY) {
|
||||
if (DEBUG) Log.d(TAG, "Popup close fling velocity= " + velocityX);
|
||||
onClose();
|
||||
|
@ -825,6 +803,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
gestureDetector.onTouchEvent(event);
|
||||
if (playerImpl == null) return false;
|
||||
if (event.getPointerCount() == 2 && !isResizing) {
|
||||
if (DEBUG) Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing.");
|
||||
playerImpl.showAndAnimateControl(-1, true);
|
||||
|
|
|
@ -36,8 +36,8 @@ import org.schabi.newpipe.util.Localization;
|
|||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatPitch;
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatPitch;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||
|
||||
public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener, View.OnClickListener {
|
||||
|
@ -48,7 +48,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
protected BasePlayer player;
|
||||
|
||||
private boolean seeking;
|
||||
|
||||
private boolean redraw;
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -119,6 +119,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
bind();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (redraw) {
|
||||
recreate();
|
||||
redraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.menu_play_queue, menu);
|
||||
|
@ -136,6 +145,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
redraw = true;
|
||||
return true;
|
||||
case R.id.action_system_audio:
|
||||
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
|
||||
|
@ -228,6 +238,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
metadataArtist = rootView.findViewById(R.id.artist_name);
|
||||
|
||||
metadata.setOnClickListener(this);
|
||||
metadataTitle.setSelected(true);
|
||||
metadataArtist.setSelected(true);
|
||||
}
|
||||
|
||||
private void buildSeekBar() {
|
||||
|
@ -452,7 +464,6 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
|||
onStateChanged(state);
|
||||
onPlayModeChanged(repeatMode, shuffled);
|
||||
onPlaybackParameterChanged(parameters);
|
||||
scrollToSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -65,8 +65,8 @@ import org.schabi.newpipe.util.ListHelper;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.player.refactor.PlayerHelper.getTimeString;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.schabi.newpipe.player.refactor;
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
@ -17,7 +17,6 @@ import com.google.android.exoplayer2.SimpleExoPlayer;
|
|||
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
|
||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AudioRendererEventListener {
|
||||
|
||||
private static final String TAG = "AudioFocusReactor";
|
||||
|
@ -32,25 +31,22 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
|||
private final Context context;
|
||||
private final AudioManager audioManager;
|
||||
|
||||
private AudioFocusRequest request;
|
||||
|
||||
private final boolean isResumeAfterAudioFocusGain;
|
||||
private final AudioFocusRequest request;
|
||||
|
||||
public AudioReactor(@NonNull final Context context, @NonNull final SimpleExoPlayer player) {
|
||||
this.player = player;
|
||||
this.context = context;
|
||||
|
||||
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
this.isResumeAfterAudioFocusGain = PlayerHelper.isResumeAfterAudioFocusGain(context);
|
||||
|
||||
player.setAudioDebugListener(this);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (shouldBuildFocusRequest()) {
|
||||
request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setWillPauseWhenDucked(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build();
|
||||
} else {
|
||||
request = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +55,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void requestAudioFocus() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (shouldBuildFocusRequest()) {
|
||||
audioManager.requestAudioFocus(request);
|
||||
} else {
|
||||
audioManager.requestAudioFocus(this, STREAM_TYPE, FOCUS_GAIN_TYPE);
|
||||
|
@ -67,21 +63,29 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
|||
}
|
||||
|
||||
public void abandonAudioFocus() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (shouldBuildFocusRequest()) {
|
||||
audioManager.abandonAudioFocusRequest(request);
|
||||
} else {
|
||||
audioManager.abandonAudioFocus(this);
|
||||
}
|
||||
}
|
||||
|
||||
public int getVolume() {
|
||||
return audioManager.getStreamVolume(STREAM_TYPE);
|
||||
}
|
||||
|
||||
public int getMaxVolume() {
|
||||
return audioManager.getStreamMaxVolume(STREAM_TYPE);
|
||||
}
|
||||
|
||||
public void setMaxVolume(final int volume) {
|
||||
public void setVolume(final int volume) {
|
||||
audioManager.setStreamVolume(STREAM_TYPE, volume, 0);
|
||||
}
|
||||
|
||||
private boolean shouldBuildFocusRequest() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// AudioFocus
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -108,7 +112,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
|||
player.setVolume(DUCK_AUDIO_TO);
|
||||
animateAudio(DUCK_AUDIO_TO, 1f, DUCK_DURATION);
|
||||
|
||||
if (isResumeAfterAudioFocusGain) {
|
||||
if (PlayerHelper.isResumeAfterAudioFocusGain(context)) {
|
||||
player.setPlayWhenReady(true);
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +163,8 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
|||
|
||||
@Override
|
||||
public void onAudioSessionId(int i) {
|
||||
if (!PlayerHelper.isUsingDSP(context)) return;
|
||||
|
||||
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, i);
|
||||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
|
|
@ -1,4 +1,4 @@
|
|||
package org.schabi.newpipe.player.refactor;
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
|
@ -1,4 +1,4 @@
|
|||
package org.schabi.newpipe.player.refactor;
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.content.Context;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.schabi.newpipe.player.refactor;
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
|
@ -1,4 +1,4 @@
|
|||
package org.schabi.newpipe.player.refactor;
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -80,6 +80,9 @@ public class PlayerHelper {
|
|||
return 5000L;
|
||||
}
|
||||
|
||||
public static boolean isUsingDSP(@NonNull final Context context) {
|
||||
return true;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Private helpers
|
||||
////////////////////////////////////////////////////////////////////////////
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe.playlist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -61,8 +62,8 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
public View view;
|
||||
}
|
||||
|
||||
public PlayQueueAdapter(final PlayQueue playQueue) {
|
||||
this.playQueueItemBuilder = new PlayQueueItemBuilder();
|
||||
public PlayQueueAdapter(final Context context, final PlayQueue playQueue) {
|
||||
this.playQueueItemBuilder = new PlayQueueItemBuilder(context);
|
||||
this.playQueue = playQueue;
|
||||
|
||||
startReactor();
|
||||
|
@ -94,9 +95,7 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
}
|
||||
};
|
||||
|
||||
playQueue.getBroadcastReceiver()
|
||||
.toObservable()
|
||||
.subscribe(observer);
|
||||
playQueue.getBroadcastReceiver().toObservable().subscribe(observer);
|
||||
}
|
||||
|
||||
private void onPlayQueueChanged(final PlayQueueEvent message) {
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package org.schabi.newpipe.playlist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
|
@ -15,6 +19,10 @@ public class PlayQueueItemBuilder {
|
|||
|
||||
private static final String TAG = PlayQueueItemBuilder.class.toString();
|
||||
|
||||
private final int thumbnailWidthPx;
|
||||
private final int thumbnailHeightPx;
|
||||
private final DisplayImageOptions imageOptions;
|
||||
|
||||
public interface OnSelectedListener {
|
||||
void selected(PlayQueueItem item, View view);
|
||||
void held(PlayQueueItem item, View view);
|
||||
|
@ -23,7 +31,11 @@ public class PlayQueueItemBuilder {
|
|||
|
||||
private OnSelectedListener onItemClickListener;
|
||||
|
||||
public PlayQueueItemBuilder() {}
|
||||
public PlayQueueItemBuilder(final Context context) {
|
||||
thumbnailWidthPx = context.getResources().getDimensionPixelSize(R.dimen.play_queue_thumbnail_width);
|
||||
thumbnailHeightPx = context.getResources().getDimensionPixelSize(R.dimen.play_queue_thumbnail_height);
|
||||
imageOptions = buildImageOptions(thumbnailWidthPx, thumbnailHeightPx);
|
||||
}
|
||||
|
||||
public void setOnSelectedListener(OnSelectedListener listener) {
|
||||
this.onItemClickListener = listener;
|
||||
|
@ -39,7 +51,7 @@ public class PlayQueueItemBuilder {
|
|||
holder.itemDurationView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
ImageLoader.getInstance().displayImage(item.getThumbnailUrl(), holder.itemThumbnailView, IMAGE_OPTIONS);
|
||||
ImageLoader.getInstance().displayImage(item.getThumbnailUrl(), holder.itemThumbnailView, imageOptions);
|
||||
|
||||
holder.itemRoot.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -78,11 +90,23 @@ public class PlayQueueItemBuilder {
|
|||
};
|
||||
}
|
||||
|
||||
private static final DisplayImageOptions IMAGE_OPTIONS =
|
||||
new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)
|
||||
.showImageOnFail(R.drawable.dummy_thumbnail)
|
||||
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
|
||||
.showImageOnLoading(R.drawable.dummy_thumbnail)
|
||||
.build();
|
||||
private DisplayImageOptions buildImageOptions(final int widthPx, final int heightPx) {
|
||||
final BitmapProcessor bitmapProcessor = new BitmapProcessor() {
|
||||
@Override
|
||||
public Bitmap process(Bitmap bitmap) {
|
||||
final Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, widthPx, heightPx, false);
|
||||
bitmap.recycle();
|
||||
return resizedBitmap;
|
||||
}
|
||||
};
|
||||
|
||||
return new DisplayImageOptions.Builder()
|
||||
.showImageOnFail(R.drawable.dummy_thumbnail)
|
||||
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
|
||||
.showImageOnLoading(R.drawable.dummy_thumbnail)
|
||||
.bitmapConfig(Bitmap.Config.RGB_565) // Users won't be able to see much anyways
|
||||
.preProcessor(bitmapProcessor)
|
||||
.imageScaleType(ImageScaleType.EXACTLY)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@
|
|||
tools:listitem="@layout/play_queue_item"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/control_pane"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_above="@id/progress_bar"
|
||||
android:layout_below="@id/appbar"
|
||||
android:id="@+id/control_pane">
|
||||
android:layout_below="@id/appbar">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/metadata"
|
||||
|
@ -114,14 +114,14 @@
|
|||
<ImageButton
|
||||
android:id="@+id/control_backward"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_toLeftOf="@+id/control_play_pause"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/exo_controls_previous"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
@ -129,17 +129,17 @@
|
|||
<ImageButton
|
||||
android:id="@+id/control_play_pause"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="2dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_pause_white"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
|
@ -147,13 +147,14 @@
|
|||
android:id="@+id/control_progress_bar"
|
||||
style="?android:attr/progressBarStyleLargeInverse"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="#00000000"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:padding="2dp"
|
||||
android:clickable="false"
|
||||
android:scaleType="fitCenter"
|
||||
|
@ -163,15 +164,15 @@
|
|||
<ImageButton
|
||||
android:id="@+id/control_forward"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_toRightOf="@+id/control_play_pause"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/exo_controls_next"
|
||||
tools:ignore="ContentDescription"/>
|
||||
</RelativeLayout>
|
||||
|
@ -189,22 +190,22 @@
|
|||
android:id="@+id/control_playback_speed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/control_repeat"
|
||||
android:gravity="center"
|
||||
android:minWidth="50dp"
|
||||
android:text="1x"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="HardcodedText,RtlHardcoded"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_repeat"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_toLeftOf="@+id/anchor"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
|
@ -212,6 +213,7 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_repeat_white"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
|
@ -222,8 +224,8 @@
|
|||
|
||||
<ImageButton
|
||||
android:id="@+id/control_shuffle"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_toRightOf="@+id/anchor"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="5dp"
|
||||
|
@ -231,6 +233,7 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_shuffle_white_24dp"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
|
@ -238,14 +241,14 @@
|
|||
android:id="@+id/control_playback_pitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/control_shuffle"
|
||||
android:gravity="center"
|
||||
android:minWidth="50dp"
|
||||
android:text="100%"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="HardcodedText,RtlHardcoded"/>
|
||||
|
|
|
@ -41,11 +41,11 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/center"
|
||||
android:layout_above="@+id/progress_bar">
|
||||
android:layout_above="@+id/playback_controls">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/metadata"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
|
@ -59,8 +59,11 @@
|
|||
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?attr/colorAccent"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis nec aliquam augue, eget cursus est. Ut id tristique enim, ut scelerisque tellus. Sed ultricies ipsum non mauris ultricies, commodo malesuada velit porta."
|
||||
|
@ -71,8 +74,11 @@
|
|||
style="@android:style/TextAppearance.StatusBar.EventContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:textSize="12sp"
|
||||
tools:text="Duis posuere arcu condimentum lobortis mattis."/>
|
||||
</LinearLayout>
|
||||
|
@ -100,11 +106,12 @@
|
|||
android:id="@+id/progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/playback_controls"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:background="@drawable/player_controls_bg">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_time"
|
||||
|
@ -124,8 +131,10 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingTop="6dp"
|
||||
tools:progress="25"
|
||||
tools:secondaryProgress="50"/>
|
||||
|
||||
|
@ -143,72 +152,71 @@
|
|||
<RelativeLayout
|
||||
android:id="@+id/playback_controls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:paddingTop="10dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/progress_bar"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/control_playback_speed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/control_repeat"
|
||||
android:gravity="center"
|
||||
android:minWidth="50dp"
|
||||
android:text="1x"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="HardcodedText,RtlHardcoded"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_repeat"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_toLeftOf="@+id/control_backward"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_repeat_white"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_backward"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_toLeftOf="@+id/control_play_pause"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/exo_controls_previous"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_play_pause"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="2dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_pause_white"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
|
@ -216,45 +224,49 @@
|
|||
android:id="@+id/control_progress_bar"
|
||||
style="?android:attr/progressBarStyleLargeInverse"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="#00000000"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:padding="2dp"
|
||||
android:clickable="false"
|
||||
android:scaleType="fitCenter"
|
||||
android:indeterminate="true"
|
||||
android:visibility="invisible"/>
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_forward"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_toRightOf="@+id/control_play_pause"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="2dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/exo_controls_next"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/control_shuffle"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:layout_toRightOf="@+id/control_forward"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitXY"
|
||||
android:tint="?attr/colorAccent"
|
||||
android:src="@drawable/ic_shuffle_white_24dp"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
|
@ -262,14 +274,14 @@
|
|||
android:id="@+id/control_playback_pitch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginLeft="2dp"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/control_shuffle"
|
||||
android:gravity="center"
|
||||
android:minWidth="50dp"
|
||||
android:text="100%"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="HardcodedText,RtlHardcoded"/>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/itemThumbnailView"
|
||||
android:layout_width="62dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_width="@dimen/play_queue_thumbnail_width"
|
||||
android:layout_height="@dimen/play_queue_thumbnail_height"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
android:maxLines="2"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/playlist_detail_title_text_size"
|
||||
tools:text="Mix musics #23 title Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsum"/>
|
||||
tools:text="Mix musics #23 title Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsum" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -89,21 +89,10 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/play_control"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="5dp"
|
||||
android:layout_below="@+id/playlist_meta">
|
||||
|
||||
<Button
|
||||
android:id="@+id/playlist_play_all_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:layout_marginRight="2dp"
|
||||
android:text="@string/play_all"
|
||||
android:textSize="@dimen/channel_rss_title_size"
|
||||
android:theme="@style/RedButton"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/playlist_play_bg_button"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -114,21 +103,40 @@
|
|||
android:layout_toStartOf="@+id/playlist_play_all_button"
|
||||
android:text="@string/controls_background_title"
|
||||
android:textSize="@dimen/channel_rss_title_size"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:theme="@style/RedButton"
|
||||
android:drawableLeft="?attr/audio"
|
||||
android:drawablePadding="4dp"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/playlist_play_all_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_toLeftOf="@+id/playlist_play_popup_button"
|
||||
android:layout_toStartOf="@+id/playlist_play_popup_button"
|
||||
android:text="@string/play_all"
|
||||
android:textSize="@dimen/channel_rss_title_size"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:theme="@style/RedButton"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/playlist_play_popup_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:layout_marginRight="2dp"
|
||||
android:layout_toLeftOf="@+id/playlist_play_bg_button"
|
||||
android:layout_toStartOf="@+id/playlist_play_bg_button"
|
||||
android:layout_alignParentRight="true"
|
||||
android:text="@string/controls_popup_title"
|
||||
android:textSize="@dimen/channel_rss_title_size"
|
||||
android:textColor="?attr/colorAccent"
|
||||
android:theme="@style/RedButton"
|
||||
android:drawableLeft="?attr/popup"
|
||||
android:drawablePadding="4dp"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible" />
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -67,6 +67,10 @@
|
|||
<dimen name="playlist_detail_uploader_image_size">24dp</dimen>
|
||||
<dimen name="playlist_detail_uploader_layout_height">28dp</dimen>
|
||||
|
||||
<!-- Play Queue View Dimensions -->
|
||||
<dimen name="play_queue_thumbnail_width">62dp</dimen>
|
||||
<dimen name="play_queue_thumbnail_height">40dp</dimen>
|
||||
|
||||
<!-- Kiosk view Dimensions-->
|
||||
<dimen name="kiosk_title_text_size">30sp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -136,9 +136,9 @@
|
|||
<string name="could_not_get_stream">Could not get any stream</string>
|
||||
<string name="could_not_load_image">Could not load image</string>
|
||||
<string name="app_ui_crash">App/UI crashed</string>
|
||||
<string name="player_video_failure">Failed to play this video</string>
|
||||
<string name="player_audio_failure">Failed to play this audio</string>
|
||||
<string name="player_unexpected_failure">Unexpected player error occurred</string>
|
||||
<string name="player_stream_failure">Failed to play this stream</string>
|
||||
<string name="player_unrecoverable_failure">Unrecoverable player error occurred</string>
|
||||
<string name="player_recoverable_failure">Recovering from player error</string>
|
||||
|
||||
<!-- error activity -->
|
||||
<string name="sorry_string">Sorry, that should not have happened.</string>
|
||||
|
|
Loading…
Reference in New Issue