diff --git a/CHANGELOG.md b/CHANGELOG.md index 5107934f..e182fbf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] +- Support for `Player.isPaused` and `Player.isMuted` + ## [0.13.0] - 2024-11-26 - Introduce platform support for web. - Supported API calls: `loadSource(source)`, `play`, `pause`, `mute`, `unmute`, `seek(time)`, `timeShift(timeShift)`, `getCurrentTime`, `getTimeShift`, `getDuration`, `getMaxTimeShift`, `isLive`, `isPlaying`, `isAirplayActive`, `isAirplayAvailable`, `castVideo`, `castStop`, `isCastAvailable`, `isCasting`, `showAirPlayTargetPicker`, `destroy` diff --git a/android/src/main/kotlin/com/bitmovin/player/flutter/FlutterPlayer.kt b/android/src/main/kotlin/com/bitmovin/player/flutter/FlutterPlayer.kt index 8626e45f..f6d8773d 100644 --- a/android/src/main/kotlin/com/bitmovin/player/flutter/FlutterPlayer.kt +++ b/android/src/main/kotlin/com/bitmovin/player/flutter/FlutterPlayer.kt @@ -92,6 +92,8 @@ class FlutterPlayer( Methods.MAX_TIME_SHIFT -> maxTimeShift Methods.IS_LIVE -> isLive Methods.IS_PLAYING -> isPlaying + Methods.IS_PAUSED -> isPaused + Methods.IS_MUTED -> isMuted Methods.SEND_CUSTOM_DATA_EVENT -> this.analytics?.sendCustomDataEvent(arg.asCustomData.toNative()) ?: Unit diff --git a/android/src/main/kotlin/com/bitmovin/player/flutter/Methods.kt b/android/src/main/kotlin/com/bitmovin/player/flutter/Methods.kt index f62229cc..45f9f390 100644 --- a/android/src/main/kotlin/com/bitmovin/player/flutter/Methods.kt +++ b/android/src/main/kotlin/com/bitmovin/player/flutter/Methods.kt @@ -21,6 +21,8 @@ class Methods { const val MAX_TIME_SHIFT = "maxTimeShift" const val IS_LIVE = "isLive" const val IS_PLAYING = "isPlaying" + const val IS_PAUSED = "isPaused" + const val IS_MUTED = "isMuted" const val SEND_CUSTOM_DATA_EVENT = "sendCustomDataEvent" const val AVAILABLE_SUBTITLES = "availableSubtitles" const val SET_SUBTITLE = "setSubtitle" diff --git a/example/lib/player_info.dart b/example/lib/player_info.dart index be4220ac..edcb8b0c 100644 --- a/example/lib/player_info.dart +++ b/example/lib/player_info.dart @@ -12,7 +12,7 @@ class PlayerInfo extends StatefulWidget { } class PlayerInfoState extends State { - final Map _data = {}; + final Map _data = {}; Future updatePlayerInfo(Player player, Event event) async { if (event is ReadyEvent) { @@ -41,6 +41,10 @@ class PlayerInfoState extends State { } if (event is PlayingEvent || event is PausedEvent) { _updatePlayerInfoForField('isPlaying', player.isPlaying); + _updatePlayerInfoForField('isPaused', player.isPaused); + } + if (event is MutedEvent || event is UnmutedEvent) { + _updatePlayerInfoForField('isMuted', player.isMuted); } if (event is TimeChangedEvent) { _updatePlayerInfoForField('currentTime', player.currentTime); @@ -63,8 +67,13 @@ class PlayerInfoState extends State { void _updatePlayerInfoForField(String field, Future value) { value.then((dynamic value) { + var valueString = value.toString(); + if (value is double) { + valueString = value.toStringAsFixed(2); + } + setState(() { - _data[field] = value.toString(); + _data[field] = valueString; }); }); } @@ -75,7 +84,7 @@ class PlayerInfoState extends State { itemCount: _data.length, itemBuilder: (context, index) { final key = _data.keys.elementAt(index); - final value = _data[key]; + final value = _data[key]!; return Padding( padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 1), @@ -87,7 +96,7 @@ class PlayerInfoState extends State { ), Expanded( flex: 3, - child: Text(value.toString()), + child: Text(value), ), ], ), diff --git a/ios/Classes/FlutterPlayer.swift b/ios/Classes/FlutterPlayer.swift index 09ca65a6..bebfa9d8 100644 --- a/ios/Classes/FlutterPlayer.swift +++ b/ios/Classes/FlutterPlayer.swift @@ -117,6 +117,10 @@ private extension FlutterPlayer { return player.isLive case (Methods.isPlaying, .empty): return player.isPlaying + case (Methods.isPaused, .empty): + return player.isPaused + case (Methods.isMuted, .empty): + return player.isMuted case (Methods.destroy, .empty): destroyPlayer() case (Methods.sendCustomDataEvent, .json(let customDataJson)): diff --git a/ios/Classes/Methods.swift b/ios/Classes/Methods.swift index 5d7b8fad..28d43393 100644 --- a/ios/Classes/Methods.swift +++ b/ios/Classes/Methods.swift @@ -18,6 +18,8 @@ internal enum Methods { static let maxTimeShift = "maxTimeShift" static let isLive = "isLive" static let isPlaying = "isPlaying" + static let isPaused = "isPaused" + static let isMuted = "isMuted" static let sendCustomDataEvent = "sendCustomDataEvent" static let availableSubtitles = "availableSubtitles" static let getSubtitle = "getSubtitle" diff --git a/lib/src/api/player/player_api.dart b/lib/src/api/player/player_api.dart index 02f9547f..12812310 100644 --- a/lib/src/api/player/player_api.dart +++ b/lib/src/api/player/player_api.dart @@ -65,6 +65,13 @@ abstract class PlayerApi { /// not paused. Future get isPlaying; + /// Whether the player is currently paused, i.e. has started playback but is + /// currently paused. + Future get isPaused; + + /// Whether the player is muted. + Future get isMuted; + /// A list of all available [SubtitleTrack]s of the active [Source], /// including "off" subtitle track. Future> get availableSubtitles; diff --git a/lib/src/methods.dart b/lib/src/methods.dart index c5b0be59..56157173 100644 --- a/lib/src/methods.dart +++ b/lib/src/methods.dart @@ -16,6 +16,8 @@ class Methods { static const String maxTimeShift = 'maxTimeShift'; static const String isLive = 'isLive'; static const String isPlaying = 'isPlaying'; + static const String isPaused = 'isPaused'; + static const String isMuted = 'isMuted'; static const String sendCustomDataEvent = 'sendCustomDataEvent'; static const String availableSubtitles = 'availableSubtitles'; static const String setSubtitle = 'setSubtitle'; diff --git a/lib/src/platform/player_platform_method_channel.dart b/lib/src/platform/player_platform_method_channel.dart index c08a01e6..ea6106bb 100644 --- a/lib/src/platform/player_platform_method_channel.dart +++ b/lib/src/platform/player_platform_method_channel.dart @@ -197,6 +197,12 @@ class PlayerPlatformMethodChannel extends PlayerPlatformInterface { @override Future get isPlaying async => _invokeMethod(Methods.isPlaying); + @override + Future get isPaused async => _invokeMethod(Methods.isPaused); + + @override + Future get isMuted async => _invokeMethod(Methods.isMuted); + @override Future loadSource(Source source) async { await super.loadSource(source); diff --git a/lib/src/platform/web/bitmovin_player_web_api.dart b/lib/src/platform/web/bitmovin_player_web_api.dart index f06018ec..f6215aa3 100644 --- a/lib/src/platform/web/bitmovin_player_web_api.dart +++ b/lib/src/platform/web/bitmovin_player_web_api.dart @@ -19,6 +19,8 @@ class BitmovinPlayerJs { external void castVideo(); external void castStop(); external bool isPlaying(); + external bool isPaused(); + external bool isMuted(); external bool isLive(); external bool isCasting(); external bool isCastAvailable(); diff --git a/lib/src/platform/web/player_platform_web.dart b/lib/src/platform/web/player_platform_web.dart index c3ed1056..da80ee95 100644 --- a/lib/src/platform/web/player_platform_web.dart +++ b/lib/src/platform/web/player_platform_web.dart @@ -75,6 +75,12 @@ class PlayerPlatformWeb extends PlayerPlatformInterface { @override Future get isPlaying async => _player.isPlaying(); + @override + Future get isPaused async => _player.isPaused(); + + @override + Future get isMuted async => _player.isMuted(); + @override Future loadSource(Source source) async { await super.loadSource(source); diff --git a/lib/src/player.dart b/lib/src/player.dart index 3e2b41f7..d21e1f65 100644 --- a/lib/src/player.dart +++ b/lib/src/player.dart @@ -81,6 +81,12 @@ class Player with PlayerEventHandler implements PlayerApi { @override Future get isPlaying async => _playerPlatformInterface.isPlaying; + @override + Future get isPaused async => _playerPlatformInterface.isPaused; + + @override + Future get isMuted async => _playerPlatformInterface.isMuted; + @override Future> get availableSubtitles async => _playerPlatformInterface.availableSubtitles;