Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add onCompletion stream 🐛 The visualization gets stuck incomplete. #147

Merged
merged 1 commit into from
Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.0.1

- Added `onCompletion` stream to get event when audio is finished playing.
- Fixed [#145](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/145) - The visualization gets stuck incomplete.

## 1.0.0

- Reworked waveforms from audio file
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ controller.onPlayerStateChanged.listen((state) {}); // Listening
controller.onCurrentDurationChanged.listen((duration) {}); // Listening to current duration changes
controller.onCurrentExtractedWaveformData.listen((data) {}); // Listening to latest extraction data
controller.onExtractionProgress.listen((progress) {}); // Listening to extraction progress
controller.onCompletion.listen((_){}); // Listening to audio completion
controller.stopAllPlayer(); // Stop all registered audio players
controller.dispose(); // Dispose controller
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ object Constants {
const val noOfSamples = "noOfSamples"
const val onCurrentExtractedWaveformData = "onCurrentExtractedWaveformData"
const val waveformData = "waveformData"
const val onExtractionProgressUpdate = "onExtractionProgressUpdate"
}

enum class FinishMode(val value:Int) {
Expand Down
7 changes: 7 additions & 0 deletions lib/src/audio_file_waveforms.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class _AudioFileWaveformsState extends State<AudioFileWaveforms>
late Clip? clipBehavior;
late PlayerWaveStyle? playerWaveStyle;
late StreamSubscription<int> onCurrentDurationSubscription;
late StreamSubscription<void> onCompletionSubscription;
StreamSubscription<List<double>>? onCurrentExtractedWaveformData;

@override
Expand All @@ -135,6 +136,11 @@ class _AudioFileWaveformsState extends State<AudioFileWaveforms>
_updatePlayerPercent(widget.size);
});

onCompletionSubscription =
widget.playerController.onCompletion.listen((event) {
_seekProgress.value = widget.playerController.maxDuration;
_updatePlayerPercent(widget.size);
});
if (widget.waveformData.isNotEmpty) {
_addWaveformData(widget.waveformData);
} else {
Expand All @@ -155,6 +161,7 @@ class _AudioFileWaveformsState extends State<AudioFileWaveforms>
void dispose() {
onCurrentDurationSubscription.cancel();
onCurrentExtractedWaveformData?.cancel();
onCompletionSubscription.cancel();
widget.playerController.removeListener(_addWaveformDataFromController);
_growingWaveController.dispose();
super.dispose();
Expand Down
12 changes: 7 additions & 5 deletions lib/src/base/audio_waveforms_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ class AudioWaveformsInterface {
var duration = call.arguments[Constants.current];
var key = call.arguments[Constants.playerKey];
if (duration.runtimeType == int) {
var indentifier = PlayerIdentifier<int>(key, duration);
PlatformStreams.instance.addCurrentDurationEvent(indentifier);
var identifier = PlayerIdentifier<int>(key, duration);
PlatformStreams.instance.addCurrentDurationEvent(identifier);
}
break;
case Constants.onDidFinishPlayingAudio:
Expand All @@ -181,8 +181,10 @@ class AudioWaveformsInterface {
: call.arguments[Constants.finishtype] == 1
? PlayerState.paused
: PlayerState.stopped;
var indentifier = PlayerIdentifier<PlayerState>(key, playerState);
PlatformStreams.instance.addPlayerStateEvent(indentifier);
var stateIdentifier = PlayerIdentifier<PlayerState>(key, playerState);
var completionIdentifier = PlayerIdentifier<void>(key, null);
PlatformStreams.instance.addCompletionEvent(completionIdentifier);
PlatformStreams.instance.addPlayerStateEvent(stateIdentifier);
if (PlatformStreams.instance.playerControllerFactory[key] != null) {
PlatformStreams.instance.playerControllerFactory[key]
?._playerState = playerState;
Expand All @@ -204,7 +206,7 @@ class AudioWaveformsInterface {
});
}

void removeMethodCallHandeler() {
void removeMethodCallHandler() {
_methodChannel.setMethodCallHandler(null);
}
}
17 changes: 15 additions & 2 deletions lib/src/base/platform_streams.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class PlatformStreams {
StreamController<PlayerIdentifier<List<double>>>.broadcast();
_extractionProgressController =
StreamController<PlayerIdentifier<double>>.broadcast();
_completionController =
StreamController<PlayerIdentifier<void>>.broadcast();
await AudioWaveformsInterface.instance.setMethodCallHandler();
}

Expand All @@ -47,11 +49,15 @@ class PlatformStreams {
Stream<PlayerIdentifier<double>> get onExtractionProgress =>
_extractionProgressController.stream;

Stream<PlayerIdentifier<void>> get onCompletion =>
_completionController.stream;

late StreamController<PlayerIdentifier<int>> _currentDurationController;
late StreamController<PlayerIdentifier<PlayerState>> _playerStateController;
late StreamController<PlayerIdentifier<List<double>>>
_extractedWaveformDataController;
late StreamController<PlayerIdentifier<double>> _extractionProgressController;
late StreamController<PlayerIdentifier<void>> _completionController;

void addCurrentDurationEvent(PlayerIdentifier<int> playerIdentifier) {
if (!_currentDurationController.isClosed) {
Expand All @@ -72,18 +78,25 @@ class PlatformStreams {
}
}

void addExtractionProgress(PlayerIdentifier<double> progress) async {
void addExtractionProgress(PlayerIdentifier<double> progress) {
if (!_extractionProgressController.isClosed) {
_extractionProgressController.add(progress);
}
}

void addCompletionEvent(PlayerIdentifier<void> event) {
if (!_completionController.isClosed) {
_completionController.add(event);
}
}

void dispose() {
_currentDurationController.close();
_playerStateController.close();
_extractedWaveformDataController.close();
_currentDurationController.close();
AudioWaveformsInterface.instance.removeMethodCallHandeler();
_completionController.close();
AudioWaveformsInterface.instance.removeMethodCallHandler();
isInitialised = false;
}
}
12 changes: 8 additions & 4 deletions lib/src/controllers/player_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class PlayerController extends ChangeNotifier {
Stream<double> get onExtractionProgress =>
PlatformStreams.instance.onExtractionProgress.filter(playerKey);

/// A stream to get events when audio is finished playing.
Stream<void> get onCompletion =>
PlatformStreams.instance.onCompletion.filter(playerKey);

PlayerController() {
if (!PlatformStreams.instance.isInitialised) {
PlatformStreams.instance.init();
Expand Down Expand Up @@ -166,7 +170,7 @@ class PlayerController extends ChangeNotifier {
if (_playerState == PlayerState.initialized ||
_playerState == PlayerState.paused) {
final isStarted = await AudioWaveformsInterface.instance
.startPlayer(_playerKey.toString(), finishMode);
.startPlayer(playerKey, finishMode);
if (isStarted) {
_setPlayerState(PlayerState.playing);
} else {
Expand All @@ -189,8 +193,8 @@ class PlayerController extends ChangeNotifier {

/// A function to stop player. After calling this, resources are freed.
Future<void> stopPlayer() async {
final isStopped = await AudioWaveformsInterface.instance
.stopPlayer(_playerKey.toString());
final isStopped =
await AudioWaveformsInterface.instance.stopPlayer(playerKey);
if (isStopped) {
_setPlayerState(PlayerState.stopped);
}
Expand All @@ -206,7 +210,7 @@ class PlayerController extends ChangeNotifier {
/// Default to 1.0
Future<bool> setVolume(double volume) async {
final result = await AudioWaveformsInterface.instance
.setVolume(volume, _playerKey.toString());
.setVolume(volume, playerKey);
return result;
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: audio_waveforms
description: A Flutter package that allow you to generate waveform while recording audio or from audio file.
version: 1.0.0
version: 1.0.1
homepage: https://github.com/SimformSolutionsPvtLtd/audio_waveforms
issue_tracker: https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues

Expand Down