2 * This file is part of DisOrder.
3 * Copyright (C) 2005, 2006, 2007, 2009 Richard Kettlewell
4 * Portions (C) 2007 Mark Wooding
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /** @file lib/uaudio-command.c
20 * @brief Support for commmand backend */
32 /** @brief Pipe to subprocess */
33 static int command_fd
;
35 /** @brief Child process ID */
36 static pid_t command_pid
;
38 static const char *const command_options
[] = {
43 /** @brief Close pipe and wait for subprocess to terminate */
44 static void command_wait(void) {
50 while((rc
= waitpid(command_pid
, &w
, 0) < 0 && errno
== EINTR
))
53 fatal(errno
, "waitpid");
56 error(0, "command subprocess %s", ws
);
61 /** @brief Create subprocess */
62 static void command_open(void) {
66 if(!(command
= uaudio_get("command")))
67 fatal(0, "'command' not set");
69 command_pid
= xfork();
72 signal(SIGPIPE
, SIG_DFL
);
76 /* TODO it would be nice to set some environment variables given the sample
77 * format. The original intended model is that you adapt DisOrder to the
78 * command you run but it'd be nice to support the opposite. */
79 execl("/bin/sh", "sh", "-c", command
, (char *)0);
80 fatal(errno
, "error executing /bin/sh");
86 /** @brief Send audio data to subprocess */
87 static size_t command_play(void *buffer
, size_t nsamples
) {
88 const size_t bytes
= nsamples
* uaudio_sample_size
;
89 int written
= write(command_fd
, buffer
, bytes
);
93 return 0; /* will retry */
95 error(0, "audio command subprocess terminated");
98 return 0; /* will retry */
100 fatal(errno
, "error writing to audio command subprocess");
103 return written
/ uaudio_sample_size
;
106 static void command_start(uaudio_callback
*callback
,
109 uaudio_thread_start(callback
,
113 4096 / uaudio_sample_size
);
116 static void command_stop(void) {
117 uaudio_thread_stop();
121 static void command_activate(void) {
122 uaudio_thread_activate();
125 static void command_deactivate(void) {
126 uaudio_thread_deactivate();
129 const struct uaudio uaudio_command
= {
131 .options
= command_options
,
132 .start
= command_start
,
133 .stop
= command_stop
,
134 .activate
= command_activate
,
135 .deactivate
= command_deactivate