Mercurial > audlegacy
annotate audacious/controlsocket.c @ 1577:18edacaa3126 trunk
[svn] - installing Container plugins might help!
author | nenolod |
---|---|
date | Fri, 11 Aug 2006 18:41:53 -0700 |
parents | 06329cbf186a |
children | dae6b30c0148 |
rev | line source |
---|---|
0 | 1 /* BMP - Cross-platform multimedia player |
2 * Copyright (C) 2003-2004 BMP development team. | |
3 * | |
4 * Based on XMMS: | |
5 * Copyright (C) 1998-2003 XMMS development team. | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
1459 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
0 | 20 */ |
21 | |
22 #include "controlsocket.h" | |
23 | |
24 #include <glib.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
27 | |
28 #include <unistd.h> | |
29 #include <errno.h> | |
30 #include <sys/time.h> | |
31 #include <sys/types.h> | |
32 #include <sys/socket.h> | |
33 #include <sys/un.h> | |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
34 #include <arpa/inet.h> |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
35 #include <netdb.h> |
0 | 36 |
37 #include "main.h" | |
38 #include "equalizer.h" | |
39 #include "mainwin.h" | |
40 #include "input.h" | |
538
e4e897d20791
[svn] remove libaudcore, we never did anything with it
nenolod
parents:
383
diff
changeset
|
41 #include "playback.h" |
0 | 42 #include "playlist.h" |
383 | 43 #include "ui_playlist.h" |
0 | 44 #include "prefswin.h" |
45 #include "libaudacious/beepctrl.h" | |
46 | |
47 | |
48 #define CTRLSOCKET_BACKLOG 100 | |
49 #define CTRLSOCKET_TIMEOUT 100000 | |
50 | |
51 | |
52 static gint session_id = 0; | |
53 | |
54 static gint ctrl_fd = 0; | |
55 static gchar *socket_name = NULL; | |
56 | |
57 static gpointer ctrlsocket_func(gpointer); | |
58 static GThread *ctrlsocket_thread; | |
59 | |
60 static GList *packet_list = NULL; | |
61 static GMutex *packet_list_mutex = NULL; | |
62 | |
63 static gboolean started = FALSE; | |
64 static gboolean going = TRUE; | |
65 static GCond *start_cond = NULL; | |
66 static GMutex *status_mutex = NULL; | |
67 | |
68 | |
69 static void | |
70 ctrlsocket_start_thread(void) | |
71 { | |
72 start_cond = g_cond_new(); | |
73 status_mutex = g_mutex_new(); | |
74 packet_list_mutex = g_mutex_new(); | |
75 | |
76 ctrlsocket_thread = g_thread_create(ctrlsocket_func, NULL, TRUE, NULL); | |
77 } | |
78 | |
79 gboolean | |
80 ctrlsocket_setup(void) | |
81 { | |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
82 audacious_set_session_uri(cfg.session_uri_base); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
83 |
1453 | 84 if (cfg.session_uri_base == NULL) |
85 return ctrlsocket_setup_unix(); | |
86 | |
87 if (!g_strncasecmp(cfg.session_uri_base, "tcp://", 6)) | |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
88 return ctrlsocket_setup_tcp(); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
89 |
1443 | 90 return ctrlsocket_setup_unix(); |
91 } | |
92 | |
93 gboolean | |
94 ctrlsocket_setup_unix(void) | |
95 { | |
0 | 96 struct sockaddr_un saddr; |
97 gint i; | |
98 gint fd; | |
99 | |
1456
6fe7ba6e5489
[svn] - Don't poll the config database if not using TCP sockets.
nhjm449
parents:
1454
diff
changeset
|
100 audacious_set_session_type((gint *) AUDACIOUS_TYPE_UNIX); |
6fe7ba6e5489
[svn] - Don't poll the config database if not using TCP sockets.
nhjm449
parents:
1454
diff
changeset
|
101 |
0 | 102 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { |
103 g_critical("ctrlsocket_setup(): Failed to open socket: %s", | |
104 strerror(errno)); | |
105 return FALSE; | |
106 } | |
107 | |
108 for (i = 0;; i++) { | |
109 saddr.sun_family = AF_UNIX; | |
110 g_snprintf(saddr.sun_path, sizeof(saddr.sun_path), | |
111 "%s/%s_%s.%d", g_get_tmp_dir(), | |
112 CTRLSOCKET_NAME, g_get_user_name(), i); | |
113 | |
114 if (xmms_remote_is_running(i)) { | |
115 if (cfg.allow_multiple_instances) | |
116 continue; | |
117 break; | |
118 } | |
119 | |
120 if ((unlink(saddr.sun_path) == -1) && errno != ENOENT) { | |
121 g_critical | |
122 ("ctrlsocket_setup(): Failed to unlink %s (Error: %s)", | |
123 saddr.sun_path, strerror(errno)); | |
124 break; | |
125 } | |
126 | |
127 if (bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { | |
128 g_critical | |
129 ("ctrlsocket_setup(): Failed to assign %s to a socket (Error: %s)", | |
130 saddr.sun_path, strerror(errno)); | |
131 break; | |
132 } | |
133 | |
134 listen(fd, CTRLSOCKET_BACKLOG); | |
135 | |
136 socket_name = g_strdup(saddr.sun_path); | |
137 ctrl_fd = fd; | |
138 session_id = i; | |
139 going = TRUE; | |
140 | |
141 ctrlsocket_start_thread(); | |
142 | |
143 return TRUE; | |
144 } | |
145 | |
146 close(fd); | |
147 | |
148 return FALSE; | |
149 } | |
150 | |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
151 gboolean |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
152 ctrlsocket_setup_tcp(void) |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
153 { |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
154 struct sockaddr_in saddr; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
155 gint i; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
156 gint fd; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
157 |
1456
6fe7ba6e5489
[svn] - Don't poll the config database if not using TCP sockets.
nhjm449
parents:
1454
diff
changeset
|
158 audacious_set_session_type((gint *) AUDACIOUS_TYPE_TCP); |
6fe7ba6e5489
[svn] - Don't poll the config database if not using TCP sockets.
nhjm449
parents:
1454
diff
changeset
|
159 |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
160 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
161 g_critical("ctrlsocket_setup(): Failed to open socket: %s", |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
162 strerror(errno)); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
163 return FALSE; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
164 } |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
165 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
166 for (i = 0;; i++) { |
1454 | 167 memset(&saddr, '\0', sizeof(saddr)); |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
168 saddr.sin_family = AF_INET; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
169 saddr.sin_port = htons(37370 + i); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
170 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
171 if (xmms_remote_is_running(i)) { |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
172 if (cfg.allow_multiple_instances) |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
173 continue; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
174 break; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
175 } |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
176 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
177 if (bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) { |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
178 g_critical |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
179 ("ctrlsocket_setup(): Failed to bind the socket (Error: %s)", |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
180 strerror(errno)); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
181 break; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
182 } |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
183 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
184 listen(fd, CTRLSOCKET_BACKLOG); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
185 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
186 ctrl_fd = fd; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
187 session_id = i; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
188 going = TRUE; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
189 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
190 ctrlsocket_start_thread(); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
191 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
192 return TRUE; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
193 } |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
194 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
195 close(fd); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
196 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
197 return FALSE; |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
198 } |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
199 |
0 | 200 gint |
201 ctrlsocket_get_session_id(void) | |
202 { | |
203 return session_id; | |
204 } | |
205 | |
206 void | |
207 ctrlsocket_cleanup(void) | |
208 { | |
209 if (ctrl_fd) { | |
210 g_mutex_lock(status_mutex); | |
211 going = FALSE; | |
212 g_cond_signal(start_cond); | |
213 g_mutex_unlock(status_mutex); | |
214 | |
215 /* wait for ctrlsocket_thread to terminate */ | |
216 g_thread_join(ctrlsocket_thread); | |
217 | |
218 /* close and remove socket */ | |
219 close(ctrl_fd); | |
220 ctrl_fd = 0; | |
1444
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
221 |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
222 if (socket_name != NULL) |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
223 { |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
224 unlink(socket_name); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
225 g_free(socket_name); |
c04ce16b2b57
[svn] - libaudacious/beepctrl.c: optimise further and be more paranoid about leaks
nenolod
parents:
1443
diff
changeset
|
226 } |
0 | 227 |
228 g_cond_free(start_cond); | |
229 g_mutex_free(status_mutex); | |
230 g_mutex_free(packet_list_mutex); | |
231 } | |
232 } | |
233 | |
234 void | |
235 ctrlsocket_start(void) | |
236 { | |
237 /* tell control socket thread to go 'live' i.e. start handling | |
238 * packets */ | |
239 g_mutex_lock(status_mutex); | |
240 started = TRUE; | |
241 g_cond_signal(start_cond); | |
242 g_mutex_unlock(status_mutex); | |
243 } | |
244 | |
245 static gint | |
246 write_all(gint fd, gconstpointer buf, size_t count) | |
247 { | |
248 size_t left = count; | |
249 GTimer *timer; | |
250 gulong usec; | |
251 gint written; | |
252 | |
253 timer = g_timer_new(); | |
254 | |
255 do { | |
256 if ((written = write(fd, buf, left)) < 0) { | |
257 count = -1; | |
258 break; | |
259 } | |
260 left -= written; | |
261 buf = (gchar *) buf + written; | |
262 g_timer_elapsed(timer, &usec); | |
263 } | |
264 while (left > 0 && usec <= CTRLSOCKET_IO_TIMEOUT_USEC); | |
265 | |
266 g_timer_destroy(timer); | |
267 return count - left; | |
268 } | |
269 | |
270 static void | |
271 ctrl_write_packet(gint fd, gpointer data, gint length) | |
272 { | |
273 ServerPktHeader pkthdr; | |
274 | |
275 pkthdr.version = XMMS_PROTOCOL_VERSION; | |
276 pkthdr.data_length = length; | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
277 if ((size_t)write_all(fd, &pkthdr, sizeof(ServerPktHeader)) < sizeof(pkthdr)) |
0 | 278 return; |
279 if (data && length > 0) | |
280 write_all(fd, data, length); | |
281 } | |
282 | |
283 static void | |
284 ctrl_write_gint(gint fd, gint val) | |
285 { | |
286 ctrl_write_packet(fd, &val, sizeof(gint)); | |
287 } | |
288 | |
289 static void | |
290 ctrl_write_gfloat(gint fd, gfloat val) | |
291 { | |
292 ctrl_write_packet(fd, &val, sizeof(gfloat)); | |
293 } | |
294 | |
295 static void | |
296 ctrl_write_gboolean(gint fd, gboolean bool) | |
297 { | |
298 ctrl_write_packet(fd, &bool, sizeof(gboolean)); | |
299 } | |
300 | |
301 static void | |
302 ctrl_write_string(gint fd, gchar * string) | |
303 { | |
304 ctrl_write_packet(fd, string, string ? strlen(string) + 1 : 0); | |
305 } | |
306 | |
307 static void | |
308 ctrl_ack_packet(PacketNode * pkt) | |
309 { | |
310 ctrl_write_packet(pkt->fd, NULL, 0); | |
311 close(pkt->fd); | |
312 if (pkt->data) | |
313 g_free(pkt->data); | |
314 g_free(pkt); | |
315 } | |
316 | |
317 static gint | |
318 read_all(gint fd, gpointer buf, size_t count) | |
319 { | |
320 size_t left = count; | |
321 GTimer *timer; | |
322 gulong usec; | |
323 gint r; | |
324 | |
325 timer = g_timer_new(); | |
326 | |
327 do { | |
328 if ((r = read(fd, buf, left)) < 0) { | |
329 count = -1; | |
330 break; | |
331 } | |
332 left -= r; | |
333 buf = (gchar *) buf + r; | |
334 g_timer_elapsed(timer, &usec); | |
335 } | |
336 while (left > 0 && usec <= CTRLSOCKET_IO_TIMEOUT_USEC); | |
337 | |
338 g_timer_destroy(timer); | |
339 return count - left; | |
340 } | |
341 | |
342 static gboolean | |
343 ctrlsocket_is_going(void) | |
344 { | |
345 gboolean result; | |
346 | |
347 g_mutex_lock(status_mutex); | |
348 result = going; | |
349 g_mutex_unlock(status_mutex); | |
350 | |
351 return result; | |
352 } | |
353 | |
354 static gpointer | |
355 ctrlsocket_func(gpointer arg) | |
356 { | |
357 fd_set set; | |
358 struct timeval tv; | |
359 struct sockaddr_un saddr; | |
360 gint fd, b, i; | |
377 | 361 gint info[3]; |
0 | 362 gint32 v[2]; |
363 PacketNode *pkt; | |
364 socklen_t len; | |
365 gfloat fval[11]; | |
366 | |
367 g_mutex_lock(status_mutex); | |
368 while (!started && going) | |
369 g_cond_wait(start_cond, status_mutex); | |
370 g_mutex_unlock(status_mutex); | |
371 | |
372 while (ctrlsocket_is_going()) { | |
373 FD_ZERO(&set); | |
374 FD_SET(ctrl_fd, &set); | |
375 tv.tv_sec = 0; | |
376 tv.tv_usec = CTRLSOCKET_TIMEOUT; | |
377 len = sizeof(saddr); | |
378 if (select(ctrl_fd + 1, &set, NULL, NULL, &tv) <= 0) | |
379 continue; | |
380 if ((fd = accept(ctrl_fd, (struct sockaddr *) &saddr, &len)) == -1) | |
381 continue; | |
382 | |
383 pkt = g_new0(PacketNode, 1); | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
384 if ((size_t)read_all(fd, &pkt->hdr, sizeof(ClientPktHeader)) |
0 | 385 < sizeof(ClientPktHeader)) { |
386 g_free(pkt); | |
387 continue; | |
388 } | |
389 | |
390 if (pkt->hdr.data_length) { | |
391 size_t data_length = pkt->hdr.data_length; | |
392 pkt->data = g_malloc0(data_length); | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
393 if ((size_t)read_all(fd, pkt->data, data_length) < data_length) { |
0 | 394 g_free(pkt->data); |
395 g_free(pkt); | |
396 g_warning("ctrlsocket_func(): Incomplete data packet dropped"); | |
397 continue; | |
398 } | |
399 } | |
400 | |
401 pkt->fd = fd; | |
402 switch (pkt->hdr.command) { | |
403 case CMD_GET_VERSION: | |
404 ctrl_write_gint(pkt->fd, 0x09a3); | |
405 ctrl_ack_packet(pkt); | |
406 break; | |
407 case CMD_IS_PLAYING: | |
408 ctrl_write_gboolean(pkt->fd, bmp_playback_get_playing()); | |
409 ctrl_ack_packet(pkt); | |
410 break; | |
411 case CMD_IS_PAUSED: | |
412 ctrl_write_gboolean(pkt->fd, bmp_playback_get_paused()); | |
413 ctrl_ack_packet(pkt); | |
414 break; | |
415 case CMD_GET_PLAYLIST_POS: | |
416 ctrl_write_gint(pkt->fd, playlist_get_position()); | |
417 ctrl_ack_packet(pkt); | |
418 break; | |
419 case CMD_GET_PLAYLIST_LENGTH: | |
420 ctrl_write_gint(pkt->fd, playlist_get_length()); | |
421 ctrl_ack_packet(pkt); | |
422 break; | |
423 case CMD_GET_PLAYQUEUE_LENGTH: | |
424 ctrl_write_gint(pkt->fd, playlist_queue_get_length()); | |
425 ctrl_ack_packet(pkt); | |
426 break; | |
984 | 427 case CMD_PLAYQUEUE_IS_QUEUED: |
428 ctrl_write_gboolean(pkt->fd, | |
429 playlist_is_position_queued(*((guint32 *) pkt->data))); | |
430 ctrl_ack_packet(pkt); | |
431 break; | |
432 case CMD_PLAYQUEUE_GET_POS: | |
433 if (pkt->data) | |
434 ctrl_write_gint(pkt->fd, | |
435 playlist_get_queue_position_number(* | |
436 ((guint32 *) pkt-> | |
437 data))); | |
438 else | |
439 ctrl_write_gint(pkt->fd, 0); | |
440 | |
441 ctrl_ack_packet(pkt); | |
442 break; | |
443 case CMD_PLAYQUEUE_GET_QPOS: | |
444 if (pkt->data) | |
445 ctrl_write_gint(pkt->fd, | |
446 playlist_get_queue_qposition_number(* | |
447 ((guint32 *) pkt-> | |
448 data))); | |
449 else | |
450 ctrl_write_gint(pkt->fd, 0); | |
451 | |
452 ctrl_ack_packet(pkt); | |
453 break; | |
0 | 454 case CMD_GET_OUTPUT_TIME: |
455 if (bmp_playback_get_playing()) | |
456 ctrl_write_gint(pkt->fd, bmp_playback_get_time()); | |
457 else | |
458 ctrl_write_gint(pkt->fd, 0); | |
459 ctrl_ack_packet(pkt); | |
460 break; | |
461 case CMD_GET_VOLUME: | |
462 input_get_volume(&v[0], &v[1]); | |
463 ctrl_write_packet(pkt->fd, v, sizeof(v)); | |
464 ctrl_ack_packet(pkt); | |
465 break; | |
466 case CMD_GET_BALANCE: | |
467 input_get_volume(&v[0], &v[1]); | |
468 if (v[0] < 0 || v[1] < 0) | |
469 b = 0; | |
470 else if (v[0] > v[1]) | |
471 b = -100 + ((v[1] * 100) / v[0]); | |
472 else if (v[1] > v[0]) | |
473 b = 100 - ((v[0] * 100) / v[1]); | |
474 else | |
475 b = 0; | |
476 ctrl_write_gint(pkt->fd, b); | |
477 ctrl_ack_packet(pkt); | |
478 break; | |
479 case CMD_GET_SKIN: | |
480 ctrl_write_string(pkt->fd, bmp_active_skin->path); | |
481 ctrl_ack_packet(pkt); | |
482 break; | |
483 case CMD_GET_PLAYLIST_FILE: | |
484 if (pkt->data) { | |
485 gchar *filename; | |
486 filename = playlist_get_filename(*((guint32 *) pkt->data)); | |
487 ctrl_write_string(pkt->fd, filename); | |
488 g_free(filename); | |
489 } | |
490 else | |
491 ctrl_write_string(pkt->fd, NULL); | |
492 ctrl_ack_packet(pkt); | |
493 break; | |
494 case CMD_GET_PLAYLIST_TITLE: | |
495 if (pkt->data) { | |
496 gchar *title; | |
497 title = playlist_get_songtitle(*((guint32 *) pkt->data)); | |
498 ctrl_write_string(pkt->fd, title); | |
499 g_free(title); | |
500 } | |
501 else | |
502 ctrl_write_string(pkt->fd, NULL); | |
503 ctrl_ack_packet(pkt); | |
504 break; | |
505 case CMD_GET_PLAYLIST_TIME: | |
506 if (pkt->data) | |
507 ctrl_write_gint(pkt->fd, | |
508 playlist_get_songtime(* | |
509 ((guint32 *) pkt-> | |
510 data))); | |
511 else | |
512 ctrl_write_gint(pkt->fd, -1); | |
513 | |
514 ctrl_ack_packet(pkt); | |
515 break; | |
516 case CMD_GET_INFO: | |
517 playback_get_sample_params(&info[0], &info[1], &info[2]); | |
518 ctrl_write_packet(pkt->fd, info, 3 * sizeof(gint)); | |
519 ctrl_ack_packet(pkt); | |
520 break; | |
521 case CMD_GET_EQ_DATA: | |
522 case CMD_SET_EQ_DATA: | |
523 /* obsolete */ | |
524 ctrl_ack_packet(pkt); | |
525 break; | |
526 case CMD_PING: | |
527 ctrl_ack_packet(pkt); | |
528 break; | |
529 case CMD_PLAYLIST_ADD: | |
530 if (pkt->data) { | |
531 guint32 *dataptr = pkt->data; | |
532 while ((len = *dataptr) > 0) { | |
533 gchar *filename; | |
534 | |
535 dataptr++; | |
536 filename = g_malloc0(len); | |
537 memcpy(filename, dataptr, len); | |
538 | |
539 GDK_THREADS_ENTER(); | |
540 playlist_add_url(filename); | |
541 GDK_THREADS_LEAVE(); | |
542 | |
543 g_free(filename); | |
544 dataptr += (len + 3) / 4; | |
545 } | |
546 } | |
547 ctrl_ack_packet(pkt); | |
548 break; | |
549 case CMD_PLAYLIST_ADD_URL_STRING: | |
550 GDK_THREADS_ENTER(); | |
551 playlist_add_url(pkt->data); | |
552 GDK_THREADS_LEAVE(); | |
553 | |
554 ctrl_ack_packet(pkt); | |
555 break; | |
556 case CMD_PLAYLIST_INS_URL_STRING: | |
557 if (pkt->data) { | |
558 gint pos = *(gint *) pkt->data; | |
559 gchar *ptr = pkt->data; | |
560 ptr += sizeof(gint); | |
561 playlist_ins_url(ptr, pos); | |
562 } | |
563 ctrl_ack_packet(pkt); | |
564 break; | |
565 case CMD_PLAYLIST_DELETE: | |
566 GDK_THREADS_ENTER(); | |
567 playlist_delete_index(*((guint32 *) pkt->data)); | |
568 GDK_THREADS_LEAVE(); | |
569 ctrl_ack_packet(pkt); | |
570 break; | |
571 case CMD_PLAYLIST_CLEAR: | |
572 GDK_THREADS_ENTER(); | |
573 playlist_clear(); | |
574 mainwin_clear_song_info(); | |
575 mainwin_set_info_text(); | |
576 GDK_THREADS_LEAVE(); | |
577 ctrl_ack_packet(pkt); | |
578 break; | |
579 case CMD_IS_MAIN_WIN: | |
580 ctrl_write_gboolean(pkt->fd, cfg.player_visible); | |
581 ctrl_ack_packet(pkt); | |
582 break; | |
583 case CMD_IS_PL_WIN: | |
584 ctrl_write_gboolean(pkt->fd, cfg.playlist_visible); | |
585 ctrl_ack_packet(pkt); | |
586 break; | |
587 case CMD_IS_EQ_WIN: | |
588 ctrl_write_gboolean(pkt->fd, cfg.equalizer_visible); | |
589 ctrl_ack_packet(pkt); | |
590 break; | |
591 case CMD_IS_REPEAT: | |
592 ctrl_write_gboolean(pkt->fd, cfg.repeat); | |
593 ctrl_ack_packet(pkt); | |
594 break; | |
595 case CMD_IS_SHUFFLE: | |
596 ctrl_write_gboolean(pkt->fd, cfg.shuffle); | |
597 ctrl_ack_packet(pkt); | |
598 break; | |
599 case CMD_IS_ADVANCE: | |
600 ctrl_write_gboolean(pkt->fd, !cfg.no_playlist_advance); | |
601 ctrl_ack_packet(pkt); | |
602 break; | |
603 case CMD_GET_EQ: | |
604 fval[0] = equalizerwin_get_preamp(); | |
605 for (i = 0; i < 10; i++) | |
606 fval[i + 1] = equalizerwin_get_band(i); | |
607 ctrl_write_packet(pkt->fd, fval, 11 * sizeof(gfloat)); | |
608 ctrl_ack_packet(pkt); | |
609 break; | |
610 case CMD_GET_EQ_PREAMP: | |
611 ctrl_write_gfloat(pkt->fd, equalizerwin_get_preamp()); | |
612 ctrl_ack_packet(pkt); | |
613 break; | |
614 case CMD_GET_EQ_BAND: | |
615 i = *((guint32 *) pkt->data); | |
616 ctrl_write_gfloat(pkt->fd, equalizerwin_get_band(i)); | |
617 ctrl_ack_packet(pkt); | |
618 break; | |
619 default: | |
620 g_mutex_lock(packet_list_mutex); | |
621 packet_list = g_list_append(packet_list, pkt); | |
622 ctrl_write_packet(pkt->fd, NULL, 0); | |
623 close(pkt->fd); | |
624 g_mutex_unlock(packet_list_mutex); | |
625 break; | |
626 } | |
627 } | |
628 g_thread_exit(NULL); | |
629 | |
630 /* Used to suppress GCC warnings. Sometimes you'd wish C has | |
631 native threading support :p */ | |
632 return NULL; | |
633 } | |
634 | |
635 void | |
636 ctrlsocket_check(void) | |
637 { | |
638 GList *pkt_list, *next; | |
639 PacketNode *pkt; | |
640 gpointer data; | |
641 guint32 v[2], i, num; | |
642 gboolean tbool; | |
643 gfloat *fval, f; | |
644 | |
645 g_mutex_lock(packet_list_mutex); | |
646 for (pkt_list = packet_list; pkt_list; pkt_list = next) { | |
647 pkt = pkt_list->data; | |
648 data = pkt->data; | |
649 | |
650 switch (pkt->hdr.command) { | |
651 case CMD_PLAY: | |
652 if (bmp_playback_get_paused()) | |
653 bmp_playback_pause(); | |
654 else if (playlist_get_length()) | |
655 bmp_playback_initiate(); | |
656 else | |
657 mainwin_eject_pushed(); | |
658 break; | |
659 case CMD_PAUSE: | |
660 bmp_playback_pause(); | |
661 break; | |
662 case CMD_STOP: | |
906 | 663 ip_data.stop = TRUE; |
0 | 664 bmp_playback_stop(); |
906 | 665 ip_data.stop = FALSE; |
0 | 666 mainwin_clear_song_info(); |
667 break; | |
668 case CMD_PLAY_PAUSE: | |
669 if (bmp_playback_get_playing()) | |
670 bmp_playback_pause(); | |
671 else | |
672 bmp_playback_initiate(); | |
673 break; | |
674 case CMD_PLAYQUEUE_ADD: | |
675 num = *((guint32 *) data); | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
676 if (num < (guint)playlist_get_length()) |
0 | 677 playlist_queue_position(num); |
678 break; | |
679 case CMD_PLAYQUEUE_REMOVE: | |
680 num = *((guint32 *) data); | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
681 if (num < (guint)playlist_get_length()) |
0 | 682 playlist_queue_remove(num); |
683 break; | |
984 | 684 case CMD_PLAYQUEUE_CLEAR: |
685 playlist_clear_queue(); | |
686 break; | |
0 | 687 case CMD_SET_PLAYLIST_POS: |
688 num = *((guint32 *) data); | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
689 if (num < (guint)playlist_get_length()) |
0 | 690 playlist_set_position(num); |
691 break; | |
692 case CMD_JUMP_TO_TIME: | |
693 num = *((guint32 *) data); | |
694 if (playlist_get_current_length() > 0 && | |
625
0a73d1faeb4e
[svn] GCC 4.1 warning fixes by Diego 'Flameeyes' Petteno from Gentoo.
chainsaw
parents:
538
diff
changeset
|
695 num < (guint)playlist_get_current_length()) |
0 | 696 bmp_playback_seek(num / 1000); |
697 break; | |
698 case CMD_SET_VOLUME: | |
699 v[0] = ((guint32 *) data)[0]; | |
700 v[1] = ((guint32 *) data)[1]; | |
701 for (i = 0; i < 2; i++) { | |
702 if (v[i] > 100) | |
703 v[i] = 100; | |
704 } | |
705 input_set_volume(v[0], v[1]); | |
706 break; | |
707 case CMD_SET_SKIN: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
708 if (has_x11_connection == TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
709 bmp_active_skin_load(data); |
0 | 710 break; |
711 case CMD_PL_WIN_TOGGLE: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
712 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
713 break; |
0 | 714 tbool = *((gboolean *) data); |
715 if (tbool) | |
716 playlistwin_show(); | |
717 else | |
718 playlistwin_hide(); | |
719 break; | |
720 case CMD_EQ_WIN_TOGGLE: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
721 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
722 break; |
0 | 723 tbool = *((gboolean *) data); |
724 equalizerwin_show(!!tbool); | |
725 break; | |
726 case CMD_SHOW_PREFS_BOX: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
727 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
728 break; |
0 | 729 show_prefs_window(); |
730 break; | |
984 | 731 case CMD_SHOW_JTF_BOX: |
732 if (has_x11_connection != TRUE) | |
733 break; | |
734 mainwin_jump_to_file(); | |
735 break; | |
0 | 736 case CMD_TOGGLE_AOT: |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
737 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
738 break; |
0 | 739 tbool = *((gboolean *) data); |
740 mainwin_set_always_on_top(tbool); | |
741 break; | |
742 case CMD_SHOW_ABOUT_BOX: | |
743 break; | |
744 case CMD_EJECT: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
745 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
746 break; |
0 | 747 mainwin_eject_pushed(); |
748 break; | |
749 case CMD_PLAYLIST_PREV: | |
750 playlist_prev(); | |
751 break; | |
752 case CMD_PLAYLIST_NEXT: | |
753 playlist_next(); | |
754 break; | |
755 case CMD_TOGGLE_REPEAT: | |
756 mainwin_repeat_pushed(!cfg.repeat); | |
757 break; | |
758 case CMD_TOGGLE_SHUFFLE: | |
759 mainwin_shuffle_pushed(!cfg.shuffle); | |
760 break; | |
761 case CMD_TOGGLE_ADVANCE: | |
762 /* FIXME: to be implemented */ | |
763 break; | |
764 case CMD_MAIN_WIN_TOGGLE: | |
680
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
765 if (has_x11_connection != TRUE) |
8282b365f6cb
[svn] - Add some sanity checking to make sure we can't do X11 stuff when running headless.
nenolod
parents:
625
diff
changeset
|
766 break; |
0 | 767 tbool = *((gboolean *) data); |
768 mainwin_show(!!tbool); | |
769 break; | |
770 case CMD_SET_EQ: | |
771 if (pkt->hdr.data_length >= 11 * sizeof(gfloat)) { | |
772 fval = (gfloat *) data; | |
773 equalizerwin_set_preamp(fval[0]); | |
774 for (i = 0; i < 10; i++) | |
775 equalizerwin_set_band(i, fval[i + 1]); | |
776 } | |
777 break; | |
778 case CMD_SET_EQ_PREAMP: | |
779 f = *((gfloat *) data); | |
780 equalizerwin_set_preamp(f); | |
781 break; | |
782 case CMD_SET_EQ_BAND: | |
783 if (pkt->hdr.data_length >= sizeof(gint) + sizeof(gfloat)) { | |
784 i = *((gint *) data); | |
785 f = *((gfloat *) ((gchar *) data + sizeof(gint))); | |
786 equalizerwin_set_band(i, f); | |
787 } | |
788 break; | |
789 case CMD_QUIT: | |
790 /* | |
791 * We unlock the packet_list_mutex to | |
792 * avoid that cleanup_ctrlsocket() can | |
793 * deadlock, mainwin_quit_cb() will | |
794 * never return anyway, so this will | |
795 * work ok. | |
796 */ | |
797 g_mutex_unlock(packet_list_mutex); | |
798 mainwin_quit_cb(); | |
799 break; | |
800 case CMD_ACTIVATE: | |
801 gtk_window_present(GTK_WINDOW(mainwin)); | |
802 break; | |
803 default: | |
804 g_message("Unknown socket command received"); | |
805 break; | |
806 } | |
807 next = g_list_next(pkt_list); | |
808 packet_list = g_list_remove_link(packet_list, pkt_list); | |
809 g_list_free_1(pkt_list); | |
810 if (pkt->data) | |
811 g_free(pkt->data); | |
812 g_free(pkt); | |
813 } | |
814 g_mutex_unlock(packet_list_mutex); | |
815 } |