anchor.diff:  import 'package:rxdart/rxdart.dart';
   import 'package:rxdart/subjects.dart';
   
  +/// An audio asset, represented by an asset name and a folder
  +/// This class is used by AssetsAudioPlayer to open a song
  +/// 
  +/// ### Example
  +///
  +///     AssetsAudioPlayer.open(AssetsAudio(
  +///       asset: "song1.mp3",
  +///       folder: "assets/audios/",
  +///     )
  +/// 
  +/// Don't forget to declare the audio folder in your `pubspec.yaml`
  +/// 
  +///     flutter:
  +///       assets:
  +///         - assets/audios/
  +///
   class AssetsAudio {
     final String asset;
     final String folder;
  
positive.code:   const AssetsAudio({this.asset, this.folder});
  }
  
  class PlayingAudio {
    final AssetsAudio assetAudio;
    final Duration duration;
  
    const PlayingAudio({this.assetAudio = const AssetsAudio(), this.duration});
  }
  
  class AssetsAudioPlayer {
    static AssetsAudioPlayerPlugin _plugin = AssetsAudioPlayerPlugin._();
    static ValueObservable<PlayingAudio> get current => _plugin.current;
    static ValueObservable<bool> get isPlaying => _plugin.isPlaying;
    static ValueObservable<bool> get finished => _plugin.finished;
    static ValueObservable<Duration> get currentPosition =>
        _plugin.currentPosition;
    static Stream<bool> get next => _plugin.next;
    static Stream<bool> get prev => _plugin.prev;
  
    static void open(AssetsAudio assetAudio) {
      _plugin.open(assetAudio);
    }
  
    static void playOrPause() async {
      _plugin.playOrPause();
    }
  
    static void play() {
      _plugin.play();
    }
  
    static void pause() {
      _plugin.pause();
    }
  
negative.code:               _prev.add(true);
                break;
                */
          case 'player.position':
            if (call.arguments is int) {
              _currentPosition.value = Duration(seconds: call.arguments);
            } else if (call.arguments is double) {
              double value = call.arguments;
              _currentPosition.value = Duration(seconds: value.round());
            }
            break;
          case 'player.isPlaying':
            _isPlaying.value = call.arguments;
            break;
          default:
            print('[ERROR] Channel method ${call.method} not implemented.');
        }
      });
    }
  
    Duration toDuration(num value) {
      if (value is int) {
        return Duration(seconds: value);
      } else if (value is double) {
        return Duration(seconds: value.round());
      } else {
        return Duration();
      }
    }
  
    void open(AssetsAudio assetAudio) async {
      String assetName = assetAudio.asset;
      if (assetName.startsWith("/")) {
        assetName = assetName.substring(1);
      }
      String folder = assetAudio.folder;
      if (folder.endsWith("/")) {
        folder = folder.substring(0, folder.length - 1);
      }
      if (folder.startsWith("/")) {
        folder = folder.substring(1);
      }
  
      try {
        _channel.invokeMethod(
            'open', <String, dynamic>{'file': assetName, 'folder': folder});
      } catch (e) {
        print(e);
      }
  
      _lastOpenedAssetsAudio = assetAudio;
    }
  
    void playOrPause() async {
      final bool playing = _isPlaying.value;
      if (playing) {
        pause();
      } else {
        play();
      }
    }
  
    void play() {
      _channel.invokeMethod('play');
    }
  
    void pause() {
      _channel.invokeMethod('pause');
    }
  
    void seek(Duration to) {
      _channel.invokeMethod('seek', to.inSeconds.round());
    }
  
    void stop() {
      _channel.invokeMethod('stop');
    }
  }
  