-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:
John Zhen Mo 2017-10-28 10:08:01 -07:00
parent f284a799ef
commit 1fb3774e03
19 changed files with 248 additions and 223 deletions

View File

@ -34,7 +34,6 @@ import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.Log; import android.util.Log;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.Toast;
import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player; 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.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.event.PlayerEventListener; 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.playlist.PlayQueueItem;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.ThemeHelper; 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) { private void onScreenOnOff(boolean on) {
if (DEBUG) Log.d(TAG, "onScreenOnOff() called with: on = [" + on + "]"); if (DEBUG) Log.d(TAG, "onScreenOnOff() called with: on = [" + on + "]");
shouldUpdateOnProgress = 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)); PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT));
remoteViews.setOnClickPendingIntent(R.id.notificationFRewind, 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)); 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()); setRepeatModeIcon(remoteViews, basePlayerImpl.getRepeatMode());
} }
@ -299,7 +296,6 @@ public final class BackgroundPlayer extends Service {
updateNotification(-1); updateNotification(-1);
} }
clearThumbnailCache();
} }
@Override @Override
@ -317,7 +313,9 @@ public final class BackgroundPlayer extends Service {
@Override @Override
public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) { public void onUpdateProgress(int currentProgress, int duration, int bufferPercent) {
updateProgress(currentProgress, duration, bufferPercent); updateProgress(currentProgress, duration, bufferPercent);
if (!shouldUpdateOnProgress) return; if (!shouldUpdateOnProgress) return;
resetNotification();
if (bigNotRemoteView != null) { if (bigNotRemoteView != null) {
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false); bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration)); bigNotRemoteView.setTextViewText(R.id.notificationTime, getTimeString(currentProgress) + " / " + getTimeString(duration));
@ -325,7 +323,6 @@ public final class BackgroundPlayer extends Service {
if (notRemoteView != null) { if (notRemoteView != null) {
notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false); notRemoteView.setProgressBar(R.id.notificationProgressBar, duration, currentProgress, false);
} }
updateNotification(-1); updateNotification(-1);
} }
@ -348,29 +345,6 @@ public final class BackgroundPlayer extends Service {
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, null); 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 // ExoPlayer Listener
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -388,6 +362,7 @@ public final class BackgroundPlayer extends Service {
@Override @Override
public void onRepeatModeChanged(int i) { public void onRepeatModeChanged(int i) {
resetNotification();
setRepeatModeIcon(notRemoteView, i); setRepeatModeIcon(notRemoteView, i);
setRepeatModeIcon(bigNotRemoteView, i); setRepeatModeIcon(bigNotRemoteView, i);
updateNotification(-1); updateNotification(-1);

View File

@ -65,12 +65,13 @@ import com.google.android.exoplayer2.util.Util;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.playback.MediaSourceManager; import org.schabi.newpipe.player.playback.MediaSourceManager;
import org.schabi.newpipe.player.playback.PlaybackListener; import org.schabi.newpipe.player.playback.PlaybackListener;
import org.schabi.newpipe.player.refactor.AudioReactor; import org.schabi.newpipe.player.helper.AudioReactor;
import org.schabi.newpipe.player.refactor.CacheFactory; import org.schabi.newpipe.player.helper.CacheFactory;
import org.schabi.newpipe.player.refactor.LoadController; import org.schabi.newpipe.player.helper.LoadController;
import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.playlist.PlayQueue;
import org.schabi.newpipe.playlist.PlayQueueAdapter; import org.schabi.newpipe.playlist.PlayQueueAdapter;
import org.schabi.newpipe.playlist.PlayQueueItem; import org.schabi.newpipe.playlist.PlayQueueItem;
@ -85,7 +86,7 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer; import io.reactivex.functions.Consumer;
import io.reactivex.functions.Predicate; 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 * Base for the players, joining the common properties
@ -194,7 +195,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
public void initListeners() {} public void initListeners() {}
protected Disposable getProgressReactor() { private Disposable getProgressReactor() {
return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS) return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.filter(new Predicate<Long>() { .filter(new Predicate<Long>() {
@ -249,7 +250,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
playbackManager = new MediaSourceManager(this, playQueue); playbackManager = new MediaSourceManager(this, playQueue);
if (playQueueAdapter != null) playQueueAdapter.dispose(); if (playQueueAdapter != null) playQueueAdapter.dispose();
playQueueAdapter = new PlayQueueAdapter(playQueue); playQueueAdapter = new PlayQueueAdapter(context, playQueue);
} }
public void initThumbnail(final String url) { public void initThumbnail(final String url) {
@ -536,7 +537,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
case Player.STATE_ENDED: // 4 case Player.STATE_ENDED: // 4
// Ensure the current window has actually ended // Ensure the current window has actually ended
// since single windows that are still loading may produce an ended state // 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); changeState(STATE_COMPLETED);
isPrepared = false; isPrepared = false;
} }
@ -549,10 +550,9 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
* There are multiple types of errors: <br><br> * There are multiple types of errors: <br><br>
* *
* {@link ExoPlaybackException#TYPE_SOURCE TYPE_SOURCE}: <br><br> * {@link ExoPlaybackException#TYPE_SOURCE TYPE_SOURCE}: <br><br>
* If the current {@link com.google.android.exoplayer2.Timeline.Window window} has * If the current {@link com.google.android.exoplayer2.Timeline.Window window} is valid,
* duration and position greater than 0, then we know the current window is working correctly * then we know the error is produced by transitioning into a bad window, therefore we report
* and the error is produced by transitioning into a bad window, therefore we report an error * an error to the play queue based on if the current error can be skipped.
* 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 * This is done because ExoPlayer reports the source exceptions before window is
* transitioned on seamless playback. * transitioned on seamless playback.
@ -579,9 +579,8 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
switch (error.type) { switch (error.type) {
case ExoPlaybackException.TYPE_SOURCE: case ExoPlaybackException.TYPE_SOURCE:
final boolean skippable = simpleExoPlayer.getDuration() >= 0 && simpleExoPlayer.getCurrentPosition() >= 0; playQueue.error(isCurrentWindowValid());
playQueue.error(skippable); onStreamError(error);
onRecoverableError(error);
break; break;
case ExoPlaybackException.TYPE_UNEXPECTED: case ExoPlaybackException.TYPE_UNEXPECTED:
onRecoverableError(error); onRecoverableError(error);
@ -670,9 +669,35 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
// General Player // 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) { public void onPrepared(boolean playWhenReady) {
if (DEBUG) Log.d(TAG, "onPrepared() called with: playWhenReady = [" + 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); simpleExoPlayer.seekTo(progress);
} }
public boolean isCurrentWindowValid() {
return simpleExoPlayer != null && simpleExoPlayer.getDuration() >= 0
&& simpleExoPlayer.getCurrentPosition() >= 0;
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Utils // Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/

View File

@ -23,7 +23,6 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Color; import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Build; import android.os.Build;
@ -50,7 +49,7 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream; 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.PlayQueueItem;
import org.schabi.newpipe.playlist.PlayQueueItemBuilder; import org.schabi.newpipe.playlist.PlayQueueItemBuilder;
import org.schabi.newpipe.playlist.PlayQueueItemHolder; import org.schabi.newpipe.playlist.PlayQueueItemHolder;
@ -288,12 +287,6 @@ public final class MainVideoPlayer extends Activity {
screenRotationButton.setOnClickListener(this); screenRotationButton.setOnClickListener(this);
} }
@Override
public void onThumbnailReceived(Bitmap thumbnail) {
super.onThumbnailReceived(thumbnail);
clearThumbnailCache();
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// ExoPlayer Video Listener // ExoPlayer Video Listener
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -439,29 +432,6 @@ public final class MainVideoPlayer extends Activity {
if (isPlaying()) hideControls(300, 0); 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 @Override
protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) { protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos); return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
@ -763,11 +733,12 @@ public final class MainVideoPlayer extends Activity {
if (e1.getX() > playerImpl.getRootView().getWidth() / 2) { if (e1.getX() > playerImpl.getRootView().getWidth() / 2) {
double floor = Math.floor(up ? stepVolume : -stepVolume); 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 >= maxVolume) currentVolume = maxVolume;
if (currentVolume <= minVolume) currentVolume = (int) minVolume; 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); if (DEBUG) Log.d(TAG, "onScroll().volumeControl, currentVolume = " + currentVolume);
final String volumeText = volumeUnicode + " " + Math.round((((float) currentVolume) / maxVolume) * 100) + "%"; final String volumeText = volumeUnicode + " " + Math.round((((float) currentVolume) / maxVolume) * 100) + "%";
playerImpl.getVolumeTextView().setText(volumeText); playerImpl.getVolumeTextView().setText(volumeText);

View File

@ -66,7 +66,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.old.PlayVideoActivity; 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.PlayQueueItem;
import org.schabi.newpipe.playlist.SinglePlayQueue; import org.schabi.newpipe.playlist.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.ErrorActivity;
@ -85,7 +85,7 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer; import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers; 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; 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) { 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); width = (int) (width > maximumWidth ? maximumWidth : width < minimumWidth ? minimumWidth : width);
@ -440,7 +440,6 @@ public final class PopupVideoPlayer extends Service {
updateNotification(-1); updateNotification(-1);
} }
clearThumbnailCache();
} }
@Override @Override
@ -481,29 +480,6 @@ public final class PopupVideoPlayer extends Service {
if (isPlaying()) hideControls(500, 0); 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 @Override
public void onStopTrackingTouch(SeekBar seekBar) { public void onStopTrackingTouch(SeekBar seekBar) {
super.onStopTrackingTouch(seekBar); super.onStopTrackingTouch(seekBar);
@ -737,7 +713,7 @@ public final class PopupVideoPlayer extends Service {
public boolean onDoubleTap(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) {
if (DEBUG) if (DEBUG)
Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY()); 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) { if (e.getX() > popupWidth / 2) {
playerImpl.onFastForward(); playerImpl.onFastForward();
@ -751,7 +727,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onSingleTapConfirmed(MotionEvent e) { public boolean onSingleTapConfirmed(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onSingleTapConfirmed() called with: e = [" + 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(); playerImpl.onVideoPlayPause();
return true; return true;
} }
@ -776,7 +752,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 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 if (playerImpl.getCurrentState() != BasePlayer.STATE_BUFFERING
&& (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0); && (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0);
@ -807,6 +783,7 @@ public final class PopupVideoPlayer extends Service {
private void onScrollEnd() { private void onScrollEnd() {
if (DEBUG) Log.d(TAG, "onScrollEnd() called"); if (DEBUG) Log.d(TAG, "onScrollEnd() called");
if (playerImpl == null) return;
if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == BasePlayer.STATE_PLAYING) { if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == BasePlayer.STATE_PLAYING) {
playerImpl.hideControls(300, VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME); playerImpl.hideControls(300, VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME);
} }
@ -814,6 +791,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (playerImpl == null) return false;
if (Math.abs(velocityX) > SHUTDOWN_FLING_VELOCITY) { if (Math.abs(velocityX) > SHUTDOWN_FLING_VELOCITY) {
if (DEBUG) Log.d(TAG, "Popup close fling velocity= " + velocityX); if (DEBUG) Log.d(TAG, "Popup close fling velocity= " + velocityX);
onClose(); onClose();
@ -825,6 +803,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event); gestureDetector.onTouchEvent(event);
if (playerImpl == null) return false;
if (event.getPointerCount() == 2 && !isResizing) { if (event.getPointerCount() == 2 && !isResizing) {
if (DEBUG) Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing."); if (DEBUG) Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing.");
playerImpl.showAndAnimateControl(-1, true); playerImpl.showAndAnimateControl(-1, true);

View File

@ -36,8 +36,8 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatPitch; import static org.schabi.newpipe.player.helper.PlayerHelper.formatPitch;
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatSpeed; import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
public abstract class ServicePlayerActivity extends AppCompatActivity public abstract class ServicePlayerActivity extends AppCompatActivity
implements PlayerEventListener, SeekBar.OnSeekBarChangeListener, View.OnClickListener { implements PlayerEventListener, SeekBar.OnSeekBarChangeListener, View.OnClickListener {
@ -48,7 +48,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
protected BasePlayer player; protected BasePlayer player;
private boolean seeking; private boolean seeking;
private boolean redraw;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Views // Views
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -119,6 +119,15 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
bind(); bind();
} }
@Override
protected void onResume() {
super.onResume();
if (redraw) {
recreate();
redraw = false;
}
}
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_play_queue, menu); getMenuInflater().inflate(R.menu.menu_play_queue, menu);
@ -136,6 +145,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
return true; return true;
case R.id.action_settings: case R.id.action_settings:
NavigationHelper.openSettings(this); NavigationHelper.openSettings(this);
redraw = true;
return true; return true;
case R.id.action_system_audio: case R.id.action_system_audio:
startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS)); startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS));
@ -228,6 +238,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
metadataArtist = rootView.findViewById(R.id.artist_name); metadataArtist = rootView.findViewById(R.id.artist_name);
metadata.setOnClickListener(this); metadata.setOnClickListener(this);
metadataTitle.setSelected(true);
metadataArtist.setSelected(true);
} }
private void buildSeekBar() { private void buildSeekBar() {
@ -452,7 +464,6 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
onStateChanged(state); onStateChanged(state);
onPlayModeChanged(repeatMode, shuffled); onPlayModeChanged(repeatMode, shuffled);
onPlaybackParameterChanged(parameters); onPlaybackParameterChanged(parameters);
scrollToSelected();
} }
@Override @Override

View File

@ -65,8 +65,8 @@ import org.schabi.newpipe.util.ListHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.schabi.newpipe.player.refactor.PlayerHelper.formatSpeed; import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
import static org.schabi.newpipe.player.refactor.PlayerHelper.getTimeString; import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
import static org.schabi.newpipe.util.AnimationUtils.animateView; import static org.schabi.newpipe.util.AnimationUtils.animateView;
/** /**

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.player.refactor; package org.schabi.newpipe.player.helper;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; 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.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
@SuppressWarnings({"WeakerAccess", "unused"})
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AudioRendererEventListener { public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AudioRendererEventListener {
private static final String TAG = "AudioFocusReactor"; private static final String TAG = "AudioFocusReactor";
@ -32,25 +31,22 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
private final Context context; private final Context context;
private final AudioManager audioManager; private final AudioManager audioManager;
private AudioFocusRequest request; private final AudioFocusRequest request;
private final boolean isResumeAfterAudioFocusGain;
public AudioReactor(@NonNull final Context context, @NonNull final SimpleExoPlayer player) { public AudioReactor(@NonNull final Context context, @NonNull final SimpleExoPlayer player) {
this.player = player; this.player = player;
this.context = context; this.context = context;
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
this.isResumeAfterAudioFocusGain = PlayerHelper.isResumeAfterAudioFocusGain(context);
player.setAudioDebugListener(this); player.setAudioDebugListener(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (shouldBuildFocusRequest()) {
request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE) request = new AudioFocusRequest.Builder(FOCUS_GAIN_TYPE)
.setAcceptsDelayedFocusGain(true) .setAcceptsDelayedFocusGain(true)
.setWillPauseWhenDucked(true) .setWillPauseWhenDucked(true)
.setOnAudioFocusChangeListener(this) .setOnAudioFocusChangeListener(this)
.build(); .build();
} else {
request = null;
} }
} }
@ -59,7 +55,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public void requestAudioFocus() { public void requestAudioFocus() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (shouldBuildFocusRequest()) {
audioManager.requestAudioFocus(request); audioManager.requestAudioFocus(request);
} else { } else {
audioManager.requestAudioFocus(this, STREAM_TYPE, FOCUS_GAIN_TYPE); audioManager.requestAudioFocus(this, STREAM_TYPE, FOCUS_GAIN_TYPE);
@ -67,21 +63,29 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
} }
public void abandonAudioFocus() { public void abandonAudioFocus() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (shouldBuildFocusRequest()) {
audioManager.abandonAudioFocusRequest(request); audioManager.abandonAudioFocusRequest(request);
} else { } else {
audioManager.abandonAudioFocus(this); audioManager.abandonAudioFocus(this);
} }
} }
public int getVolume() {
return audioManager.getStreamVolume(STREAM_TYPE);
}
public int getMaxVolume() { public int getMaxVolume() {
return audioManager.getStreamMaxVolume(STREAM_TYPE); return audioManager.getStreamMaxVolume(STREAM_TYPE);
} }
public void setMaxVolume(final int volume) { public void setVolume(final int volume) {
audioManager.setStreamVolume(STREAM_TYPE, volume, 0); audioManager.setStreamVolume(STREAM_TYPE, volume, 0);
} }
private boolean shouldBuildFocusRequest() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// AudioFocus // AudioFocus
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -108,7 +112,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
player.setVolume(DUCK_AUDIO_TO); player.setVolume(DUCK_AUDIO_TO);
animateAudio(DUCK_AUDIO_TO, 1f, DUCK_DURATION); animateAudio(DUCK_AUDIO_TO, 1f, DUCK_DURATION);
if (isResumeAfterAudioFocusGain) { if (PlayerHelper.isResumeAfterAudioFocusGain(context)) {
player.setPlayWhenReady(true); player.setPlayWhenReady(true);
} }
} }
@ -159,6 +163,8 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
@Override @Override
public void onAudioSessionId(int i) { public void onAudioSessionId(int i) {
if (!PlayerHelper.isUsingDSP(context)) return;
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION); final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, i); intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, i);
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName()); intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.player.refactor; package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.player.refactor; package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.player.refactor; package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;

View File

@ -1,4 +1,4 @@
package org.schabi.newpipe.player.refactor; package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -80,6 +80,9 @@ public class PlayerHelper {
return 5000L; return 5000L;
} }
public static boolean isUsingDSP(@NonNull final Context context) {
return true;
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Private helpers // Private helpers
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.playlist; package org.schabi.newpipe.playlist;
import android.content.Context;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -61,8 +62,8 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public View view; public View view;
} }
public PlayQueueAdapter(final PlayQueue playQueue) { public PlayQueueAdapter(final Context context, final PlayQueue playQueue) {
this.playQueueItemBuilder = new PlayQueueItemBuilder(); this.playQueueItemBuilder = new PlayQueueItemBuilder(context);
this.playQueue = playQueue; this.playQueue = playQueue;
startReactor(); startReactor();
@ -94,9 +95,7 @@ public class PlayQueueAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
} }
}; };
playQueue.getBroadcastReceiver() playQueue.getBroadcastReceiver().toObservable().subscribe(observer);
.toObservable()
.subscribe(observer);
} }
private void onPlayQueueChanged(final PlayQueueEvent message) { private void onPlayQueueChanged(final PlayQueueEvent message) {

View File

@ -1,11 +1,15 @@
package org.schabi.newpipe.playlist; package org.schabi.newpipe.playlist;
import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader; 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.R;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
@ -15,6 +19,10 @@ public class PlayQueueItemBuilder {
private static final String TAG = PlayQueueItemBuilder.class.toString(); private static final String TAG = PlayQueueItemBuilder.class.toString();
private final int thumbnailWidthPx;
private final int thumbnailHeightPx;
private final DisplayImageOptions imageOptions;
public interface OnSelectedListener { public interface OnSelectedListener {
void selected(PlayQueueItem item, View view); void selected(PlayQueueItem item, View view);
void held(PlayQueueItem item, View view); void held(PlayQueueItem item, View view);
@ -23,7 +31,11 @@ public class PlayQueueItemBuilder {
private OnSelectedListener onItemClickListener; 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) { public void setOnSelectedListener(OnSelectedListener listener) {
this.onItemClickListener = listener; this.onItemClickListener = listener;
@ -39,7 +51,7 @@ public class PlayQueueItemBuilder {
holder.itemDurationView.setVisibility(View.GONE); 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() { holder.itemRoot.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -78,11 +90,23 @@ public class PlayQueueItemBuilder {
}; };
} }
private static final DisplayImageOptions IMAGE_OPTIONS = private DisplayImageOptions buildImageOptions(final int widthPx, final int heightPx) {
new DisplayImageOptions.Builder() final BitmapProcessor bitmapProcessor = new BitmapProcessor() {
.cacheInMemory(true) @Override
.showImageOnFail(R.drawable.dummy_thumbnail) public Bitmap process(Bitmap bitmap) {
.showImageForEmptyUri(R.drawable.dummy_thumbnail) final Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, widthPx, heightPx, false);
.showImageOnLoading(R.drawable.dummy_thumbnail) bitmap.recycle();
.build(); 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();
}
} }

View File

@ -40,13 +40,13 @@
tools:listitem="@layout/play_queue_item"/> tools:listitem="@layout/play_queue_item"/>
<RelativeLayout <RelativeLayout
android:id="@+id/control_pane"
android:layout_width="200dp" android:layout_width="200dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_above="@id/progress_bar" android:layout_above="@id/progress_bar"
android:layout_below="@id/appbar" android:layout_below="@id/appbar">
android:id="@+id/control_pane">
<LinearLayout <LinearLayout
android:id="@+id/metadata" android:id="@+id/metadata"
@ -114,14 +114,14 @@
<ImageButton <ImageButton
android:id="@+id/control_backward" android:id="@+id/control_backward"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="match_parent" android:layout_height="40dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_toLeftOf="@+id/control_play_pause" android:layout_toLeftOf="@+id/control_play_pause"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:padding="2dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/exo_controls_previous" android:src="@drawable/exo_controls_previous"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -129,17 +129,17 @@
<ImageButton <ImageButton
android:id="@+id/control_play_pause" android:id="@+id/control_play_pause"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="50dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:padding="2dp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_pause_white" android:src="@drawable/ic_pause_white"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -147,13 +147,14 @@
android:id="@+id/control_progress_bar" android:id="@+id/control_progress_bar"
style="?android:attr/progressBarStyleLargeInverse" style="?android:attr/progressBarStyleLargeInverse"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="50dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:background="#00000000" android:background="#00000000"
android:tint="?attr/colorAccent"
android:padding="2dp" android:padding="2dp"
android:clickable="false" android:clickable="false"
android:scaleType="fitCenter" android:scaleType="fitCenter"
@ -163,15 +164,15 @@
<ImageButton <ImageButton
android:id="@+id/control_forward" android:id="@+id/control_forward"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="match_parent" android:layout_height="40dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/control_play_pause" android:layout_toRightOf="@+id/control_play_pause"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:padding="2dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/exo_controls_next" android:src="@drawable/exo_controls_next"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
</RelativeLayout> </RelativeLayout>
@ -189,22 +190,22 @@
android:id="@+id/control_playback_speed" android:id="@+id/control_playback_speed"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginLeft="2dp" android:layout_marginLeft="5dp"
android:layout_marginRight="2dp" android:layout_marginRight="5dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/control_repeat" android:layout_toLeftOf="@+id/control_repeat"
android:gravity="center" android:gravity="center"
android:minWidth="50dp" android:minWidth="50dp"
android:text="1x" android:text="1x"
android:textColor="@android:color/white" android:textColor="?attr/colorAccent"
android:textStyle="bold" android:textStyle="bold"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded"/> tools:ignore="HardcodedText,RtlHardcoded"/>
<ImageButton <ImageButton
android:id="@+id/control_repeat" android:id="@+id/control_repeat"
android:layout_width="25dp" android:layout_width="30dp"
android:layout_height="25dp" android:layout_height="30dp"
android:layout_toLeftOf="@+id/anchor" android:layout_toLeftOf="@+id/anchor"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
@ -212,6 +213,7 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitXY" android:scaleType="fitXY"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_repeat_white" android:src="@drawable/ic_repeat_white"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -222,8 +224,8 @@
<ImageButton <ImageButton
android:id="@+id/control_shuffle" android:id="@+id/control_shuffle"
android:layout_width="25dp" android:layout_width="30dp"
android:layout_height="25dp" android:layout_height="30dp"
android:layout_toRightOf="@+id/anchor" android:layout_toRightOf="@+id/anchor"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
@ -231,6 +233,7 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitXY" android:scaleType="fitXY"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_shuffle_white_24dp" android:src="@drawable/ic_shuffle_white_24dp"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -238,14 +241,14 @@
android:id="@+id/control_playback_pitch" android:id="@+id/control_playback_pitch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginLeft="2dp" android:layout_marginLeft="5dp"
android:layout_marginRight="2dp" android:layout_marginRight="5dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toRightOf="@+id/control_shuffle" android:layout_toRightOf="@+id/control_shuffle"
android:gravity="center" android:gravity="center"
android:minWidth="50dp" android:minWidth="50dp"
android:text="100%" android:text="100%"
android:textColor="@android:color/white" android:textColor="?attr/colorAccent"
android:textStyle="bold" android:textStyle="bold"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded"/> tools:ignore="HardcodedText,RtlHardcoded"/>

View File

@ -41,11 +41,11 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/center" android:id="@+id/center"
android:layout_above="@+id/progress_bar"> android:layout_above="@+id/playback_controls">
<LinearLayout <LinearLayout
android:id="@+id/metadata" android:id="@+id/metadata"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="8dp" android:padding="8dp"
@ -59,8 +59,11 @@
style="@android:style/TextAppearance.StatusBar.EventContent.Title" style="@android:style/TextAppearance.StatusBar.EventContent.Title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="marquee"
android:maxLines="3" android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textSize="14sp" android:textSize="14sp"
android:textColor="?attr/colorAccent" 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." 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" style="@android:style/TextAppearance.StatusBar.EventContent"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ellipsize="end" android:ellipsize="marquee"
android:maxLines="1" android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:textSize="12sp" android:textSize="12sp"
tools:text="Duis posuere arcu condimentum lobortis mattis."/> tools:text="Duis posuere arcu condimentum lobortis mattis."/>
</LinearLayout> </LinearLayout>
@ -100,11 +106,12 @@
android:id="@+id/progress_bar" android:id="@+id/progress_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@+id/playback_controls" android:layout_alignParentBottom="true"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingLeft="16dp" android:paddingLeft="12dp"
android:paddingRight="16dp"> android:paddingRight="12dp"
android:background="@drawable/player_controls_bg">
<TextView <TextView
android:id="@+id/current_time" android:id="@+id/current_time"
@ -124,8 +131,10 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp" android:paddingBottom="4dp"
android:paddingTop="8dp" android:paddingTop="6dp"
tools:progress="25" tools:progress="25"
tools:secondaryProgress="50"/> tools:secondaryProgress="50"/>
@ -143,72 +152,71 @@
<RelativeLayout <RelativeLayout
android:id="@+id/playback_controls" android:id="@+id/playback_controls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="wrap_content"
android:paddingTop="10dp" android:layout_above="@+id/progress_bar"
android:layout_alignParentBottom="true"
android:orientation="horizontal" android:orientation="horizontal"
android:background="@drawable/player_controls_bg"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<TextView <TextView
android:id="@+id/control_playback_speed" android:id="@+id/control_playback_speed"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginLeft="2dp" android:layout_marginLeft="5dp"
android:layout_marginRight="2dp" android:layout_marginRight="5dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toLeftOf="@+id/control_repeat" android:layout_toLeftOf="@+id/control_repeat"
android:gravity="center" android:gravity="center"
android:minWidth="50dp" android:minWidth="50dp"
android:text="1x" android:text="1x"
android:textColor="@android:color/white" android:textColor="?attr/colorAccent"
android:textStyle="bold" android:textStyle="bold"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded"/> tools:ignore="HardcodedText,RtlHardcoded"/>
<ImageButton <ImageButton
android:id="@+id/control_repeat" android:id="@+id/control_repeat"
android:layout_width="25dp" android:layout_width="30dp"
android:layout_height="25dp" android:layout_height="30dp"
android:layout_toLeftOf="@+id/control_backward" android:layout_toLeftOf="@+id/control_backward"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitXY" android:scaleType="fitXY"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_repeat_white" android:src="@drawable/ic_repeat_white"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
<ImageButton <ImageButton
android:id="@+id/control_backward" android:id="@+id/control_backward"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="match_parent" android:layout_height="40dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_toLeftOf="@+id/control_play_pause" android:layout_toLeftOf="@+id/control_play_pause"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:padding="2dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/exo_controls_previous" android:src="@drawable/exo_controls_previous"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
<ImageButton <ImageButton
android:id="@+id/control_play_pause" android:id="@+id/control_play_pause"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="50dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:padding="2dp"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_pause_white" android:src="@drawable/ic_pause_white"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -216,45 +224,49 @@
android:id="@+id/control_progress_bar" android:id="@+id/control_progress_bar"
style="?android:attr/progressBarStyleLargeInverse" style="?android:attr/progressBarStyleLargeInverse"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="50dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_marginLeft="5dp" android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:background="#00000000" android:background="#00000000"
android:tint="?attr/colorAccent"
android:padding="2dp" android:padding="2dp"
android:clickable="false" android:clickable="false"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:indeterminate="true" android:indeterminate="true"
android:visibility="invisible"/> android:visibility="invisible"
tools:visibility="visible"/>
<ImageButton <ImageButton
android:id="@+id/control_forward" android:id="@+id/control_forward"
android:layout_width="40dp" android:layout_width="40dp"
android:layout_height="match_parent" android:layout_height="40dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/control_play_pause" android:layout_toRightOf="@+id/control_play_pause"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:padding="2dp"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:tint="?attr/colorAccent"
android:src="@drawable/exo_controls_next" android:src="@drawable/exo_controls_next"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
<ImageButton <ImageButton
android:id="@+id/control_shuffle" android:id="@+id/control_shuffle"
android:layout_width="25dp" android:layout_width="30dp"
android:layout_height="25dp" android:layout_height="30dp"
android:layout_toRightOf="@+id/control_forward" android:layout_toRightOf="@+id/control_forward"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:scaleType="fitXY" android:scaleType="fitXY"
android:tint="?attr/colorAccent"
android:src="@drawable/ic_shuffle_white_24dp" android:src="@drawable/ic_shuffle_white_24dp"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
@ -262,14 +274,14 @@
android:id="@+id/control_playback_pitch" android:id="@+id/control_playback_pitch"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="35dp" android:layout_height="35dp"
android:layout_marginLeft="2dp" android:layout_marginLeft="5dp"
android:layout_marginRight="2dp" android:layout_marginRight="5dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_toRightOf="@+id/control_shuffle" android:layout_toRightOf="@+id/control_shuffle"
android:gravity="center" android:gravity="center"
android:minWidth="50dp" android:minWidth="50dp"
android:text="100%" android:text="100%"
android:textColor="@android:color/white" android:textColor="?attr/colorAccent"
android:textStyle="bold" android:textStyle="bold"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
tools:ignore="HardcodedText,RtlHardcoded"/> tools:ignore="HardcodedText,RtlHardcoded"/>

View File

@ -12,8 +12,8 @@
<ImageView <ImageView
android:id="@+id/itemThumbnailView" android:id="@+id/itemThumbnailView"
android:layout_width="62dp" android:layout_width="@dimen/play_queue_thumbnail_width"
android:layout_height="40dp" android:layout_height="@dimen/play_queue_thumbnail_height"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"

View File

@ -20,7 +20,7 @@
android:maxLines="2" android:maxLines="2"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/playlist_detail_title_text_size" 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 <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -89,21 +89,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/play_control" android:id="@+id/play_control"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:layout_below="@+id/playlist_meta"> 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 <Button
android:id="@+id/playlist_play_bg_button" android:id="@+id/playlist_play_bg_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -114,21 +103,40 @@
android:layout_toStartOf="@+id/playlist_play_all_button" android:layout_toStartOf="@+id/playlist_play_all_button"
android:text="@string/controls_background_title" android:text="@string/controls_background_title"
android:textSize="@dimen/channel_rss_title_size" android:textSize="@dimen/channel_rss_title_size"
android:textColor="?attr/colorAccent"
android:theme="@style/RedButton" android:theme="@style/RedButton"
android:drawableLeft="?attr/audio"
android:drawablePadding="4dp"
tools:ignore="RtlHardcoded" tools:ignore="RtlHardcoded"
tools:visibility="visible" /> 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 <Button
android:id="@+id/playlist_play_popup_button" android:id="@+id/playlist_play_popup_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right" android:layout_gravity="center_vertical|right"
android:layout_marginRight="2dp" android:layout_alignParentRight="true"
android:layout_toLeftOf="@+id/playlist_play_bg_button"
android:layout_toStartOf="@+id/playlist_play_bg_button"
android:text="@string/controls_popup_title" android:text="@string/controls_popup_title"
android:textSize="@dimen/channel_rss_title_size" android:textSize="@dimen/channel_rss_title_size"
android:textColor="?attr/colorAccent"
android:theme="@style/RedButton" android:theme="@style/RedButton"
android:drawableLeft="?attr/popup"
android:drawablePadding="4dp"
tools:ignore="RtlHardcoded" tools:ignore="RtlHardcoded"
tools:visibility="visible" /> tools:visibility="visible" />
</RelativeLayout> </RelativeLayout>

View File

@ -67,6 +67,10 @@
<dimen name="playlist_detail_uploader_image_size">24dp</dimen> <dimen name="playlist_detail_uploader_image_size">24dp</dimen>
<dimen name="playlist_detail_uploader_layout_height">28dp</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--> <!-- Kiosk view Dimensions-->
<dimen name="kiosk_title_text_size">30sp</dimen> <dimen name="kiosk_title_text_size">30sp</dimen>
</resources> </resources>

View File

@ -136,9 +136,9 @@
<string name="could_not_get_stream">Could not get any stream</string> <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="could_not_load_image">Could not load image</string>
<string name="app_ui_crash">App/UI crashed</string> <string name="app_ui_crash">App/UI crashed</string>
<string name="player_video_failure">Failed to play this video</string> <string name="player_stream_failure">Failed to play this stream</string>
<string name="player_audio_failure">Failed to play this audio</string> <string name="player_unrecoverable_failure">Unrecoverable player error occurred</string>
<string name="player_unexpected_failure">Unexpected player error occurred</string> <string name="player_recoverable_failure">Recovering from player error</string>
<!-- error activity --> <!-- error activity -->
<string name="sorry_string">Sorry, that should not have happened.</string> <string name="sorry_string">Sorry, that should not have happened.</string>