open method

  1. @override
Future<void> open(
  1. Playable playable, {
  2. bool play = true,
  3. bool synchronized = true,
})
override

Opens a Media or Playlist into the Player. Passing play as true starts the playback immediately.

await player.open(Media('asset:///assets/videos/sample.mp4'));
await player.open(Media('file:///C:/Users/Hitesh/Music/Sample.mp3'));
await player.open(
  Playlist(
    [
      Media('file:///C:/Users/Hitesh/Music/Sample.mp3'),
      Media('file:///C:/Users/Hitesh/Video/Sample.mkv'),
      Media('https://www.example.com/sample.mp4'),
      Media('rtsp://www.example.com/live'),
    ],
  ),
);

Implementation

@override
Future<void> open(
  Playable playable, {
  bool play = true,
  bool synchronized = true,
}) {
  Future<void> function() async {
    if (disposed) {
      throw AssertionError('[Player] has been disposed');
    }
    await waitForPlayerInitialization;
    await waitForVideoControllerInitializationIfAttached;

    final int index;
    final List<Media> playlist = <Media>[];
    if (playable is Media) {
      index = 0;
      playlist.add(playable);
    } else if (playable is Playlist) {
      index = playable.index;
      playlist.addAll(playable.medias);
    } else {
      index = -1;
    }

    // Keep these [Media] objects in memory.
    current.clear();
    current.addAll(playlist);

    final commands = [
      // Clear existing playlist & change currently playing index to none.
      // This causes playback to stop & player to enter the idle state.
      'stop',
      'playlist-clear',
      'playlist-play-index none',
    ];
    for (final command in commands) {
      final args = command.toNativeUtf8();
      mpv.mpv_command_string(
        ctx,
        args.cast(),
      );
      calloc.free(args);
    }

    // Enter paused state.
    {
      final name = 'pause'.toNativeUtf8();
      final value = calloc<Uint8>();
      mpv.mpv_get_property(
        ctx,
        name.cast(),
        generated.mpv_format.MPV_FORMAT_FLAG,
        value.cast(),
      );
      if (value.value == 0) {
        // We are using `cycle pause` because it waits & prevents the race condition.
        final command = 'cycle pause'.toNativeUtf8();
        mpv.mpv_command_string(
          ctx,
          command.cast(),
        );
      }
      calloc.free(name);
      calloc.free(value);
      state = state.copyWith(playing: false);
      if (!playingController.isClosed) {
        playingController.add(false);
      }
    }

    isShuffleEnabled = false;
    isPlayingStateChangeAllowed = false;

    for (int i = 0; i < playlist.length; i++) {
      await _command(
        [
          'loadfile',
          playlist[i].uri,
          'append',
        ],
      );
    }

    // If [play] is `true`, then exit paused state.
    if (play) {
      isPlayingStateChangeAllowed = true;
      final name = 'pause'.toNativeUtf8();
      final value = calloc<Uint8>();
      mpv.mpv_get_property(
        ctx,
        name.cast(),
        generated.mpv_format.MPV_FORMAT_FLAG,
        value.cast(),
      );
      if (value.value == 1) {
        // We are using `cycle pause` because it waits & prevents the race condition.
        final command = 'cycle pause'.toNativeUtf8();
        mpv.mpv_command_string(
          ctx,
          command.cast(),
        );
      }
      calloc.free(name);
      calloc.free(value);
      state = state.copyWith(playing: true);
      if (!playingController.isClosed) {
        playingController.add(true);
      }
    }

    // Jump to the specified [index] (in both cases either [play] is `true` or `false`).
    {
      final name = 'playlist-pos'.toNativeUtf8();
      final value = calloc<Int64>()..value = index;
      mpv.mpv_set_property(
        ctx,
        name.cast(),
        generated.mpv_format.MPV_FORMAT_INT64,
        value.cast(),
      );
      calloc.free(name);
      calloc.free(value);
    }
  }

  if (synchronized) {
    return lock.synchronized(function);
  } else {
    return function();
  }
}