Initial commit
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import '../../../core/contracts/playback.dart';
|
||||
import '../../../core/domain/ports/emby_gateway.dart';
|
||||
import '../../../shared/utils/app_logger.dart';
|
||||
|
||||
typedef PlaybackReportPayloadBuilder =
|
||||
PlaybackReportPayload Function({required bool isPaused, String? eventName});
|
||||
|
||||
class EmbyPlaybackReporter {
|
||||
EmbyPlaybackReporter({
|
||||
required EmbyGateway gateway,
|
||||
required AuthedRequestContext context,
|
||||
this.enabled = true,
|
||||
}) : _gateway = gateway,
|
||||
_context = context;
|
||||
|
||||
static const _tag = 'Reporter';
|
||||
|
||||
final EmbyGateway _gateway;
|
||||
final AuthedRequestContext _context;
|
||||
|
||||
|
||||
final bool enabled;
|
||||
|
||||
bool _startedReported = false;
|
||||
bool _stoppedReported = false;
|
||||
Timer? _progressTimer;
|
||||
|
||||
bool get startedReported => _startedReported;
|
||||
bool get stoppedReported => _stoppedReported;
|
||||
|
||||
Future<void> reportStarted(PlaybackReportPayload payload) async {
|
||||
if (!enabled) return;
|
||||
if (_startedReported) return;
|
||||
_startedReported = true;
|
||||
try {
|
||||
await _gateway.reportPlaybackStarted(ctx: _context, payload: payload);
|
||||
} catch (e) {
|
||||
AppLogger.warn(_tag, 'Start report failed', e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> reportProgress(PlaybackReportPayload payload) async {
|
||||
if (!_startedReported) return;
|
||||
try {
|
||||
await _gateway.reportPlaybackProgress(ctx: _context, payload: payload);
|
||||
} catch (e) {
|
||||
AppLogger.warn(_tag, 'Progress report failed', e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> reportStopped(PlaybackReportPayload payload) async {
|
||||
if (!enabled) return;
|
||||
if (!_startedReported) {
|
||||
AppLogger.debug(_tag, 'stop report skipped: start not reported');
|
||||
return;
|
||||
}
|
||||
if (_stoppedReported) {
|
||||
AppLogger.debug(_tag, 'stop report skipped: already stopped');
|
||||
return;
|
||||
}
|
||||
_stoppedReported = true;
|
||||
_progressTimer?.cancel();
|
||||
final sw = Stopwatch()..start();
|
||||
try {
|
||||
await _gateway.reportPlaybackStopped(ctx: _context, payload: payload);
|
||||
AppLogger.debug(_tag, 'stop report ok in ${sw.elapsedMilliseconds}ms');
|
||||
} catch (e) {
|
||||
AppLogger.warn(
|
||||
_tag,
|
||||
'Stop report failed after ${sw.elapsedMilliseconds}ms',
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void startProgressTimer(PlaybackReportPayloadBuilder payloadBuilder) {
|
||||
if (!enabled) return;
|
||||
if (_progressTimer != null) return;
|
||||
_progressTimer = Timer.periodic(const Duration(seconds: 8), (_) {
|
||||
if (_startedReported && !_stoppedReported) {
|
||||
unawaited(
|
||||
reportProgress(
|
||||
payloadBuilder(isPaused: false, eventName: 'TimeUpdate'),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_progressTimer?.cancel();
|
||||
_progressTimer = null;
|
||||
_startedReported = false;
|
||||
_stoppedReported = false;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
_progressTimer?.cancel();
|
||||
_progressTimer = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user