123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- import 'dart:async';
- import 'dart:core';
- import 'dart:convert';
- import 'package:flutter/services.dart';
- import 'package:flutter_sound/android_encoder.dart';
- import 'package:flutter_sound/ios_quality.dart';
- class FlutterSound {
- static const MethodChannel _channel = const MethodChannel('flutter_sound');
- static StreamController<RecordStatus> _recorderController;
- static StreamController<double> _dbPeakController;
- static StreamController<PlayStatus> _playerController;
- /// Value ranges from 0 to 120
- Stream<double> get onRecorderDbPeakChanged => _dbPeakController.stream;
- Stream<RecordStatus> get onRecorderStateChanged => _recorderController.stream;
- Stream<PlayStatus> get onPlayerStateChanged => _playerController.stream;
- bool get isPlaying => _isPlaying;
- bool get isRecording => _isRecording;
- bool _isRecording = false;
- bool _isPlaying = false;
- Future<String> setSubscriptionDuration(double sec) async {
- String result = await _channel
- .invokeMethod('setSubscriptionDuration', <String, dynamic>{
- 'sec': sec,
- });
- return result;
- }
- Future<void> _setRecorderCallback() async {
- if (_recorderController == null) {
- _recorderController = new StreamController.broadcast();
- }
- if (_dbPeakController == null) {
- _dbPeakController = new StreamController.broadcast();
- }
- _channel.setMethodCallHandler((MethodCall call) {
- switch (call.method) {
- case "updateRecorderProgress":
- Map<String, dynamic> result = json.decode(call.arguments);
- if (_recorderController != null)
- _recorderController.add(new RecordStatus.fromJSON(result));
- break;
- case "updateDbPeakProgress":
- if (_dbPeakController!= null)
- _dbPeakController.add(call.arguments);
- break;
- default:
- throw new ArgumentError('Unknown method ${call.method} ');
- }
- return null;
- });
- }
- Future<void> _setPlayerCallback() async {
- if (_playerController == null) {
- _playerController = new StreamController.broadcast();
- }
- _channel.setMethodCallHandler((MethodCall call) {
- switch (call.method) {
- case "updateProgress":
- Map<String, dynamic> result = jsonDecode(call.arguments);
- if (_playerController!=null)
- _playerController.add(new PlayStatus.fromJSON(result));
- break;
- case "audioPlayerDidFinishPlaying":
- Map<String, dynamic> result = jsonDecode(call.arguments);
- PlayStatus status = new PlayStatus.fromJSON(result);
- if (status.currentPosition != status.duration) {
- status.currentPosition = status.duration;
- }
- if (_playerController != null)
- _playerController.add(status);
- this._isPlaying = false;
- _removePlayerCallback();
- break;
- default:
- throw new ArgumentError('Unknown method ${call.method}');
- }
- return null;
- });
- }
- Future<void> _removeRecorderCallback() async {
- if (_recorderController != null) {
- _recorderController
- ..add(null)
- ..close();
- _recorderController = null;
- }
- }
- Future<void> _removeDbPeakCallback() async {
- if (_dbPeakController != null) {
- _dbPeakController
- ..add(null)
- ..close();
- _dbPeakController = null;
- }
- }
- Future<void> _removePlayerCallback() async {
- if (_playerController != null) {
- _playerController
- ..add(null)
- ..close();
- _playerController = null;
- }
- }
- Future<String> startRecorder(String uri,
- {int sampleRate, int numChannels, int bitRate,
- AndroidEncoder androidEncoder = AndroidEncoder.AAC,
- AndroidAudioSource androidAudioSource = AndroidAudioSource.MIC,
- AndroidOutputFormat androidOutputFormat = AndroidOutputFormat.MPEG_4,
- IosQuality iosQuality = IosQuality.LOW,
- }) async {
-
- if (this._isRecording) {
- throw new RecorderRunningException('Recorder is already recording.');
- }
- try {
- String result =
- await _channel.invokeMethod('startRecorder', <String, dynamic>{
- 'path': uri,
- 'sampleRate': sampleRate,
- 'numChannels': numChannels,
- 'bitRate': bitRate,
- 'androidEncoder': androidEncoder?.value,
- 'androidAudioSource': androidAudioSource?.value,
- 'androidOutputFormat': androidOutputFormat?.value,
- 'iosQuality': iosQuality?.value
- });
- _setRecorderCallback();
- this._isRecording = true;
- return result;
- } catch (err) {
- throw new Exception(err);
- }
- }
- Future<String> stopRecorder() async {
- if (!this._isRecording) {
- throw new RecorderStoppedException('Recorder is already stopped.');
- }
- String result = await _channel.invokeMethod('stopRecorder');
- this._isRecording = false;
- _removeRecorderCallback();
- _removeDbPeakCallback();
- return result;
- }
- Future<String> startPlayer(String uri) async {
- if (this._isPlaying) {
- this.resumePlayer();
- return 'Player resumed';
- // throw PlayerRunningException('Player is already playing.');
- }
- try {
- String result =
- await _channel.invokeMethod('startPlayer', <String, dynamic>{
- 'path': uri,
- });
- print('startPlayer result: $result');
- _setPlayerCallback();
- this._isPlaying = true;
- return result;
- } catch (err) {
- throw Exception(err);
- }
- }
- Future<String> stopPlayer() async {
- if (!this._isPlaying) {
- throw PlayerStoppedException('Player already stopped.');
- }
- this._isPlaying = false;
- String result = await _channel.invokeMethod('stopPlayer');
- _removePlayerCallback();
- return result;
- }
- Future<String> pausePlayer() async {
- try {
- String result = await _channel.invokeMethod('pausePlayer');
- return result;
- } catch (err) {
- print('err: $err');
- return err;
- }
- }
- Future<String> resumePlayer() async {
- try {
- String result = await _channel.invokeMethod('resumePlayer');
- return result;
- } catch (err) {
- print('err: $err');
- return err;
- }
- }
- Future<String> seekToPlayer(int milliSecs) async {
- try {
- String result =
- await _channel.invokeMethod('seekToPlayer', <String, dynamic>{
- 'sec': milliSecs,
- });
- return result;
- } catch (err) {
- print('err: $err');
- return err;
- }
- }
- Future<String> setVolume(double volume) async {
- String result = '';
- if (volume < 0.0 || volume > 1.0) {
- result = 'Value of volume should be between 0.0 and 1.0.';
- return result;
- }
- result = await _channel
- .invokeMethod('setVolume', <String, dynamic>{
- 'volume': volume,
- });
- return result;
- }
- /// Defines the interval at which the peak level should be updated.
- /// Default is 0.8 seconds
- Future<String> setDbPeakLevelUpdate(double intervalInSecs) async {
- String result = await _channel
- .invokeMethod('setDbPeakLevelUpdate', <String, dynamic>{
- 'intervalInSecs': intervalInSecs,
- });
- return result;
- }
- /// Enables or disables processing the Peak level in db's. Default is disabled
- Future<String> setDbLevelEnabled(bool enabled) async {
- String result = await _channel
- .invokeMethod('setDbLevelEnabled', <String, dynamic>{
- 'enabled': enabled,
- });
- return result;
- }
- }
- class RecordStatus {
- final double currentPosition;
- RecordStatus.fromJSON(Map<String, dynamic> json)
- : currentPosition = double.parse(json['current_position']);
- @override
- String toString() {
- return 'currentPosition: $currentPosition';
- }
- }
- class PlayStatus {
- final double duration;
- double currentPosition;
- PlayStatus.fromJSON(Map<String, dynamic> json)
- : duration = double.parse(json['duration']),
- currentPosition = double.parse(json['current_position']);
- @override
- String toString() {
- return 'duration: $duration, '
- 'currentPosition: $currentPosition';
- }
- }
- class PlayerRunningException implements Exception {
- final String message;
- PlayerRunningException(this.message);
- }
- class PlayerStoppedException implements Exception {
- final String message;
- PlayerStoppedException(this.message);
- }
- class RecorderRunningException implements Exception {
- final String message;
- RecorderRunningException(this.message);
- }
- class RecorderStoppedException implements Exception {
- final String message;
- RecorderStoppedException(this.message);
- }
|