Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using background player when there are no separate audio streams #9562

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -1666,8 +1666,9 @@ public void handleResult(@NonNull final StreamInfo info) {

binding.detailControlsDownload.setVisibility(
StreamTypeUtil.isLiveStream(info.getStreamType()) ? View.GONE : View.VISIBLE);
binding.detailControlsBackground.setVisibility(info.getAudioStreams().isEmpty()
? View.GONE : View.VISIBLE);
binding.detailControlsBackground.setVisibility(
info.getAudioStreams().isEmpty() && info.getVideoStreams().isEmpty()
? View.GONE : View.VISIBLE);

final boolean noVideoStreams =
info.getVideoStreams().isEmpty() && info.getVideoOnlyStreams().isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import com.google.android.exoplayer2.source.MediaSource;

import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
import org.schabi.newpipe.player.mediaitem.StreamInfoTag;
Expand Down Expand Up @@ -41,22 +43,50 @@ public MediaSource resolve(@NonNull final StreamInfo info) {
return liveSource;
}

final List<AudioStream> audioStreams = getNonTorrentStreams(info.getAudioStreams());

final int index = ListHelper.getDefaultAudioFormat(context, audioStreams);
if (index < 0 || index >= info.getAudioStreams().size()) {
final Stream stream = getAudioSource(info);
if (stream == null) {
return null;
}

final AudioStream audio = info.getAudioStreams().get(index);
final MediaItemTag tag = StreamInfoTag.of(info);

try {
return PlaybackResolver.buildMediaSource(
dataSource, audio, info, PlaybackResolver.cacheKeyOf(info, audio), tag);
dataSource, stream, info, PlaybackResolver.cacheKeyOf(info, stream), tag);
} catch (final ResolverException e) {
Log.e(TAG, "Unable to create audio source", e);
return null;
}
}

/**
* Get a stream to be played as audio. If a service has no separate {@link AudioStream}s we
* use a video stream as audio source to support audio background playback.
*
* @param info of the stream
* @return the audio source to use or null if none could be found
*/
@Nullable
private Stream getAudioSource(@NonNull final StreamInfo info) {
final List<AudioStream> audioStreams = getNonTorrentStreams(info.getAudioStreams());
if (!audioStreams.isEmpty()) {
final int index = ListHelper.getDefaultAudioFormat(context, audioStreams);
return getStreamForIndex(index, audioStreams);
} else {
final List<VideoStream> videoStreams = getNonTorrentStreams(info.getVideoStreams());
if (!videoStreams.isEmpty()) {
final int index = ListHelper.getDefaultResolutionIndex(context, videoStreams);
return getStreamForIndex(index, videoStreams);
}
}
return null;
}

@Nullable
Stream getStreamForIndex(final int index, @NonNull final List<? extends Stream> streams) {
if (index >= 0 && index < streams.size()) {
return streams.get(index);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,26 @@ static String cacheKeyOf(final StreamInfo info, final AudioStream audioStream) {

return cacheKey.toString();
}

/**
* Use common base type {@link Stream} to handle {@link AudioStream} or {@link VideoStream}
* transparently. For more info see {@link #cacheKeyOf(StreamInfo, AudioStream)} or
* {@link #cacheKeyOf(StreamInfo, VideoStream)}.
*
* @param info the {@link StreamInfo stream info}, to distinguish between streams with
* the same features but coming from different stream infos
* @param stream the {@link Stream} ({@link AudioStream} or {@link VideoStream})
* for which the cache key should be created
* @return a key to be used to store the cache of the provided {@link Stream}
*/
static String cacheKeyOf(final StreamInfo info, final Stream stream) {
if (stream instanceof AudioStream) {
return cacheKeyOf(info, (AudioStream) stream);
} else if (stream instanceof VideoStream) {
return cacheKeyOf(info, (VideoStream) stream);
}
throw new RuntimeException("no audio or video stream. That should never happen");
}
//endregion


Expand Down