comparison src/sun/configure.c @ 12:3da1b8942b8b trunk

[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author nenolod
date Mon, 18 Sep 2006 03:14:20 -0700
parents src/Output/sun/configure.c@088092a52fea
children d124034ebea3
comparison
equal deleted inserted replaced
11:cff1d04026ae 12:3da1b8942b8b
1 /*
2 * Copyright (C) 2001 CubeSoft Communications, Inc.
3 * <http://www.csoft.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 #include <errno.h>
21 #include "sun.h"
22 #include "audacious/util.h"
23 #include "audacious/configdb.h"
24
25 #include <glib.h>
26 #include <glib/gi18n.h>
27
28 #include "mixer.h"
29
30 struct sun_statsframe stats_frame;
31
32 static GtkWidget *configure_win;
33 static GtkWidget *buffer_size_spin, *buffer_pre_spin;
34 static GtkWidget *adevice_entry, *actldevice_entry, *mdevice_entry;
35 static GtkWidget *keepopen_cbutton;
36 static char devaudio[64], devaudioctl[64], devmixer[64], mixer_toggle[64];
37
38 static void configure_win_destroy();
39
40 static void configure_win_ok_cb(GtkWidget *w, gpointer data)
41 {
42 ConfigDb *cfgfile;
43
44 strcpy(audio.devaudio, gtk_entry_get_text(GTK_ENTRY(adevice_entry)));
45 strcpy(audio.devmixer, gtk_entry_get_text(GTK_ENTRY(mdevice_entry)));
46
47 audio.req_buffer_size = gtk_spin_button_get_value_as_int(
48 GTK_SPIN_BUTTON(buffer_size_spin));
49 audio.req_prebuffer_size = gtk_spin_button_get_value_as_int(
50 GTK_SPIN_BUTTON(buffer_pre_spin));
51
52 if (sun_mixer_open() == 0)
53 {
54 audio.mixer_keepopen = gtk_toggle_button_get_active(
55 GTK_TOGGLE_BUTTON(keepopen_cbutton));
56 sun_mixer_close();
57 }
58
59 cfgfile = bmp_cfg_db_open();
60
61 bmp_cfg_db_set_string(cfgfile, "sun",
62 "audio_devaudio", audio.devaudio);
63 bmp_cfg_db_set_string(cfgfile, "sun",
64 "audio_devaudioctl", audio.devaudioctl);
65 bmp_cfg_db_set_string(cfgfile, "sun",
66 "audio_devmixer", audio.devmixer);
67
68 bmp_cfg_db_set_string(cfgfile, "sun",
69 "mixer_voldev", audio.mixer_voldev);
70 bmp_cfg_db_set_bool(cfgfile, "sun",
71 "mixer_keepopen", audio.mixer_keepopen);
72
73 bmp_cfg_db_set_int(cfgfile, "sun",
74 "buffer_size", audio.req_buffer_size);
75 bmp_cfg_db_set_int(cfgfile, "sun",
76 "prebuffer_size", audio.req_prebuffer_size);
77
78 bmp_cfg_db_close(cfgfile);
79
80 configure_win_destroy();
81 }
82
83 static void configure_win_cancel_cb(GtkWidget *w, gpointer data)
84 {
85 configure_win_destroy();
86 }
87
88 static void mixer_cbutton_toggled_cb(GtkWidget *w, int id)
89 {
90 mixer_ctrl_t mixer;
91
92 if (sun_mixer_open() == 0)
93 {
94 mixer.type = AUDIO_MIXER_ENUM;
95 mixer.dev = id;
96 mixer_toggle[id] = !mixer_toggle[id];
97 mixer.un.ord = mixer_toggle[id];
98
99 if (ioctl(audio.mixerfd, AUDIO_MIXER_WRITE, &mixer) != 0)
100 g_warning("Could not toggle mixer setting %i", id);
101 sun_mixer_close();
102 }
103 }
104
105 static void configure_win_mixer_volume_dev_cb(GtkWidget *w, gint voldev_index)
106 {
107 mixer_devinfo_t info;
108
109 if (sun_mixer_open() == 0)
110 {
111 info.index = voldev_index;
112 if (!ioctl(audio.mixerfd, AUDIO_MIXER_DEVINFO, &info))
113 strcpy(audio.mixer_voldev, info.label.name);
114 sun_mixer_close();
115 }
116 }
117
118 static void configure_win_destroy(void)
119 {
120 stats_frame.active = 0;
121
122 if (!pthread_mutex_lock(&stats_frame.active_mutex))
123 {
124 if (!pthread_mutex_lock(&stats_frame.audioctl_mutex))
125 {
126 if (stats_frame.fd)
127 {
128 close(stats_frame.fd);
129 stats_frame.fd = 0;
130 }
131 pthread_mutex_unlock(&stats_frame.audioctl_mutex);
132 pthread_mutex_destroy(&stats_frame.audioctl_mutex);
133 }
134 pthread_mutex_unlock(&stats_frame.active_mutex);
135 pthread_mutex_destroy(&stats_frame.active_mutex);
136 }
137 gtk_widget_destroy(configure_win);
138 configure_win = NULL;
139 }
140
141 static void configure_mixer_volumedev_scan(gchar *type, GtkWidget *option_menu)
142 {
143 mixer_devinfo_t info;
144 GtkWidget *menu;
145
146 if (sun_mixer_open() < 0)
147 return;
148
149 menu = gtk_menu_new();
150
151 /* FIXME: info is used while undefined here */
152 for (info.index = 0;
153 ioctl(audio.mixerfd, AUDIO_MIXER_DEVINFO, &info) == 0;
154 info.index++)
155 {
156 GtkWidget *item;
157
158 if (info.type == AUDIO_MIXER_VALUE)
159 {
160 item = gtk_menu_item_new_with_label(info.label.name);
161 g_signal_connect(G_OBJECT(item), "activate",
162 (GCallback) configure_win_mixer_volume_dev_cb,
163 (gpointer) info.index);
164
165 gtk_widget_show(item);
166 gtk_menu_append(GTK_MENU(menu), item);
167
168 if (!strcmp(info.label.name, audio.mixer_voldev))
169 gtk_menu_reorder_child(GTK_MENU(menu), item, 0);
170 }
171 }
172
173 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
174
175 sun_mixer_close();
176 }
177
178 static void configure_adevice_box(GtkWidget *dev_vbox)
179 {
180 GtkWidget *adevice_frame, *adevice_vbox;
181
182 adevice_frame = gtk_frame_new(_("Audio device:"));
183 gtk_box_pack_start(GTK_BOX(dev_vbox), adevice_frame, FALSE, FALSE, 0);
184
185 adevice_vbox = gtk_vbox_new(FALSE, 5);
186 gtk_container_set_border_width(GTK_CONTAINER(adevice_vbox), 5);
187 gtk_container_add(GTK_CONTAINER(adevice_frame), adevice_vbox);
188
189 strcpy(devaudio, audio.devaudio);
190
191 adevice_entry = gtk_entry_new();
192 gtk_entry_set_text(GTK_ENTRY(adevice_entry), devaudio);
193 gtk_box_pack_start_defaults(GTK_BOX(adevice_vbox), adevice_entry);
194 }
195
196 static void configure_actldevice_box(GtkWidget *dev_vbox)
197 {
198 GtkWidget *actldevice_frame, *actldevice_vbox;
199
200 actldevice_frame = gtk_frame_new(_("Audio control device:"));
201 gtk_box_pack_start(GTK_BOX(dev_vbox), actldevice_frame,
202 FALSE, FALSE, 0);
203
204 actldevice_vbox = gtk_vbox_new(FALSE, 5);
205 gtk_container_set_border_width(GTK_CONTAINER(actldevice_vbox), 5);
206 gtk_container_add(GTK_CONTAINER(actldevice_frame), actldevice_vbox);
207
208 strcpy(devaudioctl, audio.devaudioctl);
209
210 actldevice_entry = gtk_entry_new();
211 gtk_entry_set_text(GTK_ENTRY(actldevice_entry), devaudioctl);
212 gtk_box_pack_start_defaults(GTK_BOX(actldevice_vbox), actldevice_entry);
213 }
214
215 static void configure_mdevice_box(GtkWidget *dev_vbox)
216 {
217 GtkWidget *mdevice_frame, *mdevice_vbox;
218
219 mdevice_frame = gtk_frame_new(_("Mixer device:"));
220 gtk_box_pack_start(GTK_BOX(dev_vbox), mdevice_frame, FALSE, FALSE, 0);
221
222 mdevice_vbox = gtk_vbox_new(FALSE, 0);
223 gtk_container_set_border_width(GTK_CONTAINER(mdevice_vbox), 5);
224 gtk_container_add(GTK_CONTAINER(mdevice_frame), mdevice_vbox);
225
226 strcpy(devmixer, audio.devmixer);
227
228 mdevice_entry = gtk_entry_new();
229 gtk_entry_set_text(GTK_ENTRY(mdevice_entry), devmixer);
230 gtk_box_pack_start_defaults(GTK_BOX(mdevice_vbox), mdevice_entry);
231
232 }
233
234
235 static void configure_devices_frame(GtkWidget *vbox, GtkWidget * notebook)
236 {
237 GtkWidget *dev_vbox;
238
239 dev_vbox = gtk_vbox_new(FALSE, 5);
240 gtk_container_set_border_width(GTK_CONTAINER(dev_vbox), 5);
241
242 configure_adevice_box(dev_vbox);
243 configure_actldevice_box(dev_vbox);
244 configure_mdevice_box(dev_vbox);
245
246 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dev_vbox,
247 gtk_label_new(_("Devices")));
248 }
249
250
251 static void configure_buffering_frame(GtkWidget *vbox, GtkWidget * notebook)
252 {
253 GtkWidget *buffer_frame, *buffer_vbox, *buffer_table;
254 GtkWidget *buffer_size_box, *buffer_size_label;
255 GtkObject *buffer_size_adj, *buffer_pre_adj;
256 GtkWidget *buffer_pre_box, *buffer_pre_label;
257
258 buffer_frame = gtk_frame_new(_("Buffering:"));
259 gtk_container_set_border_width(GTK_CONTAINER(buffer_frame), 5);
260
261 buffer_vbox = gtk_vbox_new(FALSE, 0);
262 gtk_container_add(GTK_CONTAINER(buffer_frame), buffer_vbox);
263
264 buffer_table = gtk_table_new(2, 1, TRUE);
265 gtk_container_set_border_width(GTK_CONTAINER(buffer_table), 5);
266 gtk_box_pack_start(GTK_BOX(buffer_vbox), buffer_table, FALSE, FALSE, 0);
267
268 buffer_size_box = gtk_hbox_new(FALSE, 5);
269 gtk_table_attach_defaults( GTK_TABLE(buffer_table),
270 buffer_size_box, 0, 1, 0, 1);
271 buffer_size_label = gtk_label_new(_("Buffer size (ms):"));
272
273 gtk_box_pack_start(GTK_BOX(buffer_size_box), buffer_size_label,
274 FALSE, FALSE, 0);
275
276 buffer_size_adj = gtk_adjustment_new(audio.req_buffer_size,
277 200, 131072, 100, 100, 100);
278
279 buffer_size_spin = gtk_spin_button_new(GTK_ADJUSTMENT(buffer_size_adj),
280 8, 0);
281
282 gtk_widget_set_usize(buffer_size_spin, 60, -1);
283 gtk_box_pack_start(GTK_BOX(buffer_size_box),
284 buffer_size_spin, FALSE, FALSE, 0);
285
286 buffer_pre_box = gtk_hbox_new(FALSE, 5);
287 gtk_table_attach_defaults(GTK_TABLE(buffer_table),
288 buffer_pre_box, 1, 2, 0, 1);
289 buffer_pre_label = gtk_label_new(_("Pre-buffer (percent):"));
290 gtk_box_pack_start(GTK_BOX(buffer_pre_box), buffer_pre_label,
291 FALSE, FALSE, 0);
292
293 buffer_pre_adj = gtk_adjustment_new(audio.req_prebuffer_size,
294 0, 90, 1, 1, 1);
295 buffer_pre_spin = gtk_spin_button_new(GTK_ADJUSTMENT(buffer_pre_adj),
296 1, 0);
297
298 gtk_widget_set_usize(buffer_pre_spin, 60, -1);
299 gtk_box_pack_start(GTK_BOX(buffer_pre_box), buffer_pre_spin,
300 FALSE, FALSE, 0);
301
302 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), buffer_frame,
303 gtk_label_new(_("Buffering")));
304 }
305
306 static void configure_mixer_toggle_button(GtkWidget *vbox, gchar *devname, gchar *label)
307 {
308 GtkWidget *toggle_cbutton;
309 gint devid;
310 mixer_ctrl_t mixer;
311
312 if (!sun_mixer_get_dev(audio.mixerfd, &devid, devname))
313 {
314 mixer.type = AUDIO_MIXER_ENUM;
315 mixer.dev = devid;
316
317 if (!ioctl(audio.mixerfd, AUDIO_MIXER_READ, &mixer))
318 {
319 toggle_cbutton =
320 gtk_check_button_new_with_label(_(label));
321 gtk_box_pack_start_defaults(GTK_BOX(vbox),
322 toggle_cbutton);
323
324 if (mixer.un.ord)
325 {
326 gtk_toggle_button_set_active(
327 GTK_TOGGLE_BUTTON(toggle_cbutton), TRUE);
328 mixer_toggle[mixer.dev]++;
329 }
330 else
331 {
332 mixer_toggle[mixer.dev] = 0;
333 }
334
335 gtk_signal_connect(GTK_OBJECT(toggle_cbutton),
336 "toggled",
337 GTK_SIGNAL_FUNC(mixer_cbutton_toggled_cb),
338 (gpointer) mixer.dev);
339 }
340 }
341 }
342
343
344 static void configure_mixer_box(GtkWidget *vbox, GtkWidget *notebook)
345 {
346 GtkWidget *mixervol_frame, *mixervol_box;
347 GtkWidget *mixervol_menu;
348
349 mixervol_frame = gtk_frame_new(_("Volume controls device:"));
350 gtk_box_pack_start(GTK_BOX(vbox), mixervol_frame, FALSE, FALSE, 0);
351
352 mixervol_box = gtk_vbox_new(FALSE, 0);
353 gtk_container_set_border_width(GTK_CONTAINER(mixervol_box), 5);
354 gtk_container_add(GTK_CONTAINER(mixervol_frame), mixervol_box);
355
356 mixervol_menu = gtk_option_menu_new();
357 gtk_box_pack_start(GTK_BOX(mixervol_box), mixervol_menu, TRUE, TRUE, 0);
358
359 configure_mixer_volumedev_scan("Volume devices:", mixervol_menu);
360
361 keepopen_cbutton = gtk_check_button_new_with_label(
362 _("XMMS uses mixer exclusively."));
363 if (audio.mixer_keepopen)
364 gtk_toggle_button_set_active(
365 GTK_TOGGLE_BUTTON(keepopen_cbutton), TRUE);
366
367 gtk_box_pack_start_defaults(GTK_BOX(vbox), keepopen_cbutton);
368
369 if (sun_mixer_open() == 0)
370 {
371 configure_mixer_toggle_button(vbox, "bassboost", "Bass boost");
372 configure_mixer_toggle_button(vbox, "loudness", "Loudness");
373 configure_mixer_toggle_button(vbox, "spatial", "Spatial");
374 configure_mixer_toggle_button(vbox, "surround", "Surround");
375 configure_mixer_toggle_button(vbox, "enhanced", "Enhanced");
376 configure_mixer_toggle_button(vbox, "preamp", "Preamp");
377 configure_mixer_toggle_button(vbox, "swap", "Swap channels");
378 sun_mixer_close();
379 }
380 }
381
382
383 static void configure_mixer_frame(GtkWidget *vbox, GtkWidget *notebook)
384 {
385 GtkWidget *mixervol_vbox;
386
387 mixervol_vbox = gtk_vbox_new(FALSE, 5);
388 gtk_container_set_border_width(GTK_CONTAINER(mixervol_vbox), 5);
389
390 configure_mixer_box(mixervol_vbox, notebook);
391
392 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
393 mixervol_vbox, gtk_label_new(_("Mixer")));
394 }
395
396
397 static void configure_stats_loop(void)
398 {
399 if (pthread_mutex_lock(&stats_frame.active_mutex) != 0)
400 {
401 perror("active_mutex");
402 return;
403 }
404
405 while (stats_frame.active && stats_frame.fd)
406 {
407 audio_info_t info;
408 char sl[32];
409
410 pthread_mutex_lock(&stats_frame.audioctl_mutex);
411
412 sl[0] = '\0';
413
414 if (!ioctl(stats_frame.fd, AUDIO_GETINFO, &info))
415 {
416 char s[128];
417
418 sprintf(s, "Currently %s",
419 (info.mode == AUMODE_PLAY) ? "playing" :
420 (info.mode == AUMODE_RECORD) ? "recording" :
421 (info.mode == AUMODE_PLAY_ALL) ? "playing" :
422 "not playing");
423
424 if (info.mode == AUMODE_PLAY)
425 {
426 sprintf(s, "%s at %i Hz (%i-bit %s)", s,
427 info.play.sample_rate, info.play.precision,
428 audio.output->name);
429 sprintf(sl,"%i samples, %i error(s). %s",
430 info.play.samples, info.play.error,
431 info.play.active ?
432 "I/O in progress." : "");
433 }
434 gtk_label_set_text(GTK_LABEL(stats_frame.mode_label),
435 s);
436
437 sprintf(s, "H/W block: %i bytes. Buffer: %i bytes",
438 info.blocksize, info.play.buffer_size);
439 gtk_label_set_text(
440 GTK_LABEL(stats_frame.blocksize_label), s);
441 }
442 gtk_label_set_text(GTK_LABEL(stats_frame.ooffs_label), sl);
443
444 pthread_mutex_unlock(&stats_frame.audioctl_mutex);
445 xmms_usleep(400000);
446 }
447 pthread_mutex_unlock(&stats_frame.active_mutex);
448
449 pthread_exit(NULL);
450 }
451
452 static void configure_status_frame(GtkWidget *vbox, GtkWidget *notebook)
453 {
454 GtkWidget *status_vbox;
455 GtkWidget *name_label, *props_label;
456 pthread_t loop_thread;
457
458 memset(&stats_frame, 0, sizeof(struct sun_statsframe));
459
460 if (pthread_mutex_init(&stats_frame.audioctl_mutex, NULL) != 0)
461 {
462 perror("audioctl_mutex");
463 return;
464 }
465 if (pthread_mutex_init(&stats_frame.active_mutex, NULL) != 0)
466 {
467 perror("active_mutex");
468 return;
469 }
470 status_vbox = gtk_vbox_new(FALSE, 5);
471 gtk_container_set_border_width(GTK_CONTAINER(status_vbox), 5);
472
473 name_label = gtk_label_new(NULL);
474 gtk_container_add(GTK_CONTAINER(status_vbox), name_label);
475 props_label = gtk_label_new(NULL);
476 gtk_container_add(GTK_CONTAINER(status_vbox), props_label);
477
478 stats_frame.mode_label = gtk_label_new(NULL);
479 gtk_container_add(GTK_CONTAINER(status_vbox), stats_frame.mode_label);
480 stats_frame.blocksize_label = gtk_label_new(NULL);
481 gtk_container_add(GTK_CONTAINER(status_vbox),
482 stats_frame.blocksize_label);
483 stats_frame.ooffs_label = gtk_label_new(NULL);
484 gtk_container_add(GTK_CONTAINER(status_vbox), stats_frame.ooffs_label);
485
486 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), status_vbox,
487 gtk_label_new(_("Status")));
488
489 if ((stats_frame.fd = open(audio.devaudioctl, O_RDWR)) >= 0)
490 {
491 audio_device_t device;
492 int props;
493
494 if (ioctl(stats_frame.fd, AUDIO_GETDEV, &device) >= 0)
495 {
496 char *s = g_strdup_printf("%s - %s(4) %s",
497 device.name, device.config, device.version);
498 gtk_label_set_text(GTK_LABEL(name_label), s);
499 g_free(s);
500 }
501 if (ioctl(stats_frame.fd, AUDIO_GETPROPS, &props) >= 0)
502 {
503 char s[32];
504 s[0] = '\0';
505
506 if ((props & AUDIO_PROP_FULLDUPLEX) ==
507 AUDIO_PROP_FULLDUPLEX)
508 sprintf(s, "FULLDUPLEX ");
509 if ((props & AUDIO_PROP_MMAP) == AUDIO_PROP_MMAP)
510 sprintf(s, "%s MMAP ", s);
511 if ((props & AUDIO_PROP_INDEPENDENT) ==
512 AUDIO_PROP_INDEPENDENT)
513 sprintf(s, "%s INDEPENDENT ", s);
514
515 gtk_label_set_text(GTK_LABEL(props_label), s);
516 }
517 }
518 stats_frame.active++;
519 pthread_create(&loop_thread, NULL, (void *) configure_stats_loop, NULL);
520 }
521
522 void sun_configure(void)
523 {
524 GtkWidget *vbox, *notebook;
525 GtkWidget *bbox, *ok, *cancel;
526
527 if (configure_win)
528 {
529 gdk_window_raise(configure_win->window);
530 return;
531 }
532 configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
533 gtk_signal_connect(GTK_OBJECT(configure_win), "destroy",
534 GTK_SIGNAL_FUNC(configure_win_destroy), NULL);
535
536 gtk_window_set_title(GTK_WINDOW(configure_win),
537 _("Sun driver configuration"));
538 gtk_window_set_policy(GTK_WINDOW(configure_win), FALSE, FALSE, FALSE);
539 gtk_window_set_position(GTK_WINDOW(configure_win), GTK_WIN_POS_MOUSE);
540 gtk_container_border_width(GTK_CONTAINER(configure_win), 10);
541
542 vbox = gtk_vbox_new(FALSE, 10);
543 gtk_container_add(GTK_CONTAINER(configure_win), vbox);
544
545 notebook = gtk_notebook_new();
546 gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
547
548 configure_devices_frame(vbox, notebook);
549 configure_buffering_frame(vbox, notebook);
550 configure_mixer_frame(vbox, notebook);
551 configure_status_frame(vbox, notebook);
552
553 bbox = gtk_hbutton_box_new();
554 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
555 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
556 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
557
558 ok = gtk_button_new_with_label(_("Ok"));
559 gtk_signal_connect(GTK_OBJECT(ok), "clicked",
560 GTK_SIGNAL_FUNC(configure_win_ok_cb), NULL);
561
562 GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT);
563 gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
564 gtk_widget_grab_default(ok);
565
566 cancel = gtk_button_new_with_label(_("Cancel"));
567 gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked",
568 GTK_SIGNAL_FUNC(configure_win_cancel_cb),
569 GTK_OBJECT(configure_win));
570
571 GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
572 gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
573
574 gtk_widget_show_all(configure_win);
575 }
576