Save playback state even if stream is finished and add isFinished()

This commit is contained in:
Stypox 2021-03-26 11:27:25 +01:00
parent e846f69e38
commit 360f5ac6f7
No known key found for this signature in database
GPG Key ID: 4BDF1B40A49FDD23
4 changed files with 38 additions and 13 deletions

View File

@ -10,6 +10,7 @@ import io.reactivex.rxjava3.core.Flowable
import org.schabi.newpipe.database.feed.model.FeedEntity
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity
import org.schabi.newpipe.database.stream.StreamWithState
import org.schabi.newpipe.database.stream.model.StreamStateEntity
import org.schabi.newpipe.database.subscription.SubscriptionEntity
import java.time.OffsetDateTime
@ -79,6 +80,9 @@ abstract class FeedDAO {
WHERE (
sh.stream_id IS NULL
OR sst.stream_id IS NULL
OR sst.progress_time < s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
OR sst.progress_time < s.duration * 1000 * 3 / 4
OR s.stream_type = 'LIVE_STREAM'
OR s.stream_type = 'AUDIO_LIVE_STREAM'
)

View File

@ -5,8 +5,6 @@ import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import java.util.concurrent.TimeUnit;
import static androidx.room.ForeignKey.CASCADE;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
@ -30,11 +28,13 @@ public class StreamStateEntity {
/**
* Playback state will not be saved, if playback time is less than this threshold.
*/
private static final int PLAYBACK_SAVE_THRESHOLD_START_SECONDS = 5;
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000; // 5000ms = 5s
/**
* Playback state will not be saved, if time left is less than this threshold.
* @see #isFinished(long)
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
*/
private static final int PLAYBACK_SAVE_THRESHOLD_END_SECONDS = 10;
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000; // 60000ms = 60s
@ColumnInfo(name = JOIN_STREAM_ID)
private long streamUid;
@ -63,10 +63,27 @@ public class StreamStateEntity {
this.progressTime = progressTime;
}
public boolean isValid(final int durationInSeconds) {
final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(progressTime);
return seconds > PLAYBACK_SAVE_THRESHOLD_START_SECONDS
&& seconds < durationInSeconds - PLAYBACK_SAVE_THRESHOLD_END_SECONDS;
/**
* The state will be considered valid, and thus be saved, if the progress is more than {@link
* #PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}.
* @return whether this stream state entity should be saved or not
*/
public boolean isValid() {
return progressTime > PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS;
}
/**
* The video will be considered as finished, if the time left is less than {@link
* #PLAYBACK_FINISHED_END_MILLISECONDS} and the progress is at least 3/4 of the video length.
* The state will be saved anyway, so that it can be shown under stream info items, but the
* player will not resume if a state is considered as finished. Finished streams are also the
* ones that can be filtered out in the feed fragment.
* @param durationInSeconds the duration of the stream connected with this state, in seconds
* @return whether the stream is finished or not
*/
public boolean isFinished(final long durationInSeconds) {
return progressTime >= durationInSeconds * 1000 - PLAYBACK_FINISHED_END_MILLISECONDS
&& progressTime >= durationInSeconds * 1000 * 3 / 4;
}
@Override

View File

@ -215,7 +215,7 @@ public class HistoryRecordManager {
.flatMapPublisher(streamStateTable::getState)
.firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(state -> state.isValid((int) queueItem.getDuration()))
.filter(StreamStateEntity::isValid)
.subscribeOn(Schedulers.io());
}
@ -224,7 +224,7 @@ public class HistoryRecordManager {
.flatMapPublisher(streamStateTable::getState)
.firstElement()
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
.filter(state -> state.isValid((int) info.getDuration()))
.filter(StreamStateEntity::isValid)
.subscribeOn(Schedulers.io());
}
@ -232,7 +232,7 @@ public class HistoryRecordManager {
return Completable.fromAction(() -> database.runInTransaction(() -> {
final long streamId = streamTable.upsert(new StreamEntity(info));
final StreamStateEntity state = new StreamStateEntity(streamId, progressTime);
if (state.isValid((int) info.getDuration())) {
if (state.isValid()) {
streamStateTable.upsert(state);
} else {
streamStateTable.deleteState(streamId);

View File

@ -671,7 +671,11 @@ public final class Player implements
//.doFinally()
.subscribe(
state -> {
newQueue.setRecovery(newQueue.getIndex(), state.getProgressTime());
if (!state.isFinished(newQueue.getItem().getDuration())) {
// resume playback only if the stream was not played to the end
newQueue.setRecovery(newQueue.getIndex(),
state.getProgressTime());
}
initPlayback(newQueue, repeatMode, playbackSpeed, playbackPitch,
playbackSkipSilence, playWhenReady, isMuted);
},