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
|
||||
/// instance.
|
||||
abstract class AudioPlayerPlatform {
|
||||
Stream<PlaybackEventMessage> get playbackEventMessageStream;
|
||||
Future<LoadResponse> load(LoadRequest request);
|
||||
Future<PlayResponse> play(PlayRequest request);
|
||||
Future<PauseResponse> pause(PauseRequest request);
|
||||
|
@ -68,6 +69,112 @@ abstract class AudioPlayerPlatform {
|
|||
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 {
|
||||
final String id;
|
||||
|
||||
|
@ -344,6 +451,7 @@ class ProgressiveAudioSourceMessage extends UriAudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'progressive',
|
||||
'id': id,
|
||||
'uri': uri,
|
||||
'headers': headers,
|
||||
|
@ -359,6 +467,7 @@ class DashAudioSourceMessage extends UriAudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'dash',
|
||||
'id': id,
|
||||
'uri': uri,
|
||||
'headers': headers,
|
||||
|
@ -374,6 +483,7 @@ class HlsAudioSourceMessage extends UriAudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'hls',
|
||||
'id': id,
|
||||
'uri': uri,
|
||||
'headers': headers,
|
||||
|
@ -392,7 +502,9 @@ class ConcatenatingAudioSourceMessage extends AudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'concatenating',
|
||||
'id': id,
|
||||
// TODO: ensure platform implementation uses this key
|
||||
'children': children.map((child) => child.toMap()).toList(),
|
||||
'useLazyPreparation': useLazyPreparation,
|
||||
};
|
||||
|
@ -412,9 +524,13 @@ class ClippingAudioSourceMessage extends IndexedAudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'clipping',
|
||||
'id': id,
|
||||
// TODO: ensure platform implementation uses this key
|
||||
'child': child.toMap(),
|
||||
// TODO: ensure platform implementation interprets in Us.
|
||||
'start': start.inMicroseconds,
|
||||
// TODO: ensure platform implementation interprets in Us.
|
||||
'end': end.inMicroseconds,
|
||||
};
|
||||
}
|
||||
|
@ -431,7 +547,9 @@ class LoopingAudioSourceMessage extends AudioSourceMessage {
|
|||
|
||||
@override
|
||||
Map<dynamic, dynamic> toMap() => {
|
||||
'type': 'looping',
|
||||
'id': id,
|
||||
// TODO: ensure platform implementation uses this key
|
||||
'child': child.toMap(),
|
||||
'count': count,
|
||||
};
|
||||
|
|
|
@ -22,94 +22,101 @@ class MethodChannelAudioPlayer extends AudioPlayerPlatform {
|
|||
MethodChannelAudioPlayer(this.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
|
||||
Future<LoadResponse> load(LoadRequest request) async {
|
||||
return (await _channel.invokeMethod('load', request?.toMap()))?.fromMap();
|
||||
return LoadResponse.fromMap(
|
||||
await _channel.invokeMethod('load', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PlayResponse> play(PlayRequest request) async {
|
||||
return (await _channel.invokeMethod('play', request?.toMap()))?.fromMap();
|
||||
return PlayResponse.fromMap(
|
||||
await _channel.invokeMethod('play', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PauseResponse> pause(PauseRequest request) async {
|
||||
return (await _channel.invokeMethod('pause', request?.toMap()))?.fromMap();
|
||||
return PauseResponse.fromMap(
|
||||
await _channel.invokeMethod('pause', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetVolumeResponse> setVolume(SetVolumeRequest request) async {
|
||||
return (await _channel.invokeMethod('setVolume', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetVolumeResponse.fromMap(
|
||||
await _channel.invokeMethod('setVolume', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetSpeedResponse> setSpeed(SetSpeedRequest request) async {
|
||||
return (await _channel.invokeMethod('setSpeed', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetSpeedResponse.fromMap(
|
||||
await _channel.invokeMethod('setSpeed', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetLoopModeResponse> setLoopMode(SetLoopModeRequest request) async {
|
||||
return (await _channel.invokeMethod('setLoopMode', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetLoopModeResponse.fromMap(
|
||||
await _channel.invokeMethod('setLoopMode', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetShuffleModeResponse> setShuffleMode(
|
||||
SetShuffleModeRequest request) async {
|
||||
return (await _channel.invokeMethod('setShuffleMode', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetShuffleModeResponse.fromMap(
|
||||
await _channel.invokeMethod('setShuffleMode', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetAutomaticallyWaitsToMinimizeStallingResponse>
|
||||
setAutomaticallyWaitsToMinimizeStalling(
|
||||
SetAutomaticallyWaitsToMinimizeStallingRequest request) async {
|
||||
return (await _channel.invokeMethod(
|
||||
'setAutomaticallyWaitsToMinimizeStalling', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetAutomaticallyWaitsToMinimizeStallingResponse.fromMap(
|
||||
await _channel.invokeMethod(
|
||||
'setAutomaticallyWaitsToMinimizeStalling', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SeekResponse> seek(SeekRequest request) async {
|
||||
return (await _channel.invokeMethod('seek', request?.toMap()))?.fromMap();
|
||||
return SeekResponse.fromMap(
|
||||
await _channel.invokeMethod('seek', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SetAndroidAudioAttributesResponse> setAndroidAudioAttributes(
|
||||
SetAndroidAudioAttributesRequest request) async {
|
||||
return (await _channel.invokeMethod(
|
||||
'setAndroidAudioAttributes', request?.toMap()))
|
||||
?.fromMap();
|
||||
return SetAndroidAudioAttributesResponse.fromMap(await _channel
|
||||
.invokeMethod('setAndroidAudioAttributes', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DisposeResponse> dispose(DisposeRequest request) async {
|
||||
return (await _channel.invokeMethod('dispose', request?.toMap()))
|
||||
?.fromMap();
|
||||
return DisposeResponse.fromMap(
|
||||
await _channel.invokeMethod('dispose', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ConcatenatingInsertAllResponse> concatenatingInsertAll(
|
||||
ConcatenatingInsertAllRequest request) async {
|
||||
return (await _channel.invokeMethod(
|
||||
'concatenatingInsertAll', request?.toMap()))
|
||||
?.fromMap();
|
||||
return ConcatenatingInsertAllResponse.fromMap(await _channel.invokeMethod(
|
||||
'concatenatingInsertAll', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ConcatenatingRemoveRangeResponse> concatenatingRemoveRange(
|
||||
ConcatenatingRemoveRangeRequest request) async {
|
||||
return (await _channel.invokeMethod(
|
||||
'concatenatingRemoveRange', request?.toMap()))
|
||||
?.fromMap();
|
||||
return ConcatenatingRemoveRangeResponse.fromMap(await _channel.invokeMethod(
|
||||
'concatenatingRemoveRange', request?.toMap()));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ConcatenatingMoveResponse> concatenatingMove(
|
||||
ConcatenatingMoveRequest request) async {
|
||||
return (await _channel.invokeMethod('concatenatingMove', request?.toMap()))
|
||||
?.fromMap();
|
||||
return ConcatenatingMoveResponse.fromMap(
|
||||
await _channel.invokeMethod('concatenatingMove', request?.toMap()));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue