Update comments and provide default implementations of platform interface.
This commit is contained in:
parent
1be1c212f6
commit
aa57e7fad8
|
@ -1,26 +1,15 @@
|
||||||
# just_audio_platform_interface
|
# just_audio_platform_interface
|
||||||
|
|
||||||
A common platform interface for the [`just_audio`][../just_audio] plugin.
|
A common platform interface for the [`just_audio`](../just_audio) plugin.
|
||||||
|
|
||||||
This interface allows platform-specific implementations of the `just_audio`
|
This interface allows platform-specific implementations of the `just_audio` plugin, as well as the plugin itself, to ensure they are supporting the same interface.
|
||||||
plugin, as well as the plugin itself, to ensure they are supporting the
|
|
||||||
same interface.
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
To implement a new platform-specific implementation of `just_audio`, extend
|
To implement a new platform-specific implementation of `just_audio`, extend [`JustAudioPlatform`](lib/just_audio_platform_interface.dart) with an implementation that performs the platform-specific behavior, and when you register your plugin, set the default `JustAudioPlatform` by calling `JustAudioPlatform.instance = MyPlatformJustAudio()`.
|
||||||
[`JustAudioPlatform`][2] with an implementation that performs the
|
|
||||||
platform-specific behavior, and when you register your plugin, set the default
|
|
||||||
`JustAudioPlatform` by calling
|
|
||||||
`JustAudioPlatform.instance = MyPlatformJustAudio()`.
|
|
||||||
|
|
||||||
# Note on breaking changes
|
# Note on breaking changes
|
||||||
|
|
||||||
Strongly prefer non-breaking changes (such as adding a method to the interface)
|
Strongly prefer non-breaking changes (such as adding a method to the interface) over breaking changes for this package.
|
||||||
over breaking changes for this package.
|
|
||||||
|
|
||||||
See https://flutter.dev/go/platform-interface-breaking-changes for a discussion
|
See https://flutter.dev/go/platform-interface-breaking-changes for a discussion on why a less-clean interface is preferable to a breaking change.
|
||||||
on why a less-clean interface is preferable to a breaking change.
|
|
||||||
|
|
||||||
[1]: ../just_audio
|
|
||||||
[2]: lib/just_audio_platform_interface.dart
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ abstract class JustAudioPlatform extends PlatformInterface {
|
||||||
_instance = instance;
|
_instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new player and returns a nested platform interface for
|
/// Creates a new platform player and returns a nested platform interface for
|
||||||
/// communicating with that player.
|
/// communicating with that player.
|
||||||
Future<AudioPlayerPlatform> init(InitRequest request) {
|
Future<AudioPlayerPlatform> init(InitRequest request) {
|
||||||
throw UnimplementedError('init() has not been implemented.');
|
throw UnimplementedError('init() has not been implemented.');
|
||||||
|
@ -45,30 +45,88 @@ 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.
|
||||||
|
///
|
||||||
|
/// Platform implementations should extend this class rather than implement it
|
||||||
|
/// as `just_audio` does not consider newly added methods to be breaking
|
||||||
|
/// changes. Extending this class (using `extends`) ensures that the subclass
|
||||||
|
/// will get the default implementation, while platform implementations that
|
||||||
|
/// `implements` this interface will be broken by newly added
|
||||||
|
/// [AudioPlayerPlatform] methods.
|
||||||
abstract class AudioPlayerPlatform {
|
abstract class AudioPlayerPlatform {
|
||||||
Stream<PlaybackEventMessage> get playbackEventMessageStream;
|
Stream<PlaybackEventMessage> get playbackEventMessageStream {
|
||||||
Future<LoadResponse> load(LoadRequest request);
|
throw UnimplementedError(
|
||||||
Future<PlayResponse> play(PlayRequest request);
|
'playbackEventMessageStream has not been implemented.');
|
||||||
Future<PauseResponse> pause(PauseRequest request);
|
|
||||||
Future<SetVolumeResponse> setVolume(SetVolumeRequest request);
|
|
||||||
Future<SetSpeedResponse> setSpeed(SetSpeedRequest request);
|
|
||||||
Future<SetLoopModeResponse> setLoopMode(SetLoopModeRequest request);
|
|
||||||
Future<SetShuffleModeResponse> setShuffleMode(SetShuffleModeRequest request);
|
|
||||||
Future<SetAutomaticallyWaitsToMinimizeStallingResponse>
|
|
||||||
setAutomaticallyWaitsToMinimizeStalling(
|
|
||||||
SetAutomaticallyWaitsToMinimizeStallingRequest request);
|
|
||||||
Future<SeekResponse> seek(SeekRequest request);
|
|
||||||
Future<SetAndroidAudioAttributesResponse> setAndroidAudioAttributes(
|
|
||||||
SetAndroidAudioAttributesRequest request);
|
|
||||||
Future<DisposeResponse> dispose(DisposeRequest request);
|
|
||||||
Future<ConcatenatingInsertAllResponse> concatenatingInsertAll(
|
|
||||||
ConcatenatingInsertAllRequest request);
|
|
||||||
Future<ConcatenatingRemoveRangeResponse> concatenatingRemoveRange(
|
|
||||||
ConcatenatingRemoveRangeRequest request);
|
|
||||||
Future<ConcatenatingMoveResponse> concatenatingMove(
|
|
||||||
ConcatenatingMoveRequest request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<LoadResponse> load(LoadRequest request) {
|
||||||
|
throw UnimplementedError("load() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PlayResponse> play(PlayRequest request) {
|
||||||
|
throw UnimplementedError("play() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<PauseResponse> pause(PauseRequest request) {
|
||||||
|
throw UnimplementedError("pause() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetVolumeResponse> setVolume(SetVolumeRequest request) {
|
||||||
|
throw UnimplementedError("setVolume() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetSpeedResponse> setSpeed(SetSpeedRequest request) {
|
||||||
|
throw UnimplementedError("setSpeed() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetLoopModeResponse> setLoopMode(SetLoopModeRequest request) {
|
||||||
|
throw UnimplementedError("setLoopMode() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetShuffleModeResponse> setShuffleMode(SetShuffleModeRequest request) {
|
||||||
|
throw UnimplementedError("setShuffleMode() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetAutomaticallyWaitsToMinimizeStallingResponse>
|
||||||
|
setAutomaticallyWaitsToMinimizeStalling(
|
||||||
|
SetAutomaticallyWaitsToMinimizeStallingRequest request) {
|
||||||
|
throw UnimplementedError(
|
||||||
|
"setAutomaticallyWaitsToMinimizeStalling() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SeekResponse> seek(SeekRequest request) {
|
||||||
|
throw UnimplementedError("seek() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<SetAndroidAudioAttributesResponse> setAndroidAudioAttributes(
|
||||||
|
SetAndroidAudioAttributesRequest request) {
|
||||||
|
throw UnimplementedError(
|
||||||
|
"setAndroidAudioAttributes() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DisposeResponse> dispose(DisposeRequest request) {
|
||||||
|
throw UnimplementedError("dispose() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ConcatenatingInsertAllResponse> concatenatingInsertAll(
|
||||||
|
ConcatenatingInsertAllRequest request) {
|
||||||
|
throw UnimplementedError(
|
||||||
|
"concatenatingInsertAll() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ConcatenatingRemoveRangeResponse> concatenatingRemoveRange(
|
||||||
|
ConcatenatingRemoveRangeRequest request) {
|
||||||
|
throw UnimplementedError(
|
||||||
|
"concatenatingRemoveRange() has not been implemented.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ConcatenatingMoveResponse> concatenatingMove(
|
||||||
|
ConcatenatingMoveRequest request) {
|
||||||
|
throw UnimplementedError("concatenatingMove() has not been implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A playback event communicated from the platform implementation to the
|
||||||
|
/// Flutter plugin.
|
||||||
class PlaybackEventMessage {
|
class PlaybackEventMessage {
|
||||||
final ProcessingStateMessage processingState;
|
final ProcessingStateMessage processingState;
|
||||||
final DateTime updateTime;
|
final DateTime updateTime;
|
||||||
|
@ -94,11 +152,8 @@ class PlaybackEventMessage {
|
||||||
PlaybackEventMessage(
|
PlaybackEventMessage(
|
||||||
processingState: ProcessingStateMessage.values[map['processingState']],
|
processingState: ProcessingStateMessage.values[map['processingState']],
|
||||||
updateTime: DateTime.fromMillisecondsSinceEpoch(map['updateTime']),
|
updateTime: DateTime.fromMillisecondsSinceEpoch(map['updateTime']),
|
||||||
// TODO: Ensure all platforms pass a microsecond value.
|
|
||||||
updatePosition: Duration(microseconds: map['updatePosition']),
|
updatePosition: Duration(microseconds: map['updatePosition']),
|
||||||
// TODO: Ensure all platforms pass a microsecond value.
|
|
||||||
bufferedPosition: Duration(microseconds: map['bufferedPosition']),
|
bufferedPosition: Duration(microseconds: map['bufferedPosition']),
|
||||||
// TODO: Ensure all platforms pass a microsecond value.
|
|
||||||
duration: map['duration'] == null || map['duration'] < 0
|
duration: map['duration'] == null || map['duration'] < 0
|
||||||
? null
|
? null
|
||||||
: Duration(microseconds: map['duration']),
|
: Duration(microseconds: map['duration']),
|
||||||
|
@ -110,6 +165,7 @@ class PlaybackEventMessage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A processing state communicated from the platform implementation.
|
||||||
enum ProcessingStateMessage {
|
enum ProcessingStateMessage {
|
||||||
none,
|
none,
|
||||||
loading,
|
loading,
|
||||||
|
@ -118,6 +174,7 @@ enum ProcessingStateMessage {
|
||||||
completed,
|
completed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Icy metadata communicated from the platform implementation.
|
||||||
class IcyMetadataMessage {
|
class IcyMetadataMessage {
|
||||||
final IcyInfoMessage info;
|
final IcyInfoMessage info;
|
||||||
final IcyHeadersMessage headers;
|
final IcyHeadersMessage headers;
|
||||||
|
@ -137,6 +194,7 @@ class IcyMetadataMessage {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Icy info communicated from the platform implementation.
|
||||||
class IcyInfoMessage {
|
class IcyInfoMessage {
|
||||||
final String title;
|
final String title;
|
||||||
final String url;
|
final String url;
|
||||||
|
@ -147,6 +205,7 @@ class IcyInfoMessage {
|
||||||
IcyInfoMessage(title: json['title'], url: json['url']);
|
IcyInfoMessage(title: json['title'], url: json['url']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Icy headers communicated from the platform implementation.
|
||||||
class IcyHeadersMessage {
|
class IcyHeadersMessage {
|
||||||
final int bitrate;
|
final int bitrate;
|
||||||
final String genre;
|
final String genre;
|
||||||
|
@ -419,6 +478,8 @@ class ConcatenatingMoveResponse {
|
||||||
ConcatenatingMoveResponse();
|
ConcatenatingMoveResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Information about an audio source to be communicated with the platform
|
||||||
|
/// implementation.
|
||||||
abstract class AudioSourceMessage {
|
abstract class AudioSourceMessage {
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
|
@ -504,7 +565,6 @@ class ConcatenatingAudioSourceMessage extends AudioSourceMessage {
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
'type': 'concatenating',
|
'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,
|
||||||
};
|
};
|
||||||
|
@ -526,11 +586,8 @@ class ClippingAudioSourceMessage extends IndexedAudioSourceMessage {
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
'type': 'clipping',
|
'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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -549,7 +606,6 @@ class LoopingAudioSourceMessage extends AudioSourceMessage {
|
||||||
Map<dynamic, dynamic> toMap() => {
|
Map<dynamic, dynamic> toMap() => {
|
||||||
'type': 'looping',
|
'type': 'looping',
|
||||||
'id': id,
|
'id': id,
|
||||||
// TODO: ensure platform implementation uses this key
|
|
||||||
'child': child.toMap(),
|
'child': child.toMap(),
|
||||||
'count': count,
|
'count': count,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@ class MethodChannelJustAudio extends JustAudioPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An implementation of [AudioPlayerPlatform] that uses method channels.
|
||||||
class MethodChannelAudioPlayer extends AudioPlayerPlatform {
|
class MethodChannelAudioPlayer extends AudioPlayerPlatform {
|
||||||
final String id;
|
final String id;
|
||||||
final MethodChannel _channel;
|
final MethodChannel _channel;
|
||||||
|
|
Loading…
Reference in New Issue