The daemon starts from src/daemon/main.c, this is where the inspection should start.

D-Bus setup

int main()
{
    ...
    /*/org/pulseaudio/server_lookup*/
    pa_dbusobj_server_lookup *server_lookup = NULL;

    /* Always the user bus. */
    pa_dbus_connection *lookup_service_bus = NULL;

    /* The bus where we reserve org.pulseaudio.Server,
     * either the user or the system bus. */ 
    pa_dbus_connection *server_bus = NULL;
    bool start_server;
    ...
}

D-Feet offers a nice view of PulseAudio D-Bus interface:

PulseAudio D-Bus API

Systemd socket activation

Then we can notice that the daemon can be activated using systemd socket activation:

    n_fds = sd_listen_fds(0);
    if (n_fds > 0) {
        int i = n_fds;

        passed_fds = pa_xnew(int, n_fds+2);
        passed_fds[n_fds] = passed_fds[n_fds+1] = -1;
        while (i--)
            passed_fds[i] = SD_LISTEN_FDS_START + i;
    }

And due to the good design of systemd, most of its service files are already provided by the upstream packages themsevelves instead of by the distributor. So in this case, PulseAudio provides a user service file at src/daemon/systemd/user/pulseaudio.socket:

[Unit]
Description=Sound System

[Socket]
Priority=6
Backlog=5
ListenStream=%t/pulse/native

[Install]
WantedBy=sockets.target

And from the systemd documentation we know that the ListenStream directive is used for stream sockets. And since the directive value starts with a /, this is a file system socket.

For example, such a user socket exists indeed in my home directory under the path:

/run/user/1000/pulse/native

which is a regular unix socket.

Daemon Configuration

Then PulseAudio loads the daemon configuration files.

    conf = pa_daemon_conf_new();
    if (pa_daemon_conf_load(conf, NULL) < 0)
        goto finish;

From the manpages, PulseAudio daemon configuration files are read from:

~/.config/pulse/daemon.conf, /etc/pulse/daemon.conf

Actually most distributions sets this file to commented out values. So the most important in this case is the daemon default set of values. This can be read from src/daemon/daemon-conf.c:

static const pa_daemon_conf default_conf = {
    .cmd = PA_CMD_DAEMON,
    .daemonize = false,
    .fail = true,
    .high_priority = true,
    .nice_level = -11,
    .realtime_scheduling = true,
    .realtime_priority = 5,  /* Half of JACK's default rtprio */
    .disallow_module_loading = false,
    .disallow_exit = false,
    .flat_volumes = true,
    .exit_idle_time = 20,
    .scache_idle_time = 20,
    .script_commands = NULL,
    .dl_search_path = NULL,
    .load_default_script_file = true,
    .default_script_file = NULL,
    .log_target = NULL,
    .log_level = PA_LOG_NOTICE,
    .log_backtrace = 0,
    .log_meta = false,
    .log_time = false,
    .resample_method = PA_RESAMPLER_AUTO,
    .disable_remixing = false,
    .disable_lfe_remixing = false,
    .lfe_crossover_freq = 120,
    .config_file = NULL,
    .use_pid_file = true,
    .system_instance = false,
#ifdef HAVE_DBUS
    .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
#endif
    .no_cpu_limit = true,
    .disable_shm = false,
    .lock_memory = false,
    .deferred_volume = true,
    .default_n_fragments = 4,
    .default_fragment_size_msec = 25,
    .deferred_volume_safety_margin_usec = 8000,
    .deferred_volume_extra_delay_usec = 0,
    .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
    .alternate_sample_rate = 48000,
    .default_channel_map = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
    .shm_size = 0
#ifdef HAVE_SYS_RESOURCE_H
   ,.rlimit_fsize = { .value = 0, .is_set = false },
    .rlimit_data = { .value = 0, .is_set = false },
    .rlimit_stack = { .value = 0, .is_set = false },
    .rlimit_core = { .value = 0, .is_set = false }
#ifdef RLIMIT_RSS
   ,.rlimit_rss = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_NPROC
   ,.rlimit_nproc = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_NOFILE
   ,.rlimit_nofile = { .value = 256, .is_set = true }
#endif
#ifdef RLIMIT_MEMLOCK
   ,.rlimit_memlock = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_AS
   ,.rlimit_as = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_LOCKS
   ,.rlimit_locks = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_SIGPENDING
   ,.rlimit_sigpending = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_MSGQUEUE
   ,.rlimit_msgqueue = { .value = 0, .is_set = false }
#endif
#ifdef RLIMIT_NICE
   ,.rlimit_nice = { .value = 31, .is_set = true }     /* nice level of -11 */
#endif
#ifdef RLIMIT_RTPRIO
   ,.rlimit_rtprio = { .value = 9, .is_set = true }    /* One below JACK's default for the server */
#endif
#ifdef RLIMIT_RTTIME
   ,.rlimit_rttime = { .value = 200*PA_USEC_PER_MSEC, .is_set = true } /* rtkit's limit is 200 ms */
#endif
#endif
};

Some important default configurations is that the daemon does not daemonize by default. It assumes a user instance, rather than a system instance. shared memory is enabled by default. And PA is very silent by default.

Prepare for modules support

It seems PulseAudio uses libtootl for loading modules.

    LTDL_SET_PRELOADED_SYMBOLS();
    pa_ltdl_init();
    ltdl_init = true;

    if (conf->dl_search_path)
        lt_dlsetsearchpath(conf->dl_search_path);

This code basically calls lt_dlinit, which libtool requires before making any call to its APIs.

But PulseAudio does more stuff if PA_BIND_NOW is defined. (TODO: inspect this later)

Special command line parameters

PA does not go through normal execution paths if any of these parameters are given:

    switch (conf->cmd) {
        case PA_CMD_DUMP_MODULES:
            ...
        case PA_CMD_DUMP_CONF:
            ...
        case PA_CMD_DUMP_RESAMPLE_METHODS:
            ...
        case PA_CMD_HELP :
            ...
        case PA_CMD_VERSION :
            ...
        case PA_CMD_CHECK:
            ...
        case PA_CMD_KILL:
            ...
    }

This corresponds to --dump-modules, --dump-conf, --dump-resample-methods, --help, --version, --check, and --kill.

All of them are self explanatory, probably except the resample methods.

$ pulseaudio --dump-resample-methods
trivial
speex-float-0
speex-float-1
speex-float-2
speex-float-3
speex-float-4
speex-float-5
speex-float-6
speex-float-7
speex-float-8
speex-float-9
speex-float-10
speex-fixed-0
speex-fixed-1
speex-fixed-2
speex-fixed-3
speex-fixed-4
speex-fixed-5
speex-fixed-6
speex-fixed-7
speex-fixed-8
speex-fixed-9
speex-fixed-10
ffmpeg
auto
copy
peaks

Resampling is the process of providing a different "digital signal" presentation out of the underlying "continouous signal". Note: Is this true?

results matching ""

    No results matching ""