From e134bbbac9bb44da3b42e556656844dac83d4900 Mon Sep 17 00:00:00 2001 From: Mario Graf Date: Thu, 21 Nov 2024 18:27:34 +0100 Subject: [PATCH] PoC for web event handling --- .../platform/web/bitmovin_player_web_api.dart | 18 +++++++++++++++ lib/src/platform/web/conversion.dart | 16 +++++++++++++ lib/src/platform/web/player_platform_web.dart | 23 +++++++++++++++++-- lib/src/player_event_handler.dart | 13 ++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/lib/src/platform/web/bitmovin_player_web_api.dart b/lib/src/platform/web/bitmovin_player_web_api.dart index 704884fd..e46f8080 100644 --- a/lib/src/platform/web/bitmovin_player_web_api.dart +++ b/lib/src/platform/web/bitmovin_player_web_api.dart @@ -27,6 +27,7 @@ class BitmovinPlayerJs { external double getCurrentTime(); external double getDuration(); external double getMaxTimeShift(); + external void on(String event, Function handler); } @JS() @@ -52,3 +53,20 @@ class SourceJs { external String? get hls; external String? get poster; } + +@JS('bitmovin.player.PlaybackEvent') +class PlaybackEventJs { + external String get issuer; + external double get time; + external int get timestamp; + external String get type; +} + +@JS('bitmovin.player.SeekEvent') +class SeekEventJs { + external String get issuer; + external double get position; + external double get seekTarget; + external int get timestamp; + external String get type; +} diff --git a/lib/src/platform/web/conversion.dart b/lib/src/platform/web/conversion.dart index 1cfa2e20..93a845fe 100644 --- a/lib/src/platform/web/conversion.dart +++ b/lib/src/platform/web/conversion.dart @@ -20,3 +20,19 @@ extension SourceToJs on Source { return sourceConfig.type == SourceType.hls ? sourceConfig.url : null; } } + +extension SeekEventFromJs on SeekEventJs { + SeekEvent toSeekEvent(Source source) { + return SeekEvent( + from: SeekPosition(source: source, time: position), + to: SeekPosition(source: source, time: seekTarget), + timestamp: timestamp, + ); + } +} + +extension PlayEventFromJs on PlaybackEventJs { + PlayEvent toPlayEvent() { + return PlayEvent(time: time, timestamp: timestamp); + } +} diff --git a/lib/src/platform/web/player_platform_web.dart b/lib/src/platform/web/player_platform_web.dart index 3cb8fd06..beb4ce53 100644 --- a/lib/src/platform/web/player_platform_web.dart +++ b/lib/src/platform/web/player_platform_web.dart @@ -4,6 +4,7 @@ import 'package:bitmovin_player/bitmovin_player.dart'; import 'package:bitmovin_player/src/platform/player_platform_interface.dart'; import 'package:bitmovin_player/src/platform/web/bitmovin_player_web_api.dart'; import 'package:bitmovin_player/src/platform/web/conversion.dart'; +import 'package:js/js.dart'; import 'package:web/web.dart'; /// An implementation of [PlayerPlatformInterface] that uses method channels. @@ -20,6 +21,11 @@ class PlayerPlatformWeb extends PlayerPlatformInterface { key: config.key ?? '', ), ); + + // ignore: inference_failure_on_untyped_parameter + _player + ..on('play', allowInterop(_onPlaybackEvent)) + ..on('seek', allowInterop(_onSeekEvent)); } /// Unique identifier for this player instance. @@ -29,11 +35,23 @@ class PlayerPlatformWeb extends PlayerPlatformInterface { @override final PlayerConfig config; - // ignore: unused_field final void Function(dynamic event) _onPlatformEvent; - // ignore: unused_field late BitmovinPlayerJs _player; + Source? _currentSource; + + void _onPlaybackEvent(PlaybackEventJs event) { + _onPlatformEvent(event.toPlayEvent()); + } + + void _onSeekEvent(SeekEventJs event) { + final currentSource = _currentSource; + if (currentSource == null) { + return; + } + + _onPlatformEvent(event.toSeekEvent(currentSource)); + } Element _createContainer() { final div = document.createElement('div') as HTMLDivElement @@ -81,6 +99,7 @@ class PlayerPlatformWeb extends PlayerPlatformInterface { @override Future loadSource(Source source) async { + _currentSource = source; await super.loadSource(source); _player.load(source.toSourceJs()); } diff --git a/lib/src/player_event_handler.dart b/lib/src/player_event_handler.dart index f60d6dbb..6b23c64e 100644 --- a/lib/src/player_event_handler.dart +++ b/lib/src/player_event_handler.dart @@ -24,11 +24,22 @@ mixin PlayerEventHandler implements PlayerListener { /// deserializes it to a typed event object and emits it to the corresponding /// event listener. void onPlatformEvent(dynamic event) { - if (event == null || event is! String) { + if (event == null) { _logger.e('Received event is null'); return; } + // TODO(mario): This is a temporary workaround. Find a better way. + if (event is Event) { + emit(event); + return; + } + + if (event is! String) { + _logger.e('Received event is not a JSON String'); + return; + } + final target = jsonDecode(event) as Map; final eventName = target['event']; final data = target['data'];