@@ -9,19 +9,20 @@ export 'package:audio_manager/src/AudioInfo.dart';
99export 'package:audio_manager/src/AudioType.dart' ;
1010
1111class AudioManager {
12- static late AudioManager _instance;
13-
12+ static AudioManager ? _instance;
1413 static AudioManager get instance => _getInstance ();
1514
1615 static _getInstance () {
17- _instance = new AudioManager ._();
16+ if (_instance == null ) {
17+ _instance = new AudioManager ._();
18+ }
1819 return _instance;
1920 }
2021
21- static MethodChannel ? _channel;
22+ static MethodChannel _channel = const MethodChannel ( 'audio_manager' ) ;
2223
2324 AudioManager ._() {
24- _channel = const MethodChannel ( 'audio_manager' ). .setMethodCallHandler (_handler);
25+ _channel.setMethodCallHandler (_handler);
2526 getCurrentVolume ();
2627 }
2728
@@ -52,7 +53,7 @@ class AudioManager {
5253 double _volume = 0 ;
5354
5455 /// If there are errors, return details
55- String get error => _error! ;
56+ String ? get error => _error;
5657 String ? _error;
5758
5859 /// list of playback. Used to record playlists
@@ -83,7 +84,7 @@ class AudioManager {
8384 bool _auto = true ;
8485
8586 /// Playback info
86- AudioInfo get info => _info! ;
87+ AudioInfo ? get info => _info;
8788 AudioInfo ? _info;
8889
8990 Future <dynamic > _handler (MethodCall call) {
@@ -95,7 +96,8 @@ class AudioManager {
9596 break ;
9697 case "seekComplete" :
9798 _position = Duration (milliseconds: call.arguments ?? 0 );
98- if (_duration.inMilliseconds != 0 ) _onEvents (AudioManagerEvents .seekComplete, _position);
99+ if (_duration.inMilliseconds != 0 )
100+ _onEvents (AudioManagerEvents .seekComplete, _position);
99101 break ;
100102 case "buffering" :
101103 _onEvents (AudioManagerEvents .buffering, call.arguments);
@@ -104,15 +106,18 @@ class AudioManager {
104106 _setPlaying (call.arguments ?? false );
105107 break ;
106108 case "timeupdate" :
109+ _error = null ;
107110 _position = Duration (milliseconds: call.arguments["position" ] ?? 0 );
108111 _duration = Duration (milliseconds: call.arguments["duration" ] ?? 0 );
109112 if (! _playing) _setPlaying (true );
110- if (_position.inMilliseconds < 0 || _duration.inMilliseconds <= 0 ) break ;
113+ if (_position.inMilliseconds < 0 || _duration.inMilliseconds <= 0 )
114+ break ;
111115 if (_position > _duration) {
112116 _position = _duration;
113117 _setPlaying (false );
114118 }
115- _onEvents (AudioManagerEvents .timeupdate, {"position" : _position, "duration" : _duration});
119+ _onEvents (AudioManagerEvents .timeupdate,
120+ {"position" : _position, "duration" : _duration});
116121 break ;
117122 case "error" :
118123 _error = call.arguments;
@@ -147,7 +152,7 @@ class AudioManager {
147152
148153 String _preprocessing () {
149154 var errMsg = "" ;
150- if (_info ! = null ) errMsg = "you must invoke the [start] method first" ;
155+ if (_info = = null ) errMsg = "you must invoke the [start] method first" ;
151156 if (_error != null ) errMsg = _error! ;
152157 if (_isLoading) errMsg = "audio resource loading...." ;
153158
@@ -156,22 +161,20 @@ class AudioManager {
156161 }
157162
158163 Events ? _events;
159- late bool _initialize;
164+ bool _initialize = false ;
160165
161166 /// callback events
162167 void onEvents (Events events) {
163168 _events = events;
164169 }
165170
166171 void _onEvents (AudioManagerEvents events, args) {
167- if (_events == null ) {
168- return ;
169- }
172+ if (_events == null ) return ;
170173 _events !(events, args);
171174 }
172175
173176 Future <String > get platformVersion async {
174- final String version = await _channel! .invokeMethod ('getPlatformVersion' );
177+ final String version = await _channel.invokeMethod ('getPlatformVersion' );
175178 return version;
176179 }
177180
@@ -192,25 +195,28 @@ class AudioManager {
192195
193196 _info = AudioInfo (url, title: title, desc: desc, coverUrl: cover);
194197 _audioList.insert (0 , _info! );
195- return await play (index: 0 , auto: auto! );
198+ return await play (index: 0 , auto: auto);
196199 }
197200
198201 /// This will load the file from the file-URI given by:
199202 /// `'file://${file.path}'` .
200203 Future <String > file (File file, String title,
201204 {required String desc, required String cover, required bool auto}) async {
202- return await start ("file://${file .path }" , title, desc: desc, cover: cover, auto: auto);
205+ return await start ("file://${file .path }" , title,
206+ desc: desc, cover: cover, auto: auto);
203207 }
204208
205209 Future <String > startInfo (AudioInfo audio, {required bool auto}) async {
206- return await start (audio.url, audio.title, desc: audio.desc, cover: audio.coverUrl);
210+ return await start (audio.url, audio.title,
211+ desc: audio.desc, cover: audio.coverUrl);
207212 }
208213
209214 /// Play specified subscript audio if you want
210215 Future <String > play ({int ? index, bool ? auto}) async {
211- if ((index! < 0 || index >= _audioList.length)) throw "invalid index" ;
216+ if (index != null && (index < 0 || index >= _audioList.length))
217+ throw "invalid index" ;
212218 _auto = auto ?? true ;
213- _curIndex = index;
219+ _curIndex = index ?? _curIndex ;
214220 final random = _initRandom ();
215221 // Do not replay the same url
216222 if (_info! .url != random.url) {
@@ -222,7 +228,7 @@ class AudioManager {
222228 _onEvents (AudioManagerEvents .start, _info);
223229
224230 final regx = new RegExp (r'^(http|https|file):\/\/\/?([\w.]+\/?)\S*' );
225- final result = await _channel! .invokeMethod ('start' , {
231+ final result = await _channel.invokeMethod ('start' , {
226232 "url" : _info! .url,
227233 "title" : _info! .title,
228234 "desc" : _info! .desc,
@@ -245,23 +251,23 @@ class AudioManager {
245251 if (_initialize == false && _playing == false ) {
246252 play (index: _curIndex, auto: true );
247253 }
248- bool playing = await _channel! .invokeMethod ("playOrPause" );
254+ bool playing = await _channel.invokeMethod ("playOrPause" );
249255 _setPlaying (playing);
250256 return playing;
251257 }
252258
253259 /// to play status
254260 Future <bool > toPlay () async {
255261 if (_preprocessing ().isNotEmpty) return false ;
256- bool playing = await _channel! .invokeMethod ("play" );
262+ bool playing = await _channel.invokeMethod ("play" );
257263 _setPlaying (playing);
258264 return playing;
259265 }
260266
261267 /// to pause status
262268 Future <bool > toPause () async {
263269 if (_preprocessing ().isNotEmpty) return false ;
264- bool playing = await _channel! .invokeMethod ("pause" );
270+ bool playing = await _channel.invokeMethod ("pause" );
265271 _setPlaying (playing);
266272 return playing;
267273 }
@@ -271,9 +277,11 @@ class AudioManager {
271277 /// ⚠️ You must after [AudioManagerEvents.ready] event invoked before you can change the playback progress
272278 Future <String > seekTo (Duration position) async {
273279 if (_preprocessing ().isNotEmpty) return _preprocessing ();
274- if (position.inMilliseconds < 0 || position.inMilliseconds > duration.inMilliseconds)
280+ if (position.inMilliseconds < 0 ||
281+ position.inMilliseconds > duration.inMilliseconds)
275282 return "[position] must be greater than 0 and less than the total duration" ;
276- return await _channel! .invokeMethod ("seekTo" , {"position" : position.inMilliseconds});
283+ return await _channel
284+ .invokeMethod ("seekTo" , {"position" : position.inMilliseconds});
277285 }
278286
279287 /// `rate` Play rate, default [AudioRate.rate100] is 1.0
@@ -282,40 +290,41 @@ class AudioManager {
282290 const _rates = [0.5 , 0.75 , 1 , 1.5 , 1.75 , 2 ];
283291 rate = rate;
284292 double _rate = _rates[rate.index].toDouble ();
285- return await _channel! .invokeMethod ("rate" , {"rate" : _rate});
293+ return await _channel.invokeMethod ("rate" , {"rate" : _rate});
286294 }
287295
288296 /// stop play
289297 stop () {
290298 _reset ();
291299 _initialize = false ;
292- _channel! .invokeMethod ("stop" );
300+ _channel.invokeMethod ("stop" );
293301 }
294302
295303 _reset () {
296304 if (_isLoading) return ;
297305 _duration = Duration (milliseconds: 0 );
298306 _position = Duration (milliseconds: 0 );
299307 _setPlaying (false );
300- _onEvents (AudioManagerEvents .timeupdate, {"position" : _position, "duration" : _duration});
308+ _onEvents (AudioManagerEvents .timeupdate,
309+ {"position" : _position, "duration" : _duration});
301310 }
302311
303312 /// release all resource
304313 release () {
305314 _reset ();
306- _channel! .invokeListMethod ("release" );
315+ _channel.invokeListMethod ("release" );
307316 }
308317
309318 /// Update play details
310319 updateLrc (String lrc) {
311320 if (_preprocessing ().isNotEmpty) return _preprocessing ();
312- _channel! .invokeMethod ("updateLrc" , {"lrc" : lrc});
321+ _channel.invokeMethod ("updateLrc" , {"lrc" : lrc});
313322 }
314323
315324 /// Switch playback mode. `Playmode` priority is greater than `index`
316325 PlayMode nextMode ({PlayMode ? playMode, int ? index}) {
317- int mode = index! ;
318- mode = playMode! .index;
326+ int mode = index ?? (_playMode.index + 1 ) % 3 ;
327+ if (playMode != null ) mode = playMode.index;
319328 switch (mode) {
320329 case 0 :
321330 _playMode = PlayMode .sequence;
@@ -355,35 +364,31 @@ class AudioManager {
355364 if (playMode != PlayMode .single) {
356365 _curIndex = (_curIndex + 1 ) % _audioList.length;
357366 }
358- return await play (index : 0 );
367+ return await play ();
359368 }
360369
361370 /// play previous audio
362371 Future <String > previous () async {
363372 if (playMode != PlayMode .single) {
364- num index = _curIndex - 1 ;
365- if (index < 0 ) {
366- _curIndex = _audioList.length - 1 ;
367- } else {
368- _curIndex = index.toInt ();
369- }
373+ int index = _curIndex - 1 ;
374+ _curIndex = index < 0 ? _audioList.length - 1 : index;
370375 }
371- return await play (index : _curIndex );
376+ return await play ();
372377 }
373378
374379 /// set volume range(0~1). `showVolume` : show volume view or not and this is only in iOS
375380 /// ⚠️ IOS simulator is invalid, please use real machine
376381 Future <String > setVolume (double value, {bool showVolume = false }) async {
377382 var volume = min (value, 1 );
378383 value = max (value, 0 );
379- final result =
380- await _channel ! .invokeMethod ("setVolume" , {"value" : volume, "showVolume" : showVolume});
384+ final result = await _channel
385+ .invokeMethod ("setVolume" , {"value" : volume, "showVolume" : showVolume});
381386 return result;
382387 }
383388
384389 /// get current volume
385390 Future <double > getCurrentVolume () async {
386- _volume = await _channel! .invokeMethod ("currentVolume" );
391+ _volume = await _channel.invokeMethod ("currentVolume" );
387392 return _volume;
388393 }
389394}
0 commit comments