load method

Future<void> load(
  1. String source, {
  2. LoadMode mode = LoadMode.replace,
  3. List<String> options = const [],
})

loads a file into mpv

Implementation

Future<void> load(String source,
    {LoadMode mode = LoadMode.replace,
    List<String> options = const []}) async {
  // check if this was called via load() or append() for error handling purposes
  String caller = utils.getCaller();

  // reject if mpv is not running
  if (!running) {
    throw (_errorHandler.errorMessage(8, caller, args: [
      source,
      mode.name,
      options
    ], options: {
      'replace': 'Replace the currently playing title',
      'append': 'Append the title to the playlist',
      'append-play':
          'Append the title and when it is the only title in the list start playback'
    }));
  }

  // MPV accepts various protocols, but the all start with <protocol>://, leave this input as it is
  // if it's a file, transform the path into the absolute filepath, such that it can be played
  // by any mpv instance, started in any working directory
  // also checks if the protocol is supported by mpv and throws an error otherwise
  String? sourceProtocol = utils.extractProtocolFromSource(source);
  if (sourceProtocol != null && !utils.validateProtocol(sourceProtocol)) {
    throw (_errorHandler.errorMessage(9, caller,
        args: [source, mode.name, options],
        errorMessage:
            'See https://mpv.io/manual/stable/#protocols for supported protocols'));
  }
  source = sourceProtocol != null ? source : path.absolute(source);

  _initCommandObserverSocket() async {
    Completer completer = Completer();
    Socket observeSocket = await Socket.connect(
      InternetAddress(socketURI, type: InternetAddressType.unix),
      0,
    );

    await command(
      'loadfile',
      [
        source,
        mode.name,
        options.join(","),
      ],
    );
    // get the playlist size
    int playlistSize = await getPlaylistSize();

    // if the mode is append resolve the promise because nothing
    // will be output by the mpv player
    // checking whether this source can be played or not is done when
    // the source is played
    if (mode == LoadMode.append && !completer.isCompleted) {
      observeSocket.destroy();
      completer.complete();
    }
    // if the mode is append-play and there are already songs in the playlist
    // resolve the promise since nothing will be output
    if (mode == LoadMode.appendPlay &&
        playlistSize > 1 &&
        !completer.isCompleted) {
      observeSocket.destroy();
      completer.complete();
    }

    // timeout
    int timeout = 0;
    // check if the source was started
    bool started = false;

    observeSocket.listen((event) {
      // increase timeout
      timeout += 1;
      // parse the messages from the socket
      List<String> messages = utf8.decode(event).split('\n');
      // check every message
      for (var message in messages) {
        // ignore empty messages
        if (message.isNotEmpty) {
          Map msgMap = jsonDecode(message);
          if (msgMap.containsKey("event")) {
            if (msgMap["event"] == 'start-file') {
              started = true;
            }
            // when the file has successfully been loaded resolve the promise
            else if (msgMap["event"] == 'file-loaded' &&
                started &&
                !completer.isCompleted) {
              observeSocket.destroy();
              // resolve the promise
              completer.complete();
            }
            // when the track has changed we don't need a seek event
            else if (msgMap["event"] == 'end-file' && started) {
              observeSocket.destroy();
              completer.completeError(
                  _errorHandler.errorMessage(0, caller, args: [source]));
            }
          }
        }
      }
    });

    // reject the promise if it took to long until the playback-restart happens
    // to prevent having sockets listening forever
    if (timeout > 10) {
      observeSocket.destroy();
      completer.completeError(
          _errorHandler.errorMessage(5, caller, args: [source]));
    }
  }

  await _initCommandObserverSocket();
}