Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ ext {
androidxWorkVersion = '2.8.1'

stateSaverVersion = '1.4.1'
exoPlayerVersion = '2.18.7'
exoPlayerVersion = '2.19.1'
googleAutoServiceVersion = '1.1.1'
groupieVersion = '2.10.1'
markwonVersion = '4.6.2'
Expand Down Expand Up @@ -214,7 +214,7 @@ dependencies {
// the corresponding commit hash, since JitPack sometimes deletes artifacts.
// If there’s already a git hash, just add more of it to the end (or remove a letter)
// to cause jitpack to regenerate the artifact.
implementation 'com.github.TeamNewPipe:NewPipeExtractor:68b4c9acbae2d167e7b1209bb6bf0ae086dd427e'
implementation 'com.github.davidasunmo.NewPipeExtractor:NewPipeExtractor:45df3cdb1013370a5ef9d1f9ca0df8a7cf71ebf2'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'

/** Checkstyle **/
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/java/org/schabi/newpipe/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
import org.schabi.newpipe.extractor.utils.ExtractorLogger;
import org.schabi.newpipe.extractor.utils.Logger;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
Expand Down Expand Up @@ -137,6 +139,29 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
if (DEBUG) {
// Override Extractor to print to Logcat
ExtractorLogger.setLogger(new Logger() {
@Override
public void debug(final String tag, final String message) {
Log.d(tag, message);
}

@Override
public void warn(final String tag, final String message) {
Log.w(tag, message);
}

@Override
public void error(final String tag, final String message) {
Log.e(tag, message);
}

@Override
public void error(final String tag, final String message, final Throwable t) {
Log.e(tag, message, t);
}

});
Log.d(TAG, "onCreate() called with: "
+ "savedInstanceState = [" + savedInstanceState + "]");
}
Expand Down
51 changes: 41 additions & 10 deletions app/src/main/java/org/schabi/newpipe/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ public final class Player implements PlaybackListener, Listener {

// audio only mode does not mean that player type is background, but that the player was
// minimized to background but will resume automatically to the original player type
private boolean isAudioOnly = false;
private boolean isPrepared = false;
private boolean isAudioOnly;
private boolean isPrepared;

/*//////////////////////////////////////////////////////////////////////////
// UIs, listeners and disposables
Expand All @@ -239,9 +239,9 @@ public final class Player implements PlaybackListener, Listener {
private BroadcastReceiver broadcastReceiver;
private IntentFilter intentFilter;
@Nullable
private PlayerServiceEventListener fragmentListener = null;
private PlayerServiceEventListener fragmentListener;
@Nullable
private PlayerEventListener activityListener = null;
private PlayerEventListener activityListener;

@NonNull
private final SerialDisposable progressUpdateDisposable = new SerialDisposable();
Expand Down Expand Up @@ -386,7 +386,7 @@ public void handleIntent(@NonNull final Intent intent) {
final boolean playbackSkipSilence = getPrefs().getBoolean(getContext().getString(
R.string.playback_skip_silence_key), getPlaybackSkipSilence());

final boolean samePlayQueue = playQueue != null && playQueue.equalStreamsAndIndex(newQueue);
final boolean samePlayQueue = newQueue.equalStreamsAndIndex(playQueue);
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
final boolean playWhenReady = intent.getBooleanExtra(PLAY_WHEN_READY, true);
final boolean isMuted = intent.getBooleanExtra(IS_MUTED, isMuted());
Expand Down Expand Up @@ -636,7 +636,9 @@ private void setRecovery(final int queuePos, final long windowPos) {
}

if (DEBUG) {
Log.d(TAG, "Setting recovery, queue: " + queuePos + ", pos: " + windowPos);
final var currentTitle = currentItem != null ? currentItem.getTitle() : "";
Log.d(TAG, "Setting recovery, queue: "
+ queuePos + "[" + currentTitle + "], pos: " + windowPos);
}
playQueue.setRecovery(queuePos, windowPos);
}
Expand Down Expand Up @@ -951,6 +953,34 @@ private Disposable getProgressUpdateDisposable() {

//endregion

public static String exoplayerStateToString(final int playbackState) {
return switch (playbackState) {
case com.google.android.exoplayer2.Player.STATE_IDLE -> // 1
"STATE_IDLE";
case com.google.android.exoplayer2.Player.STATE_BUFFERING -> // 2
"STATE_BUFFERING";
case com.google.android.exoplayer2.Player.STATE_READY -> //3
"STATE_READY";
case com.google.android.exoplayer2.Player.STATE_ENDED -> // 4
"STATE_ENDED";
default ->
throw new IllegalArgumentException("Unknown playback state " + playbackState);
};
}

public static String stateToString(final int state) {
return switch (state) {
case STATE_PREFLIGHT -> "STATE_PREFLIGHT";
case STATE_BLOCKED -> "STATE_BLOCKED";
case STATE_PLAYING -> "STATE_PLAYING";
case STATE_BUFFERING -> "STATE_BUFFERING";
case STATE_PAUSED -> "STATE_PAUSED";
case STATE_PAUSED_SEEK -> "STATE_PAUSED_SEEK";
case STATE_COMPLETED -> "STATE_COMPLETED";
default -> throw new IllegalArgumentException("Unknown playback state " + state);
};
}


/*//////////////////////////////////////////////////////////////////////////
// Playback states
Expand All @@ -973,7 +1003,7 @@ public void onPlayWhenReadyChanged(final boolean playWhenReady, final int reason
public void onPlaybackStateChanged(final int playbackState) {
if (DEBUG) {
Log.d(TAG, "ExoPlayer - onPlaybackStateChanged() called with: "
+ "playbackState = [" + playbackState + "]");
+ "playbackState = [" + exoplayerStateToString(playbackState) + "]");
}
updatePlaybackState(getPlayWhenReady(), playbackState);
}
Expand All @@ -982,7 +1012,7 @@ private void updatePlaybackState(final boolean playWhenReady, final int playback
if (DEBUG) {
Log.d(TAG, "ExoPlayer - updatePlaybackState() called with: "
+ "playWhenReady = [" + playWhenReady + "], "
+ "playbackState = [" + playbackState + "]");
+ "playbackState = [" + exoplayerStateToString(playbackState) + "]");
}

if (currentState == STATE_PAUSED_SEEK) {
Expand Down Expand Up @@ -1060,7 +1090,8 @@ public void onPlaybackUnblock(final MediaSource mediaSource) {

public void changeState(final int state) {
if (DEBUG) {
Log.d(TAG, "changeState() called with: state = [" + state + "]");
Log.d(TAG,
"changeState() called with: state = [" + stateToString(state) + "]");
}
currentState = state;
switch (state) {
Expand Down Expand Up @@ -1770,7 +1801,7 @@ private void saveStreamProgressState(final long progressMillis) {
.observeOn(AndroidSchedulers.mainThread())
.doOnError(e -> {
if (DEBUG) {
e.printStackTrace();
Log.e(TAG, "Error saving stream state", e);
}
})
.onErrorComplete()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package org.schabi.newpipe.player.datasource;

import static org.schabi.newpipe.MainActivity.DEBUG;

import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;

import org.schabi.newpipe.DownloaderImpl;

import java.nio.charset.StandardCharsets;
import java.util.Map;

public class LoggingHttpDataSource extends DefaultHttpDataSource {

public final String TAG = getClass().getSimpleName() + "@" + hashCode();

public LoggingHttpDataSource() { }

public LoggingHttpDataSource(@Nullable final String userAgent,
final int connectTimeoutMillis,
final int readTimeoutMillis,
final boolean allowCrossProtocolRedirects,
@Nullable final RequestProperties defaultRequestProperties) {
super(userAgent,
connectTimeoutMillis,
readTimeoutMillis,
allowCrossProtocolRedirects,
defaultRequestProperties);
}


@Override
public long open(final DataSpec dataSpec) throws HttpDataSourceException {
if (!DEBUG) {
return super.open(dataSpec);
}

Log.d(TAG, "Request URL: " + dataSpec.uri);
try {
return super.open(dataSpec);
} catch (final HttpDataSource.InvalidResponseCodeException e) {
Log.e(TAG, "HTTP error for URL: " + dataSpec.uri);
Log.e(TAG, "Response code: " + e.responseCode);
Log.e(TAG, "Headers: " + e.headerFields);
Log.e(TAG, "Body: " + new String(e.responseBody, StandardCharsets.UTF_8));
throw e;
}
}

@SuppressWarnings("checkstyle:hiddenField")
public static class Factory implements HttpDataSource.Factory {

final RequestProperties defaultRequestProperties;

@Nullable
TransferListener transferListener;
@Nullable
String userAgent;
int connectTimeoutMs;
int readTimeoutMs;
boolean allowCrossProtocolRedirects;

public Factory() {
defaultRequestProperties = new RequestProperties();
connectTimeoutMs = DEFAULT_CONNECT_TIMEOUT_MILLIS;
readTimeoutMs = DEFAULT_READ_TIMEOUT_MILLIS;
userAgent = DownloaderImpl.USER_AGENT;
}

@NonNull
@Override
public HttpDataSource createDataSource() {
final var dataSource = new LoggingHttpDataSource(userAgent,
connectTimeoutMs,
readTimeoutMs,
allowCrossProtocolRedirects,
defaultRequestProperties);
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return dataSource;
}

@NonNull
@Override
public Factory setDefaultRequestProperties(
@NonNull final Map<String, String> defaultRequestProperties) {
this.defaultRequestProperties.clearAndSet(defaultRequestProperties);
return this;
}

public Factory setUserAgent(@Nullable final String userAgent) {
this.userAgent = userAgent;
return this;
}

public Factory setConnectTimeoutMs(final int connectTimeoutMs) {
this.connectTimeoutMs = connectTimeoutMs;
return this;
}

public Factory setReadTimeoutMs(final int readTimeoutMs) {
this.readTimeoutMs = readTimeoutMs;
return this;
}

public Factory setAllowCrossProtocolRedirects(final boolean allowCrossProtocolRedirects) {
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
return this;
}

public Factory setTransferListener(@Nullable final TransferListener transferListener) {
this.transferListener = transferListener;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private NonUriHlsDataSourceFactory(@NonNull final DataSource.Factory dataSourceF
* </p>
*
* <p>
* This change allow playback of non-URI HLS contents, when the manifest is not a master
* This change allows playback of non-URI HLS contents, when the manifest is not a master
* manifest/playlist (otherwise, endless loops should be encountered because the
* {@link DataSource}s created for media playlists should use the master playlist response
* instead).
Expand Down
Loading