start method

Future<void> start({
  1. List<String> mpv_args = const [],
})

Starts the MPV player process

After MPV is started the function listens to the spawned MPV child processes stdout for see whether it could create and bind the IPC socket or not. If possible an ipcInterface is created to handle the socket communication

Observes the properties defined in the observed object
Sets up the event handlers

@param mpv_args - arguments that are passed to mpv on start up

@return Promise that is resolved when everything went fine or rejected when an error occurred

Implementation

Future<void> start({List<String> mpv_args = const []}) async {
  // check if mpv is already running

  if (running) {
    throw _errorHandler.errorMessage(6, 'start()');
  }

  // see if there's already an mpv instance running on the specified socket

  bool instance_running = await _isInstanceRunning();

  // these steps are only necessary if a new MPV instance is created, if the module is hooking into an existing
  // one, there's no need to start a new instance
  if (!instance_running) {
    // =========================
    // STARTING NEW MPV INSTANCE
    // =========================

    // check if the binary is actually available
    await utils.checkMpvBinary(binary);
    // check for the corrrect ipc command
    const ipcCommand = "--input-ipc-server";

    await _createMPVSubProcess(ipcCommand, mpv_args);
    await _checkMPVIdleMode();
    instance_running = true;
  }
  // if the module is hooking into an existing instance of MPV, we still ned to set up the
  // socket connection for the module
  else {
    await socket.connect(socketURI);
    if (debug || verbose) {
      print("[MPV_Dart]: Detected running MPV instance at ${socketURI}");
      print(
          '[MPV_Dart]: Hooked into existing MPV instance without starting a new one');
    }
  }

  // ============================================
  // SETTING UP THE PROPERTIES AND EVENT LISTENER
  // ============================================

  // set up the observed properties

  // sets the Interval to emit the current time position
  await observeProperty(
    'time-pos', /* 0 */
  );

  _timepositionListenerId = Timer.periodic(
      Duration(milliseconds: timeUpdate * 1000), (timer) async {
    bool paused = await isPaused().catchError((err) {
      if (debug) {
        print(
            '[MPV_Dart] timeposition listener cannot retrieve isPaused $err');
      }
      if (err.code == 8) {
        // mpv is not running but the interval was not cleaned out
        timer.cancel();
        return true;
      } else {
        throw err; // This error is not catcheable, maybe provide a function in options to catch these
      }
    });
    if (!paused && currentTimePos != null) {
      emit(MPVEvents.timeposition, null, currentTimePos);
    }
  });

  // Observe all the properties defined in the observed JSON object
  List<Future> observePromises = [];

  utils
      .observedProperties(audioOnly)
      .forEach((property) => observePromises.add(observeProperty(property)));

  // wait for all observe commands to finish
  await Future.wait(observePromises);

  // ### Events ###

  // events linked to the mpv instance can only be set up, if mpv was started by node js itself
  // it's not possible for an mpv instance started from a different process
  if (!instance_running) {
    // RECURSIVE METHOD (KEEP AN EYE)
    _closeHandler();
  }
  // if the module is hooking into an existing and running instance of mpv we need an event listener
  // that is attached directly to the net socket, to clear the interval for the time position
  else {
    socket.on("socket:done", null, (e, c) {
      _timepositionListenerId?.cancel();
      // it's kind of impossible to tell if an external instance was properly quit or has crashed
      // that's why both events are emitted
      emit(MPVEvents.crashed);
      emit(MPVEvents.quit);
    });
  }

  // Handle the JSON messages received from MPV via the ipcInterface
  socket.on('message', null, (message, c) {
    _messageHandler(message.eventData as Map);
  });

  // set the running flag
  running = true;

  // resolve this promise
  return;
}