Add playback event stream to platform interface.
This commit is contained in:
parent
ab6c8b2a8a
commit
3a44f844e2
|
@ -46,6 +46,7 @@ abstract class JustAudioPlatform extends PlatformInterface {
|
||||||
/// A nested platform interface for communicating with a particular player
|
/// A nested platform interface for communicating with a particular player
|
||||||
/// instance.
|
/// instance.
|
||||||
abstract class AudioPlayerPlatform {
|
abstract class AudioPlayerPlatform {
|
||||||
|
Stream<PlaybackEventMessage> get playbackEventMessageStream;
|
||||||
Future<LoadResponse> load(LoadRequest request);
|
Future<LoadResponse> load(LoadRequest request);
|
||||||
Future<PlayResponse> play(PlayRequest request);
|
Future<PlayResponse> play(PlayRequest request);
|
||||||
Future<PauseResponse> pause(PauseRequest request);
|
Future<PauseResponse> pause(PauseRequest request);
|
||||||
|
@ -68,6 +69,112 @@ abstract class AudioPlayerPlatform {
|
||||||
ConcatenatingMoveRequest request);
|
ConcatenatingMoveRequest request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PlaybackEventMessage {
|
||||||
|
final ProcessingStateMessage processingState;
|
||||||
|
final DateTime updateTime;
|
||||||
|
final Duration updatePosition;
|
||||||
|
final Duration bufferedPosition;
|
||||||
|
final Duration duration;
|
||||||
|
final IcyMetadataMessage icyMetadata;
|
||||||
|
final int currentIndex;
|
||||||
|
final int androidAudioSessionId;
|
||||||
|
|
||||||
|
PlaybackEventMessage({
|
||||||
|
@required this.processingState,
|
||||||
|
@required this.updateTime,
|
||||||
|
@required this.updatePosition,
|
||||||
|
@required this.bufferedPosition,
|
||||||
|
@required this.duration,
|
||||||
|
@required this.icyMetadata,
|
||||||
|
@required this.currentIndex,
|
||||||
|
@required this.androidAudioSessionId,
|
||||||
|
});
|
||||||
|
|
||||||
|
static PlaybackEventMessage fromMap(Map<dynamic, dynamic> map) =>
|
||||||
|
PlaybackEventMessage(
|
||||||
|
processingState: ProcessingStateMessage.values[map['processingState']],
|
||||||
|
updateTime: DateTime.fromMillisecondsSinceEpoch(map['updateTime']),
|
||||||
|
// TODO: Ensure all platforms pass a microsecond value.
|
||||||
|
updatePosition: Duration(microseconds: map['updatePosition']),
|
||||||
|
// TODO: Ensure all platforms pass a microsecond value.
|
||||||
|
bufferedPosition: Duration(microseconds: map['bufferedPosition']),
|
||||||
|
// TODO: Ensure all platforms pass a microsecond value.
|
||||||
|
duration: map['duration'] == null || map['duration'] < 0
|
||||||
|
? null
|
||||||
|
: Duration(microseconds: map['duration']),
|
||||||
|
icyMetadata: map['icyMetadata'] == null
|
||||||
|
? null
|
||||||
|
: IcyMetadataMessage.fromMap(map['icyMetadata']),
|
||||||
|
currentIndex: map['currentIndex'],
|
||||||
|
androidAudioSessionId: map['androidAudioSessionId'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ProcessingStateMessage {
|
||||||
|
none,
|
||||||
|
loading,
|
||||||
|
buffering,
|
||||||
|
ready,
|
||||||
|
completed,
|
||||||
|
}
|
||||||
|
|
||||||
|
class IcyMetadataMessage {
|
||||||
|
final IcyInfoMessage info;
|
||||||
|
final IcyHeadersMessage headers;
|
||||||
|
|
||||||
|
IcyMetadataMessage({
|
||||||
|
@required this.info,
|
||||||
|
@required this.headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
static IcyMetadataMessage fromMap(Map<dynamic, dynamic> json) =>
|
||||||
|
IcyMetadataMessage(
|
||||||
|
info:
|
||||||
|
json['info'] == null ? null : IcyInfoMessage.fromMap(json['info']),
|
||||||
|
headers: json['headers'] == null
|
||||||
|
? null
|
||||||
|
: IcyHeadersMessage.fromMap(json['headers']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class IcyInfoMessage {
|
||||||
|
final String title;
|
||||||
|
final String url;
|
||||||
|
|
||||||
|
IcyInfoMessage({@required this.title, @required this.url});
|
||||||
|
|
||||||
|
static IcyInfoMessage fromMap(Map<dynamic, dynamic> json) =>
|
||||||
|
IcyInfoMessage(title: json['title'], url: json['url']);
|
||||||
|
}
|
||||||
|
|
||||||
|
class IcyHeadersMessage {
|
||||||
|
final int bitrate;
|
||||||
|
final String genre;
|
||||||
|
final String name;
|
||||||
|
final int metadataInterval;
|
||||||
|
final String url;
|
||||||
|
final bool isPublic;
|
||||||
|
|
||||||
|
IcyHeadersMessage({
|
||||||
|
@required this.bitrate,
|
||||||
|
@required this.genre,
|
||||||
|
@required this.name,
|
||||||
|
@required this.metadataInterval,
|
||||||
|
@required this.url,
|
||||||
|
@required this.isPublic,
|
||||||
|
});
|
||||||
|
|
||||||
|
static IcyHeadersMessage fromMap(Map<dynamic, dynamic> json) =>
|
||||||
|
IcyHeadersMessage(
|
||||||
|
bitrate: json['bitrate'],
|
||||||
|
genre: json['genre'],
|
||||||
|
name: json['name'],
|
||||||
|
metadataInterval: json['metadataInterval'],
|
||||||
|
url: json['url'],
|
||||||
|
isPublic: json['isPublic'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
class InitRequest {
|
class InitRequest {
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
|
@ -344,6 +451,7 @@ class ProgressiveAudioSourceMessage extends UriAudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'progressive',
|
||||||
'id': id,
|
'id': id,
|
||||||
'uri': uri,
|
'uri': uri,
|
||||||
'headers': headers,
|
'headers': headers,
|
||||||
|
@ -359,6 +467,7 @@ class DashAudioSourceMessage extends UriAudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'dash',
|
||||||
'id': id,
|
'id': id,
|
||||||
'uri': uri,
|
'uri': uri,
|
||||||
'headers': headers,
|
'headers': headers,
|
||||||
|
@ -374,6 +483,7 @@ class HlsAudioSourceMessage extends UriAudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'hls',
|
||||||
'id': id,
|
'id': id,
|
||||||
'uri': uri,
|
'uri': uri,
|
||||||
'headers': headers,
|
'headers': headers,
|
||||||
|
@ -392,7 +502,9 @@ class ConcatenatingAudioSourceMessage extends AudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'concatenating',
|
||||||
'id': id,
|
'id': id,
|
||||||
|
// TODO: ensure platform implementation uses this key
|
||||||
'children': children.map((child) => child.toMap()).toList(),
|
'children': children.map((child) => child.toMap()).toList(),
|
||||||
'useLazyPreparation': useLazyPreparation,
|
'useLazyPreparation': useLazyPreparation,
|
||||||
};
|
};
|
||||||
|
@ -412,9 +524,13 @@ class ClippingAudioSourceMessage extends IndexedAudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'clipping',
|
||||||
'id': id,
|
'id': id,
|
||||||
|
// TODO: ensure platform implementation uses this key
|
||||||
'child': child.toMap(),
|
'child': child.toMap(),
|
||||||
|
// TODO: ensure platform implementation interprets in Us.
|
||||||
'start': start.inMicroseconds,
|
'start': start.inMicroseconds,
|
||||||
|
// TODO: ensure platform implementation interprets in Us.
|
||||||
'end': end.inMicroseconds,
|
'end': end.inMicroseconds,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -431,7 +547,9 @@ class LoopingAudioSourceMessage extends AudioSourceMessage {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
|
'type': 'looping',
|
||||||
'id': id,
|
'id': id,
|
||||||
|
// TODO: ensure platform implementation uses this key
|
||||||
'child': child.toMap(),
|
'child': child.toMap(),
|
||||||
'count': count,
|
'count': count,
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,94 +22,101 @@ class MethodChannelAudioPlayer extends AudioPlayerPlatform {
|
||||||
MethodChannelAudioPlayer(this.id)
|
MethodChannelAudioPlayer(this.id)
|
||||||
: _channel = MethodChannel('com.ryanheise.just_audio.methods.$id');
|
: _channel = MethodChannel('com.ryanheise.just_audio.methods.$id');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<PlaybackEventMessage> get playbackEventMessageStream =>
|
||||||
|
EventChannel('com.ryanheise.just_audio.events.$id')
|
||||||
|
.receiveBroadcastStream()
|
||||||
|
.map((map) => PlaybackEventMessage.fromMap(map));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LoadResponse> load(LoadRequest request) async {
|
Future<LoadResponse> load(LoadRequest request) async {
|
||||||
return (await _channel.invokeMethod('load', request?.toMap()))?.fromMap();
|
return LoadResponse.fromMap(
|
||||||
|
await _channel.invokeMethod('load', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PlayResponse> play(PlayRequest request) async {
|
Future<PlayResponse> play(PlayRequest request) async {
|
||||||
return (await _channel.invokeMethod('play', request?.toMap()))?.fromMap();
|
return PlayResponse.fromMap(
|
||||||
|
await _channel.invokeMethod('play', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PauseResponse> pause(PauseRequest request) async {
|
Future<PauseResponse> pause(PauseRequest request) async {
|
||||||
return (await _channel.invokeMethod('pause', request?.toMap()))?.fromMap();
|
return PauseResponse.fromMap(
|
||||||
|
await _channel.invokeMethod('pause', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetVolumeResponse> setVolume(SetVolumeRequest request) async {
|
Future<SetVolumeResponse> setVolume(SetVolumeRequest request) async {
|
||||||
return (await _channel.invokeMethod('setVolume', request?.toMap()))
|
return SetVolumeResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('setVolume', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetSpeedResponse> setSpeed(SetSpeedRequest request) async {
|
Future<SetSpeedResponse> setSpeed(SetSpeedRequest request) async {
|
||||||
return (await _channel.invokeMethod('setSpeed', request?.toMap()))
|
return SetSpeedResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('setSpeed', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetLoopModeResponse> setLoopMode(SetLoopModeRequest request) async {
|
Future<SetLoopModeResponse> setLoopMode(SetLoopModeRequest request) async {
|
||||||
return (await _channel.invokeMethod('setLoopMode', request?.toMap()))
|
return SetLoopModeResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('setLoopMode', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetShuffleModeResponse> setShuffleMode(
|
Future<SetShuffleModeResponse> setShuffleMode(
|
||||||
SetShuffleModeRequest request) async {
|
SetShuffleModeRequest request) async {
|
||||||
return (await _channel.invokeMethod('setShuffleMode', request?.toMap()))
|
return SetShuffleModeResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('setShuffleMode', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetAutomaticallyWaitsToMinimizeStallingResponse>
|
Future<SetAutomaticallyWaitsToMinimizeStallingResponse>
|
||||||
setAutomaticallyWaitsToMinimizeStalling(
|
setAutomaticallyWaitsToMinimizeStalling(
|
||||||
SetAutomaticallyWaitsToMinimizeStallingRequest request) async {
|
SetAutomaticallyWaitsToMinimizeStallingRequest request) async {
|
||||||
return (await _channel.invokeMethod(
|
return SetAutomaticallyWaitsToMinimizeStallingResponse.fromMap(
|
||||||
'setAutomaticallyWaitsToMinimizeStalling', request?.toMap()))
|
await _channel.invokeMethod(
|
||||||
?.fromMap();
|
'setAutomaticallyWaitsToMinimizeStalling', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SeekResponse> seek(SeekRequest request) async {
|
Future<SeekResponse> seek(SeekRequest request) async {
|
||||||
return (await _channel.invokeMethod('seek', request?.toMap()))?.fromMap();
|
return SeekResponse.fromMap(
|
||||||
|
await _channel.invokeMethod('seek', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SetAndroidAudioAttributesResponse> setAndroidAudioAttributes(
|
Future<SetAndroidAudioAttributesResponse> setAndroidAudioAttributes(
|
||||||
SetAndroidAudioAttributesRequest request) async {
|
SetAndroidAudioAttributesRequest request) async {
|
||||||
return (await _channel.invokeMethod(
|
return SetAndroidAudioAttributesResponse.fromMap(await _channel
|
||||||
'setAndroidAudioAttributes', request?.toMap()))
|
.invokeMethod('setAndroidAudioAttributes', request?.toMap()));
|
||||||
?.fromMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<DisposeResponse> dispose(DisposeRequest request) async {
|
Future<DisposeResponse> dispose(DisposeRequest request) async {
|
||||||
return (await _channel.invokeMethod('dispose', request?.toMap()))
|
return DisposeResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('dispose', request?.toMap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ConcatenatingInsertAllResponse> concatenatingInsertAll(
|
Future<ConcatenatingInsertAllResponse> concatenatingInsertAll(
|
||||||
ConcatenatingInsertAllRequest request) async {
|
ConcatenatingInsertAllRequest request) async {
|
||||||
return (await _channel.invokeMethod(
|
return ConcatenatingInsertAllResponse.fromMap(await _channel.invokeMethod(
|
||||||
'concatenatingInsertAll', request?.toMap()))
|
'concatenatingInsertAll', request?.toMap()));
|
||||||
?.fromMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ConcatenatingRemoveRangeResponse> concatenatingRemoveRange(
|
Future<ConcatenatingRemoveRangeResponse> concatenatingRemoveRange(
|
||||||
ConcatenatingRemoveRangeRequest request) async {
|
ConcatenatingRemoveRangeRequest request) async {
|
||||||
return (await _channel.invokeMethod(
|
return ConcatenatingRemoveRangeResponse.fromMap(await _channel.invokeMethod(
|
||||||
'concatenatingRemoveRange', request?.toMap()))
|
'concatenatingRemoveRange', request?.toMap()));
|
||||||
?.fromMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<ConcatenatingMoveResponse> concatenatingMove(
|
Future<ConcatenatingMoveResponse> concatenatingMove(
|
||||||
ConcatenatingMoveRequest request) async {
|
ConcatenatingMoveRequest request) async {
|
||||||
return (await _channel.invokeMethod('concatenatingMove', request?.toMap()))
|
return ConcatenatingMoveResponse.fromMap(
|
||||||
?.fromMap();
|
await _channel.invokeMethod('concatenatingMove', request?.toMap()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue