bluetooth: Only close SCO if status has changed
[pulseaudio-mirror.git] / src / utils / pacmd.c
blob4d07c4c2adf834cf35c511d80f9f3a80866ccdf3
1 /***
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <assert.h>
27 #include <signal.h>
28 #include <sys/socket.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <sys/un.h>
33 #include <locale.h>
35 #include <pulse/error.h>
36 #include <pulse/util.h>
37 #include <pulse/xmalloc.h>
38 #include <pulse/i18n.h>
40 #include <pulsecore/poll.h>
41 #include <pulsecore/macro.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/pid.h>
46 int main(int argc, char*argv[]) {
47 pid_t pid;
48 int fd = -1;
49 int ret = 1, i;
50 struct sockaddr_un sa;
51 char ibuf[PIPE_BUF], obuf[PIPE_BUF];
52 size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
53 char *cli;
54 pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed;
55 struct pollfd pollfd[3];
56 struct pollfd *watch_socket, *watch_stdin, *watch_stdout;
58 int stdin_type = 0, stdout_type = 0, fd_type = 0;
60 setlocale(LC_ALL, "");
61 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
63 if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) {
64 pa_log(_("No PulseAudio daemon running, or not running as session daemon."));
65 goto fail;
68 if ((fd = pa_socket_cloexec(PF_UNIX, SOCK_STREAM, 0)) < 0) {
69 pa_log(_("socket(PF_UNIX, SOCK_STREAM, 0): %s"), strerror(errno));
70 goto fail;
73 pa_zero(sa);
74 sa.sun_family = AF_UNIX;
76 if (!(cli = pa_runtime_path("cli")))
77 goto fail;
79 pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path));
80 pa_xfree(cli);
82 for (i = 0; i < 5; i++) {
83 int r;
85 if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) {
86 pa_log(_("connect(): %s"), strerror(errno));
87 goto fail;
90 if (r >= 0)
91 break;
93 if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) {
94 pa_log(_("Failed to kill PulseAudio daemon."));
95 goto fail;
98 pa_msleep(300);
101 if (i >= 5) {
102 pa_log(_("Daemon not responding."));
103 goto fail;
106 ibuf_index = ibuf_length = obuf_index = obuf_length = 0;
107 ibuf_eof = obuf_eof = ibuf_closed = obuf_closed = FALSE;
109 if (argc > 1) {
110 for (i = 1; i < argc; i++) {
111 size_t k;
113 k = PA_MIN(sizeof(ibuf) - ibuf_length, strlen(argv[i]));
114 memcpy(ibuf + ibuf_length, argv[i], k);
115 ibuf_length += k;
117 if (ibuf_length < sizeof(ibuf)) {
118 ibuf[ibuf_length] = i < argc-1 ? ' ' : '\n';
119 ibuf_length++;
123 ibuf_eof = TRUE;
126 for (;;) {
127 struct pollfd *p;
129 if (ibuf_eof &&
130 obuf_eof &&
131 ibuf_length <= 0 &&
132 obuf_length <= 0)
133 break;
135 if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
136 shutdown(fd, SHUT_WR);
137 ibuf_closed = TRUE;
140 if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
141 shutdown(fd, SHUT_RD);
142 obuf_closed = TRUE;
145 pa_zero(pollfd);
147 p = pollfd;
149 if (ibuf_length > 0 || (!obuf_eof && obuf_length <= 0)) {
150 watch_socket = p++;
151 watch_socket->fd = fd;
152 watch_socket->events =
153 (ibuf_length > 0 ? POLLOUT : 0) |
154 (!obuf_eof && obuf_length <= 0 ? POLLIN : 0);
155 } else
156 watch_socket = NULL;
158 if (!ibuf_eof && ibuf_length <= 0) {
159 watch_stdin = p++;
160 watch_stdin->fd = STDIN_FILENO;
161 watch_stdin->events = POLLIN;
162 } else
163 watch_stdin = NULL;
165 if (obuf_length > 0) {
166 watch_stdout = p++;
167 watch_stdout->fd = STDOUT_FILENO;
168 watch_stdout->events = POLLOUT;
169 } else
170 watch_stdout = NULL;
172 if (pa_poll(pollfd, p-pollfd, -1) < 0) {
174 if (errno == EINTR)
175 continue;
177 pa_log(_("poll(): %s"), strerror(errno));
178 goto fail;
181 if (watch_stdin) {
182 if (watch_stdin->revents & POLLIN) {
183 ssize_t r;
184 pa_assert(ibuf_length <= 0);
186 if ((r = pa_read(STDIN_FILENO, ibuf, sizeof(ibuf), &stdin_type)) <= 0) {
187 if (r < 0) {
188 pa_log(_("read(): %s"), strerror(errno));
189 goto fail;
192 ibuf_eof = TRUE;
193 } else {
194 ibuf_length = (size_t) r;
195 ibuf_index = 0;
197 } else if (watch_stdin->revents & POLLHUP)
198 ibuf_eof = TRUE;
201 if (watch_socket) {
202 if (watch_socket->revents & POLLIN) {
203 ssize_t r;
204 pa_assert(obuf_length <= 0);
206 if ((r = pa_read(fd, obuf, sizeof(obuf), &fd_type)) <= 0) {
207 if (r < 0) {
208 pa_log(_("read(): %s"), strerror(errno));
209 goto fail;
212 obuf_eof = TRUE;
213 } else {
214 obuf_length = (size_t) r;
215 obuf_index = 0;
217 } else if (watch_socket->revents & POLLHUP)
218 obuf_eof = TRUE;
221 if (watch_stdout) {
222 if (watch_stdout->revents & POLLHUP) {
223 obuf_eof = TRUE;
224 obuf_length = 0;
225 } else if (watch_stdout->revents & POLLOUT) {
226 ssize_t r;
227 pa_assert(obuf_length > 0);
229 if ((r = pa_write(STDOUT_FILENO, obuf + obuf_index, obuf_length, &stdout_type)) < 0) {
230 pa_log(_("write(): %s"), strerror(errno));
231 goto fail;
234 obuf_length -= (size_t) r;
235 obuf_index += obuf_index;
239 if (watch_socket) {
240 if (watch_socket->revents & POLLHUP) {
241 ibuf_eof = TRUE;
242 ibuf_length = 0;
243 } if (watch_socket->revents & POLLOUT) {
244 ssize_t r;
245 pa_assert(ibuf_length > 0);
247 if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, &fd_type)) < 0) {
248 pa_log(_("write(): %s"), strerror(errno));
249 goto fail;
252 ibuf_length -= (size_t) r;
253 ibuf_index += obuf_index;
258 ret = 0;
260 fail:
261 if (fd >= 0)
262 pa_close(fd);
264 return ret;