]> code.delx.au - pulseaudio/blob - src/utils/pacmd.c
Merge commit 'origin/master-tx'
[pulseaudio] / src / utils / pacmd.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5
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.
10
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.
15
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 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <assert.h>
27 #include <signal.h>
28 #include <sys/select.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/un.h>
34 #include <locale.h>
35
36 #include <pulse/error.h>
37 #include <pulse/util.h>
38 #include <pulse/xmalloc.h>
39 #include <pulse/i18n.h>
40
41 #include <pulsecore/macro.h>
42 #include <pulsecore/core-util.h>
43 #include <pulsecore/log.h>
44 #include <pulsecore/pid.h>
45
46 int main(int argc, char*argv[]) {
47
48 pid_t pid ;
49 int fd = -1;
50 int ret = 1, i;
51 struct sockaddr_un sa;
52 char ibuf[PIPE_BUF], obuf[PIPE_BUF];
53 size_t ibuf_index, ibuf_length, obuf_index, obuf_length;
54 char *cli;
55 pa_bool_t ibuf_eof, obuf_eof, ibuf_closed, obuf_closed;
56
57 setlocale(LC_ALL, "");
58 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
59
60 if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) {
61 pa_log(_("No PulseAudio daemon running, or not running as session daemon."));
62 goto fail;
63 }
64
65 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
66 pa_log(_("socket(PF_UNIX, SOCK_STREAM, 0): %s"), strerror(errno));
67 goto fail;
68 }
69
70 pa_zero(sa);
71 sa.sun_family = AF_UNIX;
72
73 if (!(cli = pa_runtime_path("cli")))
74 goto fail;
75
76 pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path));
77 pa_xfree(cli);
78
79 for (i = 0; i < 5; i++) {
80 int r;
81
82 if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) {
83 pa_log(_("connect(): %s"), strerror(errno));
84 goto fail;
85 }
86
87 if (r >= 0)
88 break;
89
90 if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) {
91 pa_log(_("Failed to kill PulseAudio daemon."));
92 goto fail;
93 }
94
95 pa_msleep(300);
96 }
97
98 if (i >= 5) {
99 pa_log(_("Daemon not responding."));
100 goto fail;
101 }
102
103 ibuf_index = ibuf_length = obuf_index = obuf_length = 0;
104 ibuf_eof = obuf_eof = ibuf_closed = obuf_closed = FALSE;
105
106 if (argc > 1) {
107 for (i = 1; i < argc; i++) {
108 size_t k;
109
110 k = PA_MIN(sizeof(ibuf) - ibuf_length, strlen(argv[i]));
111 memcpy(ibuf + ibuf_length, argv[1], k);
112 ibuf_length += k;
113
114 if (ibuf_length < sizeof(ibuf)) {
115 ibuf[ibuf_length] = i < argc-1 ? ' ' : '\n';
116 ibuf_length++;
117 }
118 }
119
120 ibuf_eof = TRUE;
121 }
122
123 for (;;) {
124 fd_set ifds, ofds;
125
126 if (ibuf_eof &&
127 obuf_eof &&
128 ibuf_length <= 0 &&
129 obuf_length <= 0)
130 break;
131
132 FD_ZERO(&ifds);
133 FD_ZERO(&ofds);
134
135 if (obuf_length > 0)
136 FD_SET(1, &ofds);
137 else if (!obuf_eof)
138 FD_SET(fd, &ifds);
139
140 if (ibuf_length > 0)
141 FD_SET(fd, &ofds);
142 else if (!ibuf_eof)
143 FD_SET(0, &ifds);
144
145 if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) {
146 pa_log(_("select(): %s"), strerror(errno));
147 goto fail;
148 }
149
150 if (FD_ISSET(0, &ifds)) {
151 ssize_t r;
152 pa_assert(!ibuf_length);
153
154 if ((r = pa_read(0, ibuf, sizeof(ibuf), NULL)) <= 0) {
155 if (r < 0) {
156 pa_log(_("read(): %s"), strerror(errno));
157 goto fail;
158 }
159
160 ibuf_eof = TRUE;
161 } else {
162 ibuf_length = (size_t) r;
163 ibuf_index = 0;
164 }
165 }
166
167 if (FD_ISSET(fd, &ifds)) {
168 ssize_t r;
169 pa_assert(!obuf_length);
170
171 if ((r = pa_read(fd, obuf, sizeof(obuf), NULL)) <= 0) {
172 if (r < 0) {
173 pa_log(_("read(): %s"), strerror(errno));
174 goto fail;
175 }
176
177 obuf_eof = TRUE;
178 } else {
179 obuf_length = (size_t) r;
180 obuf_index = 0;
181 }
182 }
183
184 if (FD_ISSET(1, &ofds)) {
185 ssize_t r;
186 pa_assert(obuf_length);
187
188 if ((r = pa_write(1, obuf + obuf_index, obuf_length, NULL)) < 0) {
189 pa_log(_("write(): %s"), strerror(errno));
190 goto fail;
191 }
192
193 obuf_length -= (size_t) r;
194 obuf_index += obuf_index;
195
196 }
197
198 if (FD_ISSET(fd, &ofds)) {
199 ssize_t r;
200 pa_assert(ibuf_length);
201
202 if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, NULL)) < 0) {
203 pa_log(_("write(): %s"), strerror(errno));
204 goto fail;
205 }
206
207 ibuf_length -= (size_t) r;
208 ibuf_index += obuf_index;
209 }
210
211 if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) {
212 pa_close(0);
213 shutdown(fd, SHUT_WR);
214 ibuf_closed = TRUE;
215 }
216
217 if (obuf_length <= 0 && obuf_eof && !obuf_closed) {
218 shutdown(fd, SHUT_RD);
219 pa_close(1);
220 obuf_closed = TRUE;
221 }
222 }
223
224 ret = 0;
225
226 fail:
227 if (fd >= 0)
228 pa_close(fd);
229
230 return ret;
231 }