Skip to content

Commit

Permalink
feat: ✨ Add a method to pause all players at once
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshuGandhiSimform committed Dec 9, 2024
1 parent af6bc5a commit ef20485
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 28 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.2.1 (Unreleased)

- Fixes [#325](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/325) - Added feature to pause all player controller at once.

## 1.2.0

- Fixed [#350](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/350) - Waveform clipping at starting position
Expand All @@ -6,6 +10,7 @@
- Fixed [#364](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/pull/364) - seekTo position issue where onDrag of waveform at initial position first wave outside the seekLine.
- Fixed [#301](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/301) - Cannot catch error of preparePlayer
- Fixes [#228](https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues/228) - Added feature to setReleaseMode for player controller.


## 1.1.1

Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,13 @@ playerController.release();
playerController.stopAllPlayer();
```
There could be any number of players but you can just call this function from any **one** player and it will stop all the players.

#### Pausing players all at once
```dart
playerController.pauseAllPlayers();
```
There could be any number of players but you can just call this function from any **one** player and it will pause all the players.

#### Disposing the controller
```dart
playerController.dispose();
Expand Down
15 changes: 4 additions & 11 deletions android/src/main/kotlin/com/simform/audio_waveforms/AudioPlayer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,26 +129,19 @@ class AudioPlayer(
}
}

fun stop(result: MethodChannel.Result) {
fun stop() {
stopListening()
if (playerListener != null) {
player?.removeListener(playerListener!!)
}
isPlayerPrepared = false
player?.stop()
result.success(true)
}


fun pause(result: MethodChannel.Result) {
try {
stopListening()
player?.pause()
result.success(true)
} catch (e: Exception) {
result.error(Constants.LOG_TAG, "Failed to pause the player", e.toString())
}

fun pause() {
stopListening()
player?.pause()
}

fun release(result: MethodChannel.Result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
Constants.stopPlayer -> {
val key = call.argument(Constants.playerKey) as String?
if (key != null) {
audioPlayers[key]?.stop(result)
audioPlayers[key]?.stop()
result.success(true)
} else {
result.error(Constants.LOG_TAG, "Player key can't be null", "")
}
Expand All @@ -111,7 +112,8 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
Constants.pausePlayer -> {
val key = call.argument(Constants.playerKey) as String?
if (key != null) {
audioPlayers[key]?.pause(result)
audioPlayers[key]?.pause()
result.success(true)
} else {
result.error(Constants.LOG_TAG, "Player key can't be null", "")
}
Expand Down Expand Up @@ -188,7 +190,7 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

Constants.stopAllPlayers -> {
for ((key, _) in audioPlayers) {
audioPlayers[key]?.stop(result)
audioPlayers[key]?.stop()
audioPlayers[key] = null
}
result.success(true)
Expand All @@ -202,6 +204,13 @@ class AudioWaveformsPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {
}
}

Constants.pauseAllPlayers -> {
for ((key, _) in audioPlayers) {
audioPlayers[key]?.pause()
}
result.success(true)
}

else -> result.notImplemented()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ object Constants {

const val resultFilePath = "resultFilePath"
const val resultDuration = "resultDuration"
const val pauseAllPlayers = "pauseAllPlayers"
}

enum class FinishMode(val value: Int) {
Expand Down
2 changes: 1 addition & 1 deletion example/lib/chat_bubble.dart
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class _WaveBubbleState extends State<WaveBubble> {
IconButton(
onPressed: () async {
controller.playerState.isPlaying
? await controller.pausePlayer()
? await controller.stopAllPlayers()
: await controller.startPlayer();
controller.setFinishMode(finishMode: FinishMode.loop);
},
Expand Down
24 changes: 22 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,20 @@ class _HomeState extends State<Home> {
setState(() {});
}

var recordAudioListener;
void _initialiseControllers() {
recorderController = RecorderController()
..androidEncoder = AndroidEncoder.aac
..androidOutputFormat = AndroidOutputFormat.mpeg4
..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
..sampleRate = 44100;

recordAudioListener = () {
var ab = recorderController.elapsedDuration.inSeconds ?? 0;
print('object-----> $ab');
};

recorderController.addListener(recordAudioListener);
}

void _pickFile() async {
Expand Down Expand Up @@ -214,14 +222,26 @@ class _HomeState extends State<Home> {
try {
if (isRecording) {
recorderController.reset();
await recorderController.pause();
final audioFile = await recorderController.stop();
final time = recorderController.recordedDuration.inSeconds;
recorderController.removeListener(recordAudioListener!);

print('Duration ======> $audioFile $time');

path = await recorderController.stop(false);
if (audioFile != null && (time ?? 0) > 0) {
print('object ---> Upload image');
}
recorderController.dispose();

/* path = await recorderController.stop(false);
if (path != null) {
isRecordingCompleted = true;
debugPrint(path);
debugPrint("Recorded file size: ${File(path!).lengthSync()}");
}
recorderController.dispose();
}*/
} else {
await recorderController.record(path: path); // Path is optional
}
Expand Down
6 changes: 2 additions & 4 deletions ios/Classes/AudioPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,15 @@ class AudioPlayer: NSObject, AVAudioPlayerDelegate {
}


func pausePlayer(result: @escaping FlutterResult) {
func pausePlayer() {
stopListening()
player?.pause()
result(true)
}

func stopPlayer(result: @escaping FlutterResult) {
func stopPlayer() {
stopListening()
player?.stop()
timer = nil
result(true)
}

func release(result: @escaping FlutterResult) {
Expand Down
16 changes: 12 additions & 4 deletions ios/Classes/SwiftAudioWaveformsPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,17 @@ public class SwiftAudioWaveformsPlugin: NSObject, FlutterPlugin {
case Constants.pausePlayer:
let key = args?[Constants.playerKey] as? String
if(key != nil){
audioPlayers[key!]?.pausePlayer(result: result)
audioPlayers[key!]?.pausePlayer()
result(true)
} else {
result(FlutterError(code: Constants.audioWaveforms, message: "Can not pause player", details: "Player key is null"))
}
break
case Constants.stopPlayer:
let key = args?[Constants.playerKey] as? String
if(key != nil){
audioPlayers[key!]?.stopPlayer(result: result)
audioPlayers[key!]?.stopPlayer()
result(true)
} else {
result(FlutterError(code: Constants.audioWaveforms, message: "Can not stop player", details: "Player key is null"))
}
Expand Down Expand Up @@ -133,8 +135,8 @@ public class SwiftAudioWaveformsPlugin: NSObject, FlutterPlugin {
result(FlutterError(code: Constants.audioWaveforms, message: "Can not get duration", details: "Player key is null"))
}
case Constants.stopAllPlayers:
for (playerKey,_) in audioPlayers{
audioPlayers[playerKey]?.stopPlayer(result: result)
for (playerKey,_) in audioPlayers {
audioPlayers[playerKey]?.stopPlayer()
audioPlayers[playerKey] = nil
}
result(true)
Expand All @@ -147,6 +149,12 @@ public class SwiftAudioWaveformsPlugin: NSObject, FlutterPlugin {
} else {
result(FlutterError(code: Constants.audioWaveforms, message: "Can not get waveform data", details: "Player key is null"))
}
case Constants.pauseAllPlayers:
for(playerKey,_) in audioPlayers {
audioPlayers[playerKey]?.pausePlayer()
}
result(true)
break
default:
result(FlutterMethodNotImplemented)
break
Expand Down
1 change: 1 addition & 0 deletions ios/Classes/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct Constants {
static let overrideAudioSession = "overrideAudioSession"
static let resultFilePath = "resultFilePath"
static let resultDuration = "resultDuration"
static let pauseAllPlayers = "pauseAllPlayers"
}


Expand Down
5 changes: 5 additions & 0 deletions lib/src/base/audio_waveforms_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ class AudioWaveformsInterface {
return result ?? false;
}

Future<bool> pauseAllPlayers() async {
var result = await _methodChannel.invokeMethod(Constants.pauseAllPlayers);
return result ?? false;
}

Future<void> setMethodCallHandler() async {
_methodChannel.setMethodCallHandler((call) async {
switch (call.method) {
Expand Down
1 change: 1 addition & 0 deletions lib/src/base/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Constants {
static const String current = "current";
static const String onCurrentDuration = "onCurrentDuration";
static const String stopAllPlayers = "stopAllPlayers";
static const String pauseAllPlayers = "pauseAllPlayers";
static const String onDidFinishPlayingAudio = "onDidFinishPlayingAudio";
static const String extractWaveformData = "extractWaveformData";
static const String noOfSamples = "noOfSamples";
Expand Down
31 changes: 29 additions & 2 deletions lib/src/controllers/player_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,37 @@ class PlayerController extends ChangeNotifier {
///
/// This method will close the stream and free resources taken by all
/// players. This method will not dispose controller.
Future<void> stopAllPlayers() async {
///
/// Returns true if all player stopped otherwise return false.
Future<bool> stopAllPlayers() async {
PlatformStreams.instance.dispose();
await AudioWaveformsInterface.instance.stopAllPlayers();
var isAllPlayersStopped =
await AudioWaveformsInterface.instance.stopAllPlayers();
if (isAllPlayersStopped) {
PlatformStreams.instance.playerControllerFactory
.forEach((playKey, controller) {
controller._setPlayerState(PlayerState.stopped);
});
}
PlatformStreams.instance.playerControllerFactory.clear();
return isAllPlayersStopped;
}

/// This method is to pause all players at once.
///
/// This method will only pause the players it will not release the resources.
///
/// Returns true if all player paused otherwise return false.
Future<bool> pauseAllPlayers() async {
var isAllPlayersPaused =
await AudioWaveformsInterface.instance.pauseAllPlayers();
if (isAllPlayersPaused) {
PlatformStreams.instance.playerControllerFactory
.forEach((playKey, controller) {
controller._setPlayerState(PlayerState.paused);
});
}
return isAllPlayersPaused;
}

/// Sets [_shouldRefresh] flag with provided boolean parameter.
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.2.0
version: 1.2.1
homepage: https://github.com/SimformSolutionsPvtLtd/audio_waveforms
issue_tracker: https://github.com/SimformSolutionsPvtLtd/audio_waveforms/issues

Expand Down

0 comments on commit ef20485

Please sign in to comment.