mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
210 lines
5.1 KiB
Dart
210 lines
5.1 KiB
Dart
part of skysprites;
|
|
|
|
// TODO: The sound effects should probably use Android's SoundPool instead of
|
|
// MediaPlayer as it is more efficient and flexible for playing back sound effects
|
|
|
|
typedef void SoundEffectStreamCallback(SoundEffectStream);
|
|
|
|
class SoundEffect {
|
|
SoundEffect(this._pipeFuture);
|
|
|
|
// TODO: Remove load method from SoundEffect
|
|
Future load() async {
|
|
_data = await _pipeFuture;
|
|
}
|
|
|
|
Future<MojoDataPipeConsumer> _pipeFuture;
|
|
MojoDataPipeConsumer _data;
|
|
}
|
|
|
|
class SoundEffectStream {
|
|
SoundEffectStream(
|
|
this.sound,
|
|
this.loop,
|
|
this.volume,
|
|
this.pitch,
|
|
this.pan,
|
|
this.onSoundComplete
|
|
);
|
|
|
|
// TODO: Make these properties work
|
|
SoundEffect sound;
|
|
bool playing = false;
|
|
bool loop = false;
|
|
double volume = 1.0;
|
|
double pitch = 1.0;
|
|
double pan = 0.0;
|
|
|
|
// TODO: Implement completion callback. On completion, sounds should
|
|
// also be removed from the list of playing sounds.
|
|
SoundEffectStreamCallback onSoundComplete;
|
|
|
|
MediaPlayerProxy _player;
|
|
}
|
|
|
|
SoundEffectPlayer _sharedSoundEffectPlayer;
|
|
|
|
class SoundEffectPlayer {
|
|
|
|
static SoundEffectPlayer sharedInstance() {
|
|
if (_sharedSoundEffectPlayer == null) {
|
|
_sharedSoundEffectPlayer = new SoundEffectPlayer();
|
|
}
|
|
return _sharedSoundEffectPlayer;
|
|
}
|
|
|
|
SoundEffectPlayer() {
|
|
_mediaService = new MediaServiceProxy.unbound();
|
|
shell.requestService(null, _mediaService);
|
|
}
|
|
|
|
MediaServiceProxy _mediaService;
|
|
List<SoundEffectStream> _soundEffectStreams = [];
|
|
|
|
// TODO: This should no longer be needed when moving to SoundPool backing
|
|
Map<SoundEffect,MediaPlayerProxy> _mediaPlayers = {};
|
|
|
|
Future _prepare(SoundEffectStream playingSound) async {
|
|
await playingSound._player.ptr.prepare(playingSound.sound._data);
|
|
}
|
|
|
|
// TODO: Move sound loading here
|
|
// TODO: Support loading sounds from bundles
|
|
// Future<SoundEffect> load(url) async {
|
|
// ...
|
|
// }
|
|
|
|
// TODO: Add sound unloader
|
|
// unload(SoundEffect effect) {
|
|
// ...
|
|
// }
|
|
|
|
// TODO: Add paused property (should pause playback of all sounds)
|
|
bool paused;
|
|
|
|
SoundEffectStream play(
|
|
SoundEffect sound,
|
|
[bool loop = false,
|
|
double volume = 1.0,
|
|
double pitch = 1.0,
|
|
double pan = 0.0,
|
|
SoundEffectStreamCallback callback = null]) {
|
|
|
|
// Create new PlayingSound object
|
|
SoundEffectStream playingSound = new SoundEffectStream(
|
|
sound,
|
|
loop,
|
|
volume,
|
|
pitch,
|
|
pan,
|
|
callback
|
|
);
|
|
|
|
// TODO: Replace this with calls to SoundPool
|
|
if (_mediaPlayers[sound] == null) {
|
|
// Create player
|
|
playingSound._player = new MediaPlayerProxy.unbound();
|
|
_mediaService.ptr.createPlayer(playingSound._player);
|
|
|
|
// Prepare sound, then play it
|
|
_prepare(playingSound).then((_) {
|
|
playingSound._player.ptr.seekTo(0);
|
|
playingSound._player.ptr.start();
|
|
});
|
|
|
|
_soundEffectStreams.add(playingSound);
|
|
_mediaPlayers[sound] = playingSound._player;
|
|
} else {
|
|
// Reuse player
|
|
playingSound._player = _mediaPlayers[sound];
|
|
playingSound._player.ptr.seekTo(0);
|
|
playingSound._player.ptr.start();
|
|
}
|
|
|
|
return playingSound;
|
|
}
|
|
|
|
void stop(SoundEffectStream stream) {
|
|
stream._player.ptr.pause();
|
|
_soundEffectStreams.remove(stream);
|
|
}
|
|
|
|
void stopAll() {
|
|
for (SoundEffectStream playingSound in _soundEffectStreams) {
|
|
playingSound._player.ptr.pause();
|
|
}
|
|
_soundEffectStreams = [];
|
|
}
|
|
}
|
|
|
|
typedef void SoundTrackCallback(SoundTrack);
|
|
typedef void SoundTrackBufferingCallback(SoundTrack, int);
|
|
|
|
class SoundTrack {
|
|
MediaPlayerProxy _player;
|
|
|
|
SoundTrackCallback onSoundComplete;
|
|
SoundTrackCallback onSeekComplete;
|
|
SoundTrackBufferingCallback onBufferingUpdate;
|
|
bool loop;
|
|
double time;
|
|
double volume;
|
|
}
|
|
|
|
SoundTrackPlayer _sharedSoundTrackPlayer;
|
|
|
|
class SoundTrackPlayer {
|
|
List<SoundTrack> _soundTracks = [];
|
|
|
|
static sharedInstance() {
|
|
if (_sharedSoundTrackPlayer == null) {
|
|
_sharedSoundTrackPlayer = new SoundTrackPlayer();
|
|
}
|
|
return _sharedSoundTrackPlayer;
|
|
}
|
|
|
|
SoundTrackPlayer() {
|
|
_mediaService = new MediaServiceProxy.unbound();
|
|
shell.requestService(null, _mediaService);
|
|
}
|
|
|
|
MediaServiceProxy _mediaService;
|
|
|
|
Future<SoundTrack> load(Future<MojoDataPipeConsumer> pipe) async {
|
|
// Create media player
|
|
SoundTrack soundTrack = new SoundTrack();
|
|
soundTrack._player = new MediaPlayerProxy.unbound();
|
|
_mediaService.ptr.createPlayer(soundTrack._player);
|
|
|
|
await soundTrack._player.ptr.prepare(await pipe);
|
|
return soundTrack;
|
|
}
|
|
|
|
void unload(SoundTrack soundTrack) {
|
|
stop(soundTrack);
|
|
_soundTracks.remove(soundTrack);
|
|
}
|
|
|
|
void play(
|
|
SoundTrack soundTrack,
|
|
[bool loop = false,
|
|
double volume,
|
|
double startTime = 0.0]) {
|
|
// TODO: Implement looping & volume
|
|
// soundTrack._player.ptr.setLooping(loop);
|
|
// soundTrack._player.ptr.setVolume(volume);
|
|
soundTrack._player.ptr.seekTo((startTime * 1000.0).toInt());
|
|
soundTrack._player.ptr.start();
|
|
}
|
|
|
|
void stop(SoundTrack track) {
|
|
track._player.ptr.pause();
|
|
}
|
|
|
|
void stopAll() {
|
|
for (SoundTrack soundTrack in _soundTracks) {
|
|
soundTrack._player.ptr.pause();
|
|
}
|
|
}
|
|
}
|