<cmd>pulseaudio <opt>--dump-modules</opt></cmd>
<cmd>pulseaudio <opt>--dump-resample-methods</opt></cmd>
<cmd>pulseaudio <opt>--cleanup-shm</opt></cmd>
+ <cmd>pulseaudio <opt>--start</opt></cmd>
<cmd>pulseaudio <opt>--kill</opt></cmd>
<cmd>pulseaudio <opt>--check</opt></cmd>
</synopsis>
(e.g. Linux).</p></optdesc>
</option>
+ <option>
+ <p><opt>--start</opt></p>
+
+ <optdesc><p>Start PulseAudio if it is not running yet. This is
+ different from starting PulseAudio without <opt>--start</opt>
+ which would fail if PA is already running. PulseAudio is
+ guaranteed to be fully initialized when this call
+ returns. Implies <opt>--daemon</p>.</optdesc>
+ </option>
+
<option>
<p><opt>-k | --kill</opt></p>
ARG_DISABLE_SHM,
ARG_DUMP_RESAMPLE_METHODS,
ARG_SYSTEM,
- ARG_CLEANUP_SHM
+ ARG_CLEANUP_SHM,
+ ARG_START
};
/* Tabel for getopt_long() */
{"dl-search-path", 1, 0, ARG_DL_SEARCH_PATH},
{"resample-method", 1, 0, ARG_RESAMPLE_METHOD},
{"kill", 0, 0, ARG_KILL},
+ {"start", 0, 0, ARG_START},
{"use-pid-file", 2, 0, ARG_USE_PID_FILE},
{"check", 0, 0, ARG_CHECK},
{"system", 2, 0, ARG_SYSTEM},
" --dump-modules Dump list of available modules\n"
" --dump-resample-methods Dump available resample methods\n"
" --cleanup-shm Cleanup stale shared memory segments\n"
+ " --start Start the daemon if it is not running\n"
" -k --kill Kill a running daemon\n"
" --check Check for a running daemon\n\n"
conf->cmd = PA_CMD_KILL;
break;
+ case ARG_START:
+ conf->cmd = PA_CMD_START;
+ conf->daemonize = TRUE;
+ break;
+
case ARG_CHECK:
conf->cmd = PA_CMD_CHECK;
break;
#include "ltdl-bind-now.h"
#include "polkit.h"
+#define AUTOSPAWN_LOCK "autospawn.lock"
+
#ifdef HAVE_LIBWRAP
/* Only one instance of these variables */
int allow_severity = LOG_INFO;
pa_time_event *win32_timer;
struct timeval win32_tv;
#endif
+ char *lf = NULL;
+ int autospawn_lock_fd = -1;
#if defined(__linux__) && defined(__OPTIMIZE__)
/*
if (conf->high_priority && !pa_can_high_priority())
pa_log_warn("High-priority scheduling enabled in configuration but not allowed by policy.");
- if (conf->high_priority && conf->cmd == PA_CMD_DAEMON)
+ if (conf->high_priority && (conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START))
pa_raise_priority(conf->nice_level);
if (suid_root) {
pa_bool_t drop;
- drop = conf->cmd != PA_CMD_DAEMON || !conf->realtime_scheduling;
+ drop = (conf->cmd != PA_CMD_DAEMON && conf->cmd != PA_CMD_START) || !conf->realtime_scheduling;
#ifdef RLIMIT_RTPRIO
if (!drop) {
goto finish;
default:
- pa_assert(conf->cmd == PA_CMD_DAEMON);
+ pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
}
if (real_root && !conf->system_instance)
goto finish;
}
+ if (conf->cmd == PA_CMD_START) {
+ /* If we shall start PA only when it is not running yet, we
+ * first take the autospawn lock to make things
+ * synchronous. */
+
+ lf = pa_runtime_path(AUTOSPAWN_LOCK);
+ autospawn_lock_fd = pa_lock_lockfile(lf);
+ }
+
if (conf->daemonize) {
pid_t child;
int tty_fd;
goto finish;
}
+ if (autospawn_lock_fd >= 0) {
+ /* The lock file is unlocked from the parent, so we need
+ * to close it in the child */
+
+ pa_close(autospawn_lock_fd);
+ autospawn_lock_fd = -1;
+ }
+
pa_assert_se(pa_close(daemon_pipe[0]) == 0);
daemon_pipe[0] = -1;
#endif
pa_log_info("Running in system mode: %s", pa_yes_no(pa_in_system_mode()));
if (conf->use_pid_file) {
- if (pa_pid_file_create("pulseaudio") < 0) {
+ int z;
+
+ if ((z = pa_pid_file_create("pulseaudio")) != 0) {
+
+ if (conf->cmd == PA_CMD_START && z > 0) {
+ /* If we are already running and with are run in
+ * --start mode, then let's return this as success. */
+
+ pa_log_info("z=%i rock!", z);
+
+ retval = 0;
+ goto finish;
+ }
+
pa_log("pa_pid_file_create() failed.");
goto finish;
}
goto finish;
}
-
#ifdef HAVE_FORK
- if (conf->daemonize) {
+ if (daemon_pipe[1] >= 0) {
int ok = 0;
pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL);
+ pa_close(daemon_pipe[1]);
+ daemon_pipe[1] = -1;
}
#endif
finish:
+ if (autospawn_lock_fd >= 0)
+ pa_unlock_lockfile(lf, autospawn_lock_fd);
+
+ if (lf)
+ pa_xfree(lf);
+
#ifdef OS_IS_WIN32
if (win32_timer)
pa_mainloop_get_api(mainloop)->time_free(win32_timer);
pa_signal_done();
#ifdef HAVE_FORK
+ if (daemon_pipe[1] >= 0)
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
+
pa_close_pipe(daemon_pipe);
#endif