From 70007175d28cf4c7323e772683bbe084e62df024 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 7 Sep 2004 17:06:54 +0000 Subject: implemented new CLI command: dump add prefork() and postfork() arguments to pa_context_connect_spawn() git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@184 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 9 ++--- polyp/cli-command.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ polyp/pacat.c | 2 +- polyp/polypaudio.pa | 12 +++---- polyp/polyplib-context.c | 19 ++++++++-- polyp/polyplib-context.h | 14 +++++--- 6 files changed, 130 insertions(+), 20 deletions(-) diff --git a/doc/todo b/doc/todo index f8a5ce86..4232a4d4 100644 --- a/doc/todo +++ b/doc/todo @@ -1,6 +1,8 @@ *** $Id$ *** -*** 0.4 *** +- add FAQ + +*** 0.5 *** - make mcalign merge chunks - use ref counting in more objects (i.e. sink, source, sink_input, source_output) - unix socket directories include user name @@ -12,11 +14,6 @@ - add sample directory - config file for command line arguments -- add FAQ -- pa_context_connect_spawn(): change function to fork+exec+waitpid-like function -- on delete event in paman -- add feature to dump config file - ** later *** - xmlrpc/http - dbus diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 4c4f566b..52926199 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -82,6 +82,7 @@ static int pa_cli_command_play_file(struct pa_core *c, struct pa_tokenizer *t, s static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_add(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static int pa_cli_command_autoload_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose); static const struct command commands[] = { { "exit", pa_cli_command_exit, "Terminate the daemon", 1 }, @@ -115,6 +116,7 @@ static const struct command commands[] = { { "autoload_source_add", pa_cli_command_autoload_add, "Add autoload entry for a source (args: source, name, arguments)", 4}, { "autoload_sink_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a sink (args: sink)", 2}, { "autoload_source_remove", pa_cli_command_autoload_remove, "Remove autoload entry for a source (args: source)", 2}, + { "dump", pa_cli_command_dump, "Dump daemon configuration", 1}, { NULL, NULL, NULL, 0 } }; @@ -596,6 +598,98 @@ static int pa_cli_command_autoload_list(struct pa_core *c, struct pa_tokenizer * return 0; } +static int pa_cli_command_dump(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) { + struct pa_module *m; + struct pa_sink *s; + int nl; + const char *p; + uint32_t index; + char txt[256]; + time_t now; + void *i; + struct pa_autoload_entry *a; + + assert(c && t); + + time(&now); + + pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt)); + + + for (m = pa_idxset_first(c->modules, &index); m; m = pa_idxset_next(c->modules, &index)) { + if (m->auto_unload) + continue; + + pa_strbuf_printf(buf, "load %s", m->name); + + if (m->argument) + pa_strbuf_printf(buf, " %s", m->argument); + + pa_strbuf_puts(buf, "\n"); + } + + nl = 0; + + for (s = pa_idxset_first(c->sinks, &index); s; s = pa_idxset_next(c->sinks, &index)) { + if (s->volume == PA_VOLUME_NORM) + continue; + + if (s->owner && s->owner->auto_unload) + continue; + + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + + pa_strbuf_printf(buf, "sink_volume %s 0x%03x\n", s->name, s->volume); + } + + + if (c->autoload_hashmap) { + nl = 0; + + i = NULL; + while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i))) { + + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + + pa_strbuf_printf(buf, "autoload_%s_add %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module); + + if (a->argument) + pa_strbuf_printf(buf, " %s", a->argument); + + pa_strbuf_puts(buf, "\n"); + } + } + + nl = 0; + + if ((p = pa_namereg_get_default_sink_name(c))) { + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + pa_strbuf_printf(buf, "sink_default %s\n", p); + } + + if ((p = pa_namereg_get_default_source_name(c))) { + if (!nl) { + pa_strbuf_puts(buf, "\n"); + nl = 1; + } + pa_strbuf_printf(buf, "source_default %s\n", p); + } + + pa_strbuf_puts(buf, "\n### EOF\n"); + + return 0; +} + + int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) { const char *cs; diff --git a/polyp/pacat.c b/polyp/pacat.c index 40301be8..0ad5fa52 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -357,7 +357,7 @@ int main(int argc, char *argv[]) { pa_context_set_state_callback(context, context_state_callback, NULL); /* Connect the context */ - pa_context_connect_spawn(context, NULL); + pa_context_connect_spawn(context, NULL, NULL, NULL); /* Run the main loop */ if (pa_mainloop_run(m, &ret) < 0) { diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index 40012fd6..15434627 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -28,15 +28,15 @@ load module-oss device="/dev/dsp" sink_name=output source_name=input record=0 # Load audio drivers automatically on access -#autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input -#autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input +#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input +#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-alsa-sink sink_name=output #autoload_source_add input module-alsa-source source_name=input # Load several protocols -#load module-esound-protocol-tcp +load module-esound-protocol-tcp #load module-simple-protocol-tcp load module-native-protocol-unix #load module-cli-protocol-unix @@ -46,8 +46,8 @@ load module-native-protocol-unix load module-cli # Make some devices default -#isink_default output -#source_default input +sink_default output +source_default input .nofail @@ -55,7 +55,7 @@ load module-cli scache_load /usr/share/sounds/KDE_Notify.wav x11-bell # Load X11 bell module -#load module-x11-bell sample=x11-bell sink=output +load module-x11-bell sample=x11-bell sink=output #load module-pipe-source #load module-pipe-sink diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c index a810bd98..caaa1dbb 100644 --- a/polyp/polyplib-context.c +++ b/polyp/polyplib-context.c @@ -571,9 +571,9 @@ static int is_running(void) { return 1; } -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)) { pid_t pid; - int status; + int status, r; int fds[2] = { -1, -1} ; struct pa_iochannel *io; @@ -586,9 +586,16 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { goto fail; } + if (prefork) + prefork(); + if ((pid = fork()) < 0) { pa_log(__FILE__": fork() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); + + if (postfork) + postfork(); + goto fail; } else if (!pid) { char t[64]; @@ -610,7 +617,13 @@ int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)) { } /* Parent */ - if (waitpid(pid, &status, 0) < 0) { + + r = waitpid(pid, &status, 0); + + if (postfork) + postfork(); + + if (r < 0) { pa_log(__FILE__": waitpid() failed: %s\n", strerror(errno)); pa_context_fail(c, PA_ERROR_INTERNAL); goto fail; diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h index 65befbb3..4b199751 100644 --- a/polyp/polyplib-context.h +++ b/polyp/polyplib-context.h @@ -82,10 +82,16 @@ int pa_context_connect(struct pa_context *c, const char *server); /** Connect the context to a server. If the default server is local * but not accessible, spawn a new daemon. If atfork is not NULL it is * run after the fork() in the child process. It may be used to close - * file descriptors or to do any other cleanups. Make sure that - * SIGCHLD is handled when calling this function. The function will - * waitpid() on the daemon's PID. \since 0.4 */ -int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void)); + * file descriptors or to do any other cleanups. (It is not safe to + * close all file descriptors unconditionally, since a UNIX socket is + * passed to the new process.) if prefork is not NULL it is run just + * before forking in the parent process. Use this to block SIGCHLD + * handling if required. If postfork is not NULL it is run just after + * forking in the parent process. Use this to unblock SIGCHLD if + * required. The function will waitpid() on the daemon's PID, but + * will not block or ignore SIGCHLD signals, since this cannot be done + * in a thread compatible way. \since 0.4 */ +int pa_context_connect_spawn(struct pa_context *c, void (*atfork)(void), void (*prefork)(void), void (*postfork)(void)); /** Terminate the context connection immediately */ void pa_context_disconnect(struct pa_context *c); -- cgit