start method
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;
}