Mercurial > audlegacy-plugins
comparison src/Visualization/paranormal/client.c @ 0:13389e613d67 trunk
[svn] - initial import of audacious-plugins tree (lots to do)
| author | nenolod |
|---|---|
| date | Mon, 18 Sep 2006 01:11:49 -0700 |
| parents | |
| children | 6303e3a8a6b8 |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:13389e613d67 |
|---|---|
| 1 /* pnxmms - An xmms visualization plugin using the Paranormal | |
| 2 * audio visualization library | |
| 3 * | |
| 4 * Copyright (C) 2001 Jamie Gennis <jgennis@mindspring.com> | |
| 5 * | |
| 6 * This library is free software; you can redistribute it and/or | |
| 7 * modify it under the terms of the GNU Library General Public | |
| 8 * License as published by the Free Software Foundation; either | |
| 9 * version 2 of the License, or (at your option) any later version. | |
| 10 * | |
| 11 * This library 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 GNU | |
| 14 * Library General Public License for more details. | |
| 15 * | |
| 16 * You should have received a copy of the GNU Library General Public | |
| 17 * License along with this library; if not, write to the Free | |
| 18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 19 */ | |
| 20 | |
| 21 #ifdef HAVE_CONFIG_H | |
| 22 #include <config.h> | |
| 23 #endif | |
| 24 | |
| 25 #include <sys/types.h> | |
| 26 #include <sys/stat.h> | |
| 27 #include <unistd.h> | |
| 28 #include <stdio.h> | |
| 29 #include <string.h> | |
| 30 #include <errno.h> | |
| 31 | |
| 32 #include <gtk/gtk.h> | |
| 33 #include <audacious/plugin.h> | |
| 34 #include <libaudacious/configdb.h> | |
| 35 #include <SDL/SDL.h> | |
| 36 #include <SDL/SDL_thread.h> | |
| 37 | |
| 38 #include "pn.h" | |
| 39 | |
| 40 /* Paranormal visualization object */ | |
| 41 static PnVis *vis; | |
| 42 | |
| 43 /* Paranormal audio data object */ | |
| 44 static PnAudioData *audio_data; | |
| 45 | |
| 46 /* SDL window's surface */ | |
| 47 static SDL_Surface *screen; | |
| 48 | |
| 49 /* Synchronization stuffs */ | |
| 50 static SDL_Thread *render_thread; | |
| 51 static int render_func (void *data); | |
| 52 static gboolean kill_render_thread; | |
| 53 static gboolean quit_timeout_func (gpointer data); | |
| 54 static guint quit_timeout; | |
| 55 static gboolean render_thread_finished; | |
| 56 | |
| 57 static SDL_mutex *vis_mutex; | |
| 58 static SDL_mutex *audio_data_mutex; | |
| 59 static gfloat intermediate_pcm_data[3][512]; | |
| 60 static gfloat intermediate_freq_data[3][256]; | |
| 61 | |
| 62 /* PNXMMS Options */ | |
| 63 static gboolean options_read = FALSE; | |
| 64 static gboolean preset_changed = FALSE; | |
| 65 static gchar *preset; | |
| 66 static guint image_width = 320; | |
| 67 static guint image_height = 240; | |
| 68 | |
| 69 /* Config dialog */ | |
| 70 GtkWidget *config_dialog; | |
| 71 GtkWidget *load_button; | |
| 72 | |
| 73 /* Config functions */ | |
| 74 static void read_options (void); | |
| 75 static void write_options (void); | |
| 76 static void load_default_vis (void); | |
| 77 static void create_config_dialog (void); | |
| 78 | |
| 79 /* Rendering functions */ | |
| 80 static void draw_image (PnImage *image); | |
| 81 | |
| 82 /* XMMS interface */ | |
| 83 static void pn_xmms_init (void); | |
| 84 static void pn_xmms_cleanup (void); | |
| 85 /* static void pn_xmms_about (void); */ | |
| 86 static void pn_xmms_configure (void); | |
| 87 static void pn_xmms_render_pcm (gint16 data[2][512]); | |
| 88 static void pn_xmms_render_freq (gint16 data[2][256]); | |
| 89 | |
| 90 static VisPlugin pn_xmms_vp = | |
| 91 { | |
| 92 NULL, /* handle */ | |
| 93 NULL, /* filename */ | |
| 94 0, /* xmms_session */ | |
| 95 "Paranormal Visualization Studio " VERSION, | |
| 96 2, | |
| 97 2, | |
| 98 pn_xmms_init, | |
| 99 pn_xmms_cleanup, | |
| 100 NULL, /* pn_xmms_about, */ | |
| 101 pn_xmms_configure, | |
| 102 NULL, /* disable_plugin */ | |
| 103 NULL, /* playback_start */ | |
| 104 NULL, /* pkayback_stop */ | |
| 105 pn_xmms_render_pcm, | |
| 106 pn_xmms_render_freq | |
| 107 }; | |
| 108 | |
| 109 VisPlugin* | |
| 110 get_vplugin_info (void) | |
| 111 { | |
| 112 return &pn_xmms_vp; | |
| 113 } | |
| 114 | |
| 115 static void | |
| 116 pn_xmms_init (void) | |
| 117 { | |
| 118 /* Load the saved options */ | |
| 119 read_options (); | |
| 120 | |
| 121 /* Initialize SDL */ | |
| 122 if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) | |
| 123 { | |
| 124 g_warning ("Unable to initialize SDL: %s\n", SDL_GetError ()); | |
| 125 pn_xmms_vp.disable_plugin (&pn_xmms_vp); | |
| 126 } | |
| 127 | |
| 128 screen = SDL_SetVideoMode (image_width, image_height, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE); | |
| 129 if (! screen) | |
| 130 { | |
| 131 g_warning ("Unable to create a new SDL window: %s\n", SDL_GetError ()); | |
| 132 pn_xmms_vp.disable_plugin (&pn_xmms_vp); | |
| 133 } | |
| 134 | |
| 135 SDL_WM_SetCaption ("Paranormal Visualization Studio " VERSION, PACKAGE); | |
| 136 | |
| 137 /* Initialize Paranormal */ | |
| 138 pn_init (); | |
| 139 | |
| 140 /* Set up the visualization objects */ | |
| 141 vis = pn_vis_new (image_width, image_height); | |
| 142 pn_object_ref (PN_OBJECT (vis)); | |
| 143 pn_object_sink (PN_OBJECT (vis)); | |
| 144 | |
| 145 if (! preset || ! pn_vis_load_from_file (vis, preset)) | |
| 146 load_default_vis (); | |
| 147 | |
| 148 audio_data = pn_audio_data_new (); | |
| 149 pn_object_ref (PN_OBJECT (audio_data)); | |
| 150 pn_object_sink (PN_OBJECT (audio_data)); | |
| 151 pn_audio_data_set_stereo (audio_data, FALSE); | |
| 152 pn_audio_data_set_pcm_samples (audio_data, 512); | |
| 153 pn_audio_data_set_freq_bands (audio_data, 256); | |
| 154 | |
| 155 /* Set up the render thread */ | |
| 156 audio_data_mutex = SDL_CreateMutex (); | |
| 157 vis_mutex = SDL_CreateMutex (); | |
| 158 if (! audio_data_mutex || ! vis_mutex) | |
| 159 { | |
| 160 g_warning ("Unable to create mutex: %s\n", SDL_GetError ()); | |
| 161 pn_xmms_vp.disable_plugin (&pn_xmms_vp); | |
| 162 } | |
| 163 | |
| 164 kill_render_thread = FALSE; | |
| 165 render_thread_finished = FALSE; | |
| 166 render_thread = SDL_CreateThread (render_func, NULL); | |
| 167 if (! render_thread) | |
| 168 { | |
| 169 g_warning ("Unable to create render thread: %s\n", SDL_GetError ()); | |
| 170 pn_xmms_vp.disable_plugin (&pn_xmms_vp); | |
| 171 } | |
| 172 | |
| 173 /* Create the quit-checker timeout */ | |
| 174 quit_timeout = gtk_timeout_add (500, quit_timeout_func, NULL); | |
| 175 } | |
| 176 | |
| 177 static void | |
| 178 pn_xmms_cleanup (void) | |
| 179 { | |
| 180 if (quit_timeout != 0) | |
| 181 { | |
| 182 gtk_timeout_remove (quit_timeout); | |
| 183 quit_timeout = 0; | |
| 184 } | |
| 185 | |
| 186 if (render_thread) | |
| 187 { | |
| 188 kill_render_thread = TRUE; | |
| 189 SDL_WaitThread (render_thread, NULL); | |
| 190 render_thread = NULL; | |
| 191 } | |
| 192 | |
| 193 if (audio_data_mutex) | |
| 194 { | |
| 195 SDL_DestroyMutex (audio_data_mutex); | |
| 196 audio_data_mutex = NULL; | |
| 197 } | |
| 198 | |
| 199 if (screen) | |
| 200 { | |
| 201 SDL_FreeSurface (screen); | |
| 202 screen = NULL; | |
| 203 } | |
| 204 SDL_Quit (); | |
| 205 | |
| 206 if (vis) | |
| 207 { | |
| 208 pn_object_unref (PN_OBJECT (vis)); | |
| 209 vis = NULL; | |
| 210 } | |
| 211 | |
| 212 write_options (); | |
| 213 } | |
| 214 | |
| 215 /* | |
| 216 static void | |
| 217 pn_xmms_about (void) | |
| 218 { | |
| 219 // FIXME: This needs to wait until XMMS supports GTK+ 2.0 | |
| 220 } | |
| 221 */ | |
| 222 | |
| 223 static void | |
| 224 pn_xmms_configure (void) | |
| 225 { | |
| 226 read_options (); | |
| 227 create_config_dialog (); | |
| 228 } | |
| 229 | |
| 230 static void | |
| 231 pn_xmms_render_pcm (gint16 data[2][512]) | |
| 232 { | |
| 233 guint i; | |
| 234 | |
| 235 /* Set up the audio data */ | |
| 236 for (i=0; i<512; i++) | |
| 237 { | |
| 238 intermediate_pcm_data[PN_CHANNEL_LEFT][i] = (gfloat)(data[0][i]) / 32768.0; | |
| 239 intermediate_pcm_data[PN_CHANNEL_RIGHT][i] = (gfloat)(data[0][i]) / 32768.0; | |
| 240 intermediate_pcm_data[PN_CHANNEL_CENTER][i] = .5 * (intermediate_pcm_data[PN_CHANNEL_LEFT][i] | |
| 241 + intermediate_pcm_data[PN_CHANNEL_RIGHT][i]); | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 static void | |
| 246 pn_xmms_render_freq (gint16 data[2][256]) | |
| 247 { | |
| 248 guint i; | |
| 249 | |
| 250 /* Set up the audio data */ | |
| 251 for (i=0; i<256; i++) | |
| 252 { | |
| 253 intermediate_freq_data[PN_CHANNEL_LEFT][i] = (gfloat)(data[0][i]) / 32768.0; | |
| 254 intermediate_freq_data[PN_CHANNEL_RIGHT][i] = (gfloat)(data[0][i]) / 32768.0; | |
| 255 intermediate_freq_data[PN_CHANNEL_CENTER][i] = .5 * (intermediate_freq_data[PN_CHANNEL_LEFT][i] | |
| 256 + intermediate_freq_data[PN_CHANNEL_RIGHT][i]); | |
| 257 } | |
| 258 } | |
| 259 | |
| 260 static gboolean | |
| 261 quit_timeout_func (gpointer data) | |
| 262 { | |
| 263 if (render_thread_finished) | |
| 264 { | |
| 265 pn_xmms_vp.disable_plugin (&pn_xmms_vp); | |
| 266 quit_timeout = 0; | |
| 267 return FALSE; | |
| 268 } | |
| 269 return TRUE; | |
| 270 } | |
| 271 | |
| 272 static int | |
| 273 render_func (void *data) | |
| 274 { | |
| 275 guint i; | |
| 276 PnImage *image; | |
| 277 guint last_time = 0, last_second = 0; | |
| 278 gfloat fps = 0.0; | |
| 279 guint this_time; | |
| 280 SDL_Event event; | |
| 281 | |
| 282 while (! kill_render_thread) | |
| 283 { | |
| 284 /* Lock & copy the audio data */ | |
| 285 SDL_mutexP (audio_data_mutex); | |
| 286 | |
| 287 for (i=0; i<3; i++) | |
| 288 { | |
| 289 memcpy (PN_AUDIO_DATA_PCM_DATA (audio_data, i), intermediate_pcm_data[i], 512 * sizeof (gfloat)); | |
| 290 memcpy (PN_AUDIO_DATA_FREQ_DATA (audio_data, i), intermediate_freq_data[i], 256 * sizeof (gfloat)); | |
| 291 } | |
| 292 | |
| 293 SDL_mutexV (audio_data_mutex); | |
| 294 | |
| 295 pn_audio_data_update (audio_data); | |
| 296 | |
| 297 /* Render the image */ | |
| 298 SDL_mutexP (vis_mutex); | |
| 299 image = pn_vis_render (vis, audio_data); | |
| 300 SDL_mutexV (vis_mutex); | |
| 301 | |
| 302 /* Draw the image */ | |
| 303 draw_image (image); | |
| 304 | |
| 305 /* Compute the FPS */ | |
| 306 this_time = SDL_GetTicks (); | |
| 307 | |
| 308 fps = fps * .95 + (1000.0 / (gfloat) (this_time - last_time)) * .05; | |
| 309 if (this_time > 2000 + last_second) | |
| 310 { | |
| 311 last_second = this_time; | |
| 312 printf ("paranormal fps: %f\n", fps); | |
| 313 } | |
| 314 last_time = this_time; | |
| 315 | |
| 316 /* Handle window events */ | |
| 317 while (SDL_PollEvent (&event)) | |
| 318 { | |
| 319 switch (event.type) | |
| 320 { | |
| 321 case SDL_QUIT: | |
| 322 render_thread_finished = TRUE; | |
| 323 return 0; | |
| 324 | |
| 325 case SDL_VIDEORESIZE: | |
| 326 image_width = event.resize.w; | |
| 327 image_height = event.resize.h; | |
| 328 screen = SDL_SetVideoMode (image_width, image_height, 32, | |
| 329 SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE); | |
| 330 printf ("changed to: w: %u, h: %u\n", image_width, image_height); | |
| 331 pn_vis_set_image_size (vis, image_width, image_height); | |
| 332 break; | |
| 333 | |
| 334 case SDL_KEYDOWN: | |
| 335 switch (event.key.keysym.sym) | |
| 336 { | |
| 337 case SDLK_ESCAPE: | |
| 338 render_thread_finished = TRUE; | |
| 339 return 0; | |
| 340 | |
| 341 case SDLK_RETURN: | |
| 342 if (event.key.keysym.mod & (KMOD_ALT | KMOD_META)) | |
| 343 { | |
| 344 /* Toggle fullscreen */ | |
| 345 SDL_WM_ToggleFullScreen (screen); | |
| 346 if (SDL_ShowCursor (SDL_QUERY) == SDL_ENABLE) | |
| 347 SDL_ShowCursor (SDL_DISABLE); | |
| 348 else | |
| 349 SDL_ShowCursor (SDL_ENABLE); | |
| 350 } | |
| 351 break; | |
| 352 case SDLK_BACKQUOTE: | |
| 353 { | |
| 354 char fname[20]; | |
| 355 int i = 0; | |
| 356 struct stat buf; | |
| 357 | |
| 358 do | |
| 359 { | |
| 360 sprintf (fname, "pnxmms_ss_%05u.bmp", i++); | |
| 361 } while(!(stat(fname, &buf) != 0 && errno == ENOENT )); | |
| 362 SDL_SaveBMP(screen, fname); | |
| 363 } | |
| 364 break; | |
| 365 | |
| 366 default: | |
| 367 break; | |
| 368 } | |
| 369 break; | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 /* don't lock the CPU :P */ | |
| 374 g_usleep(10000); | |
| 375 } | |
| 376 | |
| 377 return 0; | |
| 378 } | |
| 379 | |
| 380 static void | |
| 381 draw_image (PnImage *image) | |
| 382 { | |
| 383 guint width, height, src_stride, dest_stride; | |
| 384 guint i; | |
| 385 register PnColor *src; | |
| 386 register Uint32 *dest; | |
| 387 | |
| 388 /* Lock the SDL surface */ | |
| 389 SDL_LockSurface (screen); | |
| 390 | |
| 391 /* Get the dimentions */ | |
| 392 width = pn_image_get_width (image); | |
| 393 height = pn_image_get_height (image); | |
| 394 | |
| 395 src_stride = pn_image_get_pitch (image) >> 2; | |
| 396 dest_stride = screen->pitch >> 2; | |
| 397 | |
| 398 src = pn_image_get_image_buffer (image); | |
| 399 dest = (Uint32 *) screen->pixels; | |
| 400 | |
| 401 /* Copy the pixel data */ | |
| 402 while (--height > 0) | |
| 403 { | |
| 404 for (i=0; i<width; i++) | |
| 405 dest[i] = SDL_MapRGB (screen->format, src[i].red, src[i].green, src[i].blue); | |
| 406 dest += dest_stride; | |
| 407 src += src_stride; | |
| 408 } | |
| 409 | |
| 410 /* Unlock the SDL surface */ | |
| 411 SDL_UnlockSurface (screen); | |
| 412 | |
| 413 /* Draw it to the screen */ | |
| 414 SDL_Flip (screen); | |
| 415 } | |
| 416 | |
| 417 static void | |
| 418 read_options (void) | |
| 419 { | |
| 420 ConfigDb *cfg; | |
| 421 gint i; | |
| 422 | |
| 423 if (options_read == TRUE) | |
| 424 return; | |
| 425 | |
| 426 cfg = bmp_cfg_db_open (); | |
| 427 if (!cfg) | |
| 428 return; | |
| 429 | |
| 430 if (bmp_cfg_db_get_int (cfg, "pnxmms", "image_width", &i)) | |
| 431 image_width = i; | |
| 432 | |
| 433 if (bmp_cfg_db_get_int (cfg, "pnxmms", "image_height", &i)) | |
| 434 image_height = i; | |
| 435 | |
| 436 bmp_cfg_db_get_string (cfg, "pnxmms", "preset", &preset); | |
| 437 | |
| 438 bmp_cfg_db_close (cfg); | |
| 439 | |
| 440 return; | |
| 441 } | |
| 442 | |
| 443 static void | |
| 444 write_options (void) | |
| 445 { | |
| 446 ConfigDb *cfg; | |
| 447 | |
| 448 cfg = bmp_cfg_db_open (); | |
| 449 if (!cfg) | |
| 450 fprintf (stderr, "PNXMMS: Unable to open XMMS config file!\n"); | |
| 451 | |
| 452 bmp_cfg_db_set_int (cfg, "pnxmms", "image_width", image_width); | |
| 453 bmp_cfg_db_set_int (cfg, "pnxmms", "image_height", image_height); | |
| 454 | |
| 455 if (preset) | |
| 456 bmp_cfg_db_set_string (cfg, "pnxmms", "preset", preset); | |
| 457 | |
| 458 bmp_cfg_db_close (cfg); | |
| 459 } | |
| 460 | |
| 461 static void | |
| 462 load_default_vis (void) | |
| 463 { | |
| 464 PnContainer *container; | |
| 465 PnActuator *actuator; | |
| 466 PnOption *option; | |
| 467 | |
| 468 /* Actuator List */ | |
| 469 container = (PnContainer *) pn_actuator_list_new (); | |
| 470 | |
| 471 /* Scope */ | |
| 472 actuator = (PnActuator *) pn_scope_new (); | |
| 473 option = pn_actuator_get_option_by_name (actuator, "init_script"); | |
| 474 pn_string_option_set_value (PN_STRING_OPTION (option), "samples = width/2;"); | |
| 475 option = pn_actuator_get_option_by_name (actuator, "frame_script"); | |
| 476 pn_string_option_set_value (PN_STRING_OPTION (option), | |
| 477 "base = base + .04;\n" | |
| 478 "red = abs (sin (.5 * pi + .1 * base));\n" | |
| 479 "green = .5 * abs (sin (.5 * pi - .2 * base));\n" | |
| 480 "blue = abs (sin (.5 * pi + .3 * base));"); | |
| 481 option = pn_actuator_get_option_by_name (actuator, "sample_script"); | |
| 482 pn_string_option_set_value (PN_STRING_OPTION (option), | |
| 483 "x = 2 * iteration - 1;\n" | |
| 484 "y = value;"); | |
| 485 option = pn_actuator_get_option_by_name (actuator, "draw_method"); | |
| 486 pn_list_option_set_index (PN_LIST_OPTION (option), 1); | |
| 487 pn_container_add_actuator (container, actuator, PN_POSITION_TAIL); | |
| 488 | |
| 489 /* Distortion */ | |
| 490 actuator = (PnActuator *) pn_distortion_new (); | |
| 491 option = pn_actuator_get_option_by_name (actuator, "distortion_script"); | |
| 492 pn_string_option_set_value (PN_STRING_OPTION (option), | |
| 493 "intensity = .99 + .08 * r;\n" | |
| 494 "r = .98 * atan (r);\n" | |
| 495 "theta = theta + .01;"); | |
| 496 option = pn_actuator_get_option_by_name (actuator, "polar_coords"); | |
| 497 pn_boolean_option_set_value (PN_BOOLEAN_OPTION (option), TRUE); | |
| 498 pn_container_add_actuator (container, actuator, PN_POSITION_TAIL); | |
| 499 | |
| 500 /* Add the actuator list to the vis */ | |
| 501 pn_vis_set_root_actuator (vis, PN_ACTUATOR (container)); | |
| 502 } | |
| 503 | |
| 504 static void | |
| 505 apply_settings (void) | |
| 506 { | |
| 507 if (preset_changed) | |
| 508 { | |
| 509 preset_changed = FALSE; | |
| 510 SDL_mutexP (vis_mutex); | |
| 511 pn_vis_load_from_file (vis, preset); | |
| 512 SDL_mutexV (vis_mutex); | |
| 513 } | |
| 514 | |
| 515 write_options (); | |
| 516 } | |
| 517 | |
| 518 static void | |
| 519 destroy_config_dialog (GtkObject *user_data, gpointer data) | |
| 520 { | |
| 521 gtk_widget_destroy (GTK_WIDGET(config_dialog)); | |
| 522 config_dialog = NULL; | |
| 523 } | |
| 524 | |
| 525 static void | |
| 526 apply_button_cb (GtkButton *button, gpointer data) | |
| 527 { | |
| 528 apply_settings (); | |
| 529 } | |
| 530 | |
| 531 static void | |
| 532 ok_button_cb (GtkButton *button, gpointer data) | |
| 533 { | |
| 534 apply_settings (); | |
| 535 destroy_config_dialog (NULL, NULL); | |
| 536 } | |
| 537 | |
| 538 static void | |
| 539 cancel_button_cb (GtkButton *button, gpointer data) | |
| 540 { | |
| 541 destroy_config_dialog (NULL, NULL); | |
| 542 } | |
| 543 | |
| 544 /* If selector != NULL, then it's 'OK', otherwise it's 'Cancel' */ | |
| 545 static void | |
| 546 load_preset_cb (GtkButton *button, GtkFileSelection *selector) | |
| 547 { | |
| 548 if (selector) | |
| 549 { | |
| 550 if (preset) | |
| 551 g_free (preset); | |
| 552 preset = g_strdup (gtk_file_selection_get_filename (selector)); | |
| 553 gtk_label_set_text (GTK_LABEL (GTK_BIN (load_button)->child), preset); | |
| 554 preset_changed = TRUE; | |
| 555 } | |
| 556 | |
| 557 gtk_widget_set_sensitive (config_dialog, TRUE); | |
| 558 } | |
| 559 | |
| 560 static void | |
| 561 load_preset_button_cb (GtkButton *button, gpointer data) | |
| 562 { | |
| 563 GtkWidget *selector; | |
| 564 | |
| 565 selector = gtk_file_selection_new ("Load Preset"); | |
| 566 | |
| 567 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (selector)->ok_button), | |
| 568 "clicked", GTK_SIGNAL_FUNC (load_preset_cb), selector); | |
| 569 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (selector)->cancel_button), | |
| 570 "clicked", GTK_SIGNAL_FUNC (load_preset_cb), NULL); | |
| 571 | |
| 572 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->ok_button), | |
| 573 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), | |
| 574 (gpointer) selector); | |
| 575 gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->cancel_button), | |
| 576 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), | |
| 577 (gpointer) selector); | |
| 578 | |
| 579 gtk_widget_set_sensitive (config_dialog, FALSE); | |
| 580 gtk_widget_show (selector); | |
| 581 } | |
| 582 | |
| 583 static void | |
| 584 create_config_dialog (void) | |
| 585 { | |
| 586 GtkWidget *bbox, *button, *vbox, *frame, *table, *label; | |
| 587 | |
| 588 if (config_dialog != NULL) | |
| 589 return; | |
| 590 | |
| 591 /* Create the dialog */ | |
| 592 config_dialog = gtk_dialog_new (); | |
| 593 gtk_window_set_title (GTK_WINDOW (config_dialog), PACKAGE " " VERSION | |
| 594 " - Configuration"); | |
| 595 gtk_widget_set_usize (config_dialog, 500, 300); | |
| 596 gtk_container_border_width (GTK_CONTAINER (config_dialog), 8); | |
| 597 gtk_signal_connect_object (GTK_OBJECT (config_dialog), "delete-event", | |
| 598 GTK_SIGNAL_FUNC (destroy_config_dialog), NULL); | |
| 599 | |
| 600 /* OK / Cancel / Apply */ | |
| 601 bbox = gtk_hbutton_box_new (); | |
| 602 gtk_widget_show (bbox); | |
| 603 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); | |
| 604 gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 8); | |
| 605 gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 64, 0); | |
| 606 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (config_dialog)->action_area), | |
| 607 bbox, FALSE, FALSE, 0); | |
| 608 button = gtk_button_new_with_label ("OK"); | |
| 609 gtk_widget_show (button); | |
| 610 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL); | |
| 611 gtk_signal_connect (GTK_OBJECT (button), "clicked", | |
| 612 GTK_SIGNAL_FUNC (ok_button_cb), NULL); | |
| 613 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); | |
| 614 button = gtk_button_new_with_label ("Cancel"); | |
| 615 gtk_widget_show (button); | |
| 616 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL); | |
| 617 gtk_signal_connect (GTK_OBJECT (button), "clicked", | |
| 618 GTK_SIGNAL_FUNC (cancel_button_cb), NULL); | |
| 619 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); | |
| 620 button = gtk_button_new_with_label ("Apply"); | |
| 621 gtk_widget_show (button); | |
| 622 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL); | |
| 623 gtk_signal_connect (GTK_OBJECT (button), "clicked", | |
| 624 GTK_SIGNAL_FUNC (apply_button_cb), NULL); | |
| 625 gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0); | |
| 626 | |
| 627 | |
| 628 /* The vertical box */ | |
| 629 vbox = gtk_vbox_new (FALSE, 1); | |
| 630 gtk_widget_show (vbox); | |
| 631 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (config_dialog)->vbox), vbox, | |
| 632 TRUE, TRUE, 0); | |
| 633 | |
| 634 /* General options */ | |
| 635 frame = gtk_frame_new (NULL); | |
| 636 gtk_widget_show (frame); | |
| 637 gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); | |
| 638 gtk_frame_set_label (GTK_FRAME (frame), "General"); | |
| 639 table = gtk_table_new (2, 1, TRUE); | |
| 640 gtk_widget_show (table); | |
| 641 gtk_container_add (GTK_CONTAINER (frame), table); | |
| 642 label = gtk_label_new ("Preset File: "); | |
| 643 gtk_widget_show (label); | |
| 644 gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, | |
| 645 GTK_FILL, 0, 3, 3); | |
| 646 load_button = gtk_button_new_with_label (preset ? preset : "<default>"); | |
| 647 gtk_widget_show (load_button); | |
| 648 gtk_table_attach (GTK_TABLE (table), load_button, 1, 2, 0, 1, | |
| 649 GTK_EXPAND | GTK_FILL, 0, 3, 3); | |
| 650 gtk_signal_connect (GTK_OBJECT (load_button), "clicked", | |
| 651 GTK_SIGNAL_FUNC (load_preset_button_cb), NULL); | |
| 652 | |
| 653 /* Show it all */ | |
| 654 gtk_widget_show (config_dialog); | |
| 655 gtk_widget_grab_focus (config_dialog); | |
| 656 } |
