mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 21:56:18 -08:00
feat(playback): add embedded mpv series navigation
This commit is contained in:
1 parent
c93b0b4a77
commit
4e30289293
24 files changed
+1045
-13
No files matched your search
@@ -70,6 +70,7 @@ enum class SessionStatus {
|
||||
Loading,
|
||||
Playing,
|
||||
Paused,
|
||||
Ended,
|
||||
Error,
|
||||
Closed,
|
||||
};
|
||||
@@ -157,6 +158,8 @@ std::string toStatusString(SessionStatus status)
|
||||
return "playing";
|
||||
case SessionStatus::Paused:
|
||||
return "paused";
|
||||
case SessionStatus::Ended:
|
||||
return "ended";
|
||||
case SessionStatus::Error:
|
||||
return "error";
|
||||
case SessionStatus::Closed:
|
||||
@@ -1128,6 +1131,11 @@ void runEventLoop(const std::shared_ptr<Session>& session)
|
||||
endFile->error < 0
|
||||
? mpv_error_string(endFile->error)
|
||||
: "Playback failed.";
|
||||
} else if (
|
||||
endFile &&
|
||||
endFile->reason == MPV_END_FILE_REASON_EOF &&
|
||||
session->running.load()) {
|
||||
session->snapshot.status = SessionStatus::Ended;
|
||||
} else if (session->running.load()) {
|
||||
session->snapshot.status = SessionStatus::Idle;
|
||||
}
|
||||
@@ -1163,6 +1171,7 @@ void runEventLoop(const std::shared_ptr<Session>& session)
|
||||
property->data) {
|
||||
session->paused = *static_cast<int*>(property->data) != 0;
|
||||
if (session->snapshot.status != SessionStatus::Loading &&
|
||||
session->snapshot.status != SessionStatus::Ended &&
|
||||
session->snapshot.status != SessionStatus::Error &&
|
||||
session->loadedPath) {
|
||||
session->snapshot.status = session->paused
|
||||
@@ -1912,6 +1921,7 @@ Napi::Value SetPaused(const Napi::CallbackInfo& info)
|
||||
std::lock_guard<std::mutex> lock(session->mutex);
|
||||
session->paused = paused != 0;
|
||||
if (session->loadedPath &&
|
||||
session->snapshot.status != SessionStatus::Ended &&
|
||||
session->snapshot.status != SessionStatus::Error) {
|
||||
session->snapshot.status = session->paused
|
||||
? SessionStatus::Paused
|
||||
|
||||
@@ -45,4 +45,26 @@ describe('Embedded MPV native source recording invariants', () => {
|
||||
);
|
||||
expect(body).toContain('stopRecordingRequestId,');
|
||||
});
|
||||
|
||||
it('maps successful MPV end-file events to an ended session status', () => {
|
||||
expect(nativeSource).toContain('Ended,');
|
||||
expect(nativeSource).toContain('case SessionStatus::Ended:');
|
||||
|
||||
const eventLoopBodyStart = nativeSource.indexOf('void runEventLoop(');
|
||||
expect(eventLoopBodyStart).toBeGreaterThanOrEqual(0);
|
||||
const endFileCaseStart = nativeSource.indexOf(
|
||||
'case MPV_EVENT_END_FILE',
|
||||
eventLoopBodyStart
|
||||
);
|
||||
expect(endFileCaseStart).toBeGreaterThanOrEqual(0);
|
||||
const nextCaseStart = nativeSource.indexOf(
|
||||
'case MPV_EVENT_PROPERTY_CHANGE',
|
||||
endFileCaseStart
|
||||
);
|
||||
expect(nextCaseStart).toBeGreaterThan(endFileCaseStart);
|
||||
|
||||
const endFileCase = nativeSource.slice(endFileCaseStart, nextCaseStart);
|
||||
expect(endFileCase).toContain('SessionStatus::Ended');
|
||||
expect(endFileCase).toContain('MPV_END_FILE_REASON_EOF');
|
||||
});
|
||||
});
|
||||
@@ -197,6 +197,17 @@ describe('EmbeddedMpvNativeService power blocker', () => {
|
||||
expect(powerSaveBlockerMock.stop).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('releases the blocker when MPV reports playback ended', () => {
|
||||
startSession('s1', snapshot('playing'));
|
||||
expect(powerSaveBlockerMock.start).toHaveBeenCalledTimes(1);
|
||||
|
||||
addon.getSessionSnapshot.mockReturnValueOnce(snapshot('ended'));
|
||||
service.setPaused('s1', false);
|
||||
|
||||
expect(powerSaveBlockerMock.stop).toHaveBeenCalledTimes(1);
|
||||
expect(powerSaveBlockerMock.stop).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('keeps the blocker held while any other session is still playing', () => {
|
||||
startSession('s1', snapshot('playing'));
|
||||
startSession('s2', snapshot('playing'));
|
||||
|
||||
Reference in new issue
Block a user