comparison Plugins/Visualization/libvisual-proxy/main.c @ 61:fa848bd484d8 trunk

[svn] Move plugins to Plugins/
author nenolod
date Fri, 28 Oct 2005 22:58:11 -0700
parents
children 256b3acc87d4
comparison
equal deleted inserted replaced
60:1771f253e1b2 61:fa848bd484d8
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5
6 #include <audacious/plugin.h>
7 #include <audacious/util.h>
8 #include <libaudacious/beepctrl.h>
9
10 #include <SDL.h>
11 #include <SDL_thread.h>
12
13 #include <gtk/gtk.h>
14 #include <glib/gi18n.h>
15
16 #include <libvisual/libvisual.h>
17
18 #include "config.h"
19
20 #include "lv_bmp_config.h"
21 #include "about.h"
22
23 #define LV_XMMS_DEFAULT_INPUT_PLUGIN "esd"
24
25 /* SDL variables */
26 static SDL_Surface *screen = NULL;
27 static SDL_Color sdlpal[256];
28 static SDL_Thread *render_thread;
29 static SDL_mutex *pcm_mutex;
30 static SDL_Surface *icon;
31
32 /* Libvisual and visualisation variables */
33 static VisVideo *video;
34 static VisPalette *pal;
35
36 static char song_name[1024];
37 static const char *cur_lv_plugin = NULL;
38
39 static VisBin *bin = NULL;
40
41 static VisSongInfo *songinfo;
42
43 static Options *options;
44
45 static int gl_plug = 0;
46
47 static gint16 xmmspcm[2][512];
48
49 /* Thread state variables */
50 static int visual_running = 0;
51 static int visual_stopped = 1;
52
53 static void lv_bmp_init (void);
54 static void lv_bmp_cleanup (void);
55 static void lv_bmp_disable (VisPlugin *);
56 static void lv_bmp_playback_start (void);
57 static void lv_bmp_playback_stop (void);
58 static void lv_bmp_render_pcm (gint16 data[2][512]);
59
60 static int sdl_quit (void);
61 static void sdl_set_pal (void);
62 static void sdl_draw (SDL_Surface *screen);
63 static int sdl_create (int width, int height);
64 static int sdl_event_handle (void);
65
66 static int visual_upload_callback (VisInput *input, VisAudio *audio, void *private);
67 static int visual_resize (int width, int height);
68 static int visual_initialize (int width, int height);
69 static int visual_render (void*);
70
71 static gint disable_func (gpointer data);
72 static void dummy (GtkWidget *widget, gpointer data);
73
74 VisPlugin *get_vplugin_info (void);
75
76 VisPlugin lv_bmp_vp =
77 {
78 NULL, /* (void*) handle, filled in by xmms */
79 NULL, /* (char*) Filename, filled in by xmms */
80 0, /* The session ID for attaching to the control socket */
81 "libvisual proxy plugin", /* description */
82 2, /* Numbers of PCM channels wanted in the call to render_pcm */
83 0, /* Numbers of freq channels wanted in the call to render_freq */
84 lv_bmp_init, /* init */
85 lv_bmp_cleanup, /* cleanup */
86 NULL, /* about */
87 NULL, /* configure */
88 lv_bmp_disable, /* disable plugin */
89 lv_bmp_playback_start, /* playback start */
90 lv_bmp_playback_stop, /* playback stop */
91 lv_bmp_render_pcm, /* render pcm */
92 NULL, /* render freq */
93 };
94
95 VisPlugin *get_vplugin_info ()
96 {
97 return &lv_bmp_vp;
98 }
99
100 static char *lv_bmp_get_songname ()
101 {
102 return xmms_remote_get_playlist_title (lv_bmp_vp.xmms_session,
103 xmms_remote_get_playlist_pos (lv_bmp_vp.xmms_session));
104 }
105
106 static void lv_bmp_init ()
107 {
108 char **argv;
109 int argc;
110 int ret;
111 gchar *msg;
112 GtkWidget *msgwin;
113
114 if (!visual_is_initialized ()) {
115 argv = g_malloc (sizeof(char*));
116 argv[0] = g_strdup (_("XMMS plugin"));
117 argc = 1;
118
119 visual_init (&argc, &argv);
120
121 g_free (argv[0]);
122 g_free (argv);
123 }
124
125 #if LV_XMMS_ENABLE_DEBUG
126 visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_HIGH);
127 #endif
128 /*g_print ("Trying to set verboseness\n");
129 visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW);
130 g_print ("Verboseness done\n");*/
131
132 options = lv_bmp_config_open ();
133 if (!options) {
134 visual_log (VISUAL_LOG_CRITICAL, _("Cannot get options"));
135 return;
136 }
137
138 lv_bmp_config_load_prefs ();
139
140 if (SDL_Init (SDL_INIT_VIDEO) < 0) {
141 msg = g_strconcat (_("Cannot initialize SDL!\n"),
142 SDL_GetError(),
143 "\n\n", PACKAGE_NAME,
144 _(" will not be loaded."), 0);
145 msgwin = xmms_show_message ("libvisual-proxy", msg, _("Accept"), TRUE, dummy, NULL);
146 gtk_widget_show (msgwin);
147 g_free (msg);
148 return;
149 }
150
151 icon = SDL_LoadBMP (options->icon_file);
152 if (icon)
153 SDL_WM_SetIcon (icon, NULL);
154 else
155 visual_log (VISUAL_LOG_WARNING, _("Cannot not load icon: %s"), SDL_GetError());
156
157 pcm_mutex = SDL_CreateMutex ();
158
159 if (strlen (options->last_plugin) <= 0 ) {
160 visual_log (VISUAL_LOG_INFO, _("Last plugin: (none)"));
161 } else {
162 visual_log (VISUAL_LOG_INFO, _("Last plugin: %s"), options->last_plugin);
163 }
164
165 cur_lv_plugin = options->last_plugin;
166 if (!(visual_actor_valid_by_name (cur_lv_plugin))) {
167 visual_log (VISUAL_LOG_INFO, _("%s is not a valid actor plugin"), cur_lv_plugin);
168 cur_lv_plugin = lv_bmp_config_get_next_actor ();
169 }
170
171 SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin);
172
173 if (!cur_lv_plugin) {
174 visual_log (VISUAL_LOG_CRITICAL, _("Could not get actor plugin"));
175 lv_bmp_config_close ();
176 return;
177 } else {
178 lv_bmp_config_set_current_actor (cur_lv_plugin);
179 }
180
181 visual_log (VISUAL_LOG_DEBUG, "calling SDL_CreateThread()");
182
183 render_thread = SDL_CreateThread ((void *) visual_render, NULL);
184 }
185
186 static void lv_bmp_cleanup ()
187 {
188 visual_log (VISUAL_LOG_DEBUG, "entering cleanup...");
189 visual_running = 0;
190
191 SDL_WaitThread (render_thread, NULL);
192
193 render_thread = NULL;
194 visual_stopped = 1;
195
196 visual_log (VISUAL_LOG_DEBUG, "calling SDL_DestroyMutex()");
197 SDL_DestroyMutex (pcm_mutex);
198
199 pcm_mutex = NULL;
200
201 /*
202 * WARNING This must be synchronized with config module.
203 */
204
205 options->last_plugin = cur_lv_plugin;
206
207 visual_log (VISUAL_LOG_DEBUG, "calling lv_bmp_config_save_prefs()");
208 lv_bmp_config_save_prefs ();
209
210 visual_log (VISUAL_LOG_DEBUG, "closing config file");
211 lv_bmp_config_close ();
212
213 if (icon != NULL)
214 SDL_FreeSurface (icon);
215
216 visual_log (VISUAL_LOG_DEBUG, "destroying VisBin...");
217 visual_object_unref (VISUAL_OBJECT (bin));
218
219 visual_log (VISUAL_LOG_DEBUG, "calling sdl_quit()");
220 sdl_quit ();
221
222 visual_log (VISUAL_LOG_DEBUG, "calling visual_quit()");
223 visual_quit ();
224 }
225
226 static void lv_bmp_disable (VisPlugin* plugin)
227 {
228
229 }
230
231 static void lv_bmp_playback_start ()
232 {
233
234 }
235 static void lv_bmp_playback_stop ()
236 {
237
238 }
239
240 static void lv_bmp_render_pcm (gint16 data[2][512])
241 {
242 if (visual_running == 1) {
243 SDL_mutexP (pcm_mutex);
244 memcpy (xmmspcm, data, sizeof(gint16)*2*512);
245 strncpy (song_name, lv_bmp_get_songname (), 1023);
246 SDL_mutexV (pcm_mutex);
247 }
248 }
249
250 static int sdl_quit ()
251 {
252 visual_log (VISUAL_LOG_DEBUG, "Calling SDL_FreeSurface()");
253 if (screen != NULL)
254 SDL_FreeSurface (screen);
255
256 screen = NULL;
257
258 visual_log (VISUAL_LOG_DEBUG, "sdl_quit: calling SDL_Quit()");
259 /*
260 * FIXME this doesn't work!
261 */
262 SDL_Quit ();
263
264 visual_log (VISUAL_LOG_DEBUG, "Leaving...");
265 return 0;
266 }
267
268 static void sdl_set_pal ()
269 {
270 int i;
271
272 visual_log_return_if_fail (screen != NULL);
273
274 if (pal != NULL) {
275 for (i = 0; i < 256; i ++) {
276 sdlpal[i].r = pal->colors[i].r;
277 sdlpal[i].g = pal->colors[i].g;
278 sdlpal[i].b = pal->colors[i].b;
279 }
280 SDL_SetColors (screen, sdlpal, 0, 256);
281 }
282 }
283
284 static void sdl_draw (SDL_Surface *screen)
285 {
286 visual_log_return_if_fail (screen != NULL);
287 SDL_Flip (screen);
288 }
289
290 static int sdl_create (int width, int height)
291 {
292 const SDL_VideoInfo *videoinfo;
293 int videoflags;
294
295 if (screen != NULL)
296 SDL_FreeSurface (screen);
297
298 visual_log (VISUAL_LOG_DEBUG, "sdl_create video->bpp %d", video->bpp);
299 visual_log (VISUAL_LOG_DEBUG, gl_plug ? "OpenGl plugin at create: yes" : "OpenGl plugin at create: no");
300
301 if (gl_plug == 1) {
302 videoinfo = SDL_GetVideoInfo ();
303
304 if (videoinfo == 0) {
305 visual_log (VISUAL_LOG_CRITICAL, _("Could not get video info"));
306 return -1;
307 }
308
309 videoflags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE;
310
311 if (videoinfo->hw_available)
312 videoflags |= SDL_HWSURFACE;
313 else
314 videoflags |= SDL_SWSURFACE;
315
316 if (videoinfo->blit_hw)
317 videoflags |= SDL_HWACCEL;
318
319 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
320
321 visual_log (VISUAL_LOG_DEBUG, "Setting video mode %dx%d", width, height);
322 screen = SDL_SetVideoMode (width, height, 16, videoflags);
323 } else {
324 visual_log (VISUAL_LOG_DEBUG, "Setting video mode %dx%d", width, height);
325 screen = SDL_SetVideoMode (width, height, video->bpp * 8, SDL_RESIZABLE);
326 }
327
328 SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY / 4, SDL_DEFAULT_REPEAT_INTERVAL / 4);
329
330 visual_video_set_buffer (video, screen->pixels);
331 visual_log (VISUAL_LOG_DEBUG, "pointer to the pixels: %p", screen->pixels);
332
333 visual_video_set_pitch (video, screen->pitch);
334 visual_log (VISUAL_LOG_DEBUG, "pitch: %d", video->pitch);
335
336 return 0;
337 }
338
339 static int visual_initialize (int width, int height)
340 {
341 VisInput *input;
342 VisVideoDepth depth;
343 int ret;
344
345 bin = visual_bin_new ();
346 visual_bin_set_supported_depth (bin, VISUAL_VIDEO_DEPTH_ALL);
347 // visual_bin_set_preferred_depth (bin, VISUAL_BIN_DEPTH_LOWEST);
348
349 depth = visual_video_depth_enum_from_value (options->depth);
350 if (depth == VISUAL_VIDEO_DEPTH_ERROR)
351 depth = VISUAL_VIDEO_DEPTH_24BIT;
352 options->depth = depth;
353
354 video = visual_video_new ();
355
356 ret = visual_video_set_depth (video, depth);
357 if (ret < 0) {
358 visual_log (VISUAL_LOG_CRITICAL, _("Cannot set video depth"));
359 return -1;
360 }
361 visual_video_set_dimension (video, width, height);
362
363 ret = visual_bin_set_video (bin, video);
364 if (ret < 0) {
365 visual_log (VISUAL_LOG_CRITICAL, _("Cannot set video"));
366 return -1;
367 }
368 /*visual_bin_connect_by_names (bin, cur_lv_plugin, NULL);*/
369 visual_bin_connect_by_names (bin, cur_lv_plugin, LV_XMMS_DEFAULT_INPUT_PLUGIN);
370
371 if (visual_bin_get_depth (bin) == VISUAL_VIDEO_DEPTH_GL) {
372 visual_video_set_depth (video, VISUAL_VIDEO_DEPTH_GL);
373 gl_plug = 1;
374 } else {
375 gl_plug = 0;
376 }
377
378 visual_log (VISUAL_LOG_DEBUG, gl_plug ? "OpenGl plugin: yes" : "OpenGl plugin: no");
379 ret = sdl_create (width, height);
380 if (ret < 0) {
381 return -1;
382 }
383
384 /* Called so the flag is set to FALSE, seen we create the initial environment here */
385 visual_bin_depth_changed (bin);
386
387 input = visual_bin_get_input (bin);
388 ret = visual_input_set_callback (input, visual_upload_callback, NULL);
389 if (ret < 0) {
390 visual_log (VISUAL_LOG_CRITICAL, _("Cannot set input plugin callback"));
391 return -1;
392 }
393
394 visual_bin_switch_set_style (bin, VISUAL_SWITCH_STYLE_MORPH);
395 visual_bin_switch_set_automatic (bin, TRUE);
396 visual_bin_switch_set_mode (bin, VISUAL_MORPH_MODE_TIME);
397 visual_bin_switch_set_time (bin, 4, 0);
398
399 visual_bin_realize (bin);
400 visual_bin_sync (bin, FALSE);
401
402 return 0;
403 }
404
405 static int visual_upload_callback (VisInput *input, VisAudio *audio, void *private_data)
406 {
407 int i;
408
409 visual_log_return_val_if_fail (audio != NULL, -1);
410
411 for (i = 0; i < 512; i++) {
412 audio->plugpcm[0][i] = xmmspcm[0][i];
413 audio->plugpcm[1][i] = xmmspcm[1][i];
414 }
415
416 return 0;
417 }
418
419 static int visual_resize (int width, int height)
420 {
421 visual_video_set_dimension (video, width, height);
422
423 sdl_create (width, height);
424
425 options->width = width;
426 options->height = height;
427
428 visual_bin_sync (bin, FALSE);
429
430 return 0;
431 }
432
433 static int visual_render (void *arg)
434 {
435 visual_running = 1;
436 visual_stopped = 0;
437 static long render_time, now;
438 long frame_length;
439 long idle_time;
440 long frames;
441 int ret;
442
443 ret = visual_initialize (options->width, options->height);
444 if (ret < 0) {
445 visual_log (VISUAL_LOG_CRITICAL, _("Cannot initialize plugin's visual stuff"));
446 return -1;
447 }
448
449 frame_length = (1.0 / options->fps) * 1000;
450 frames = 0;
451 while (visual_running == 1) {
452 /* Update songinfo */
453 songinfo = visual_actor_get_songinfo (visual_bin_get_actor (bin));
454 visual_songinfo_set_type (songinfo, VISUAL_SONGINFO_TYPE_SIMPLE);
455
456 visual_songinfo_set_simple_name (songinfo, song_name);
457
458 /* On depth change */
459 if (visual_bin_depth_changed (bin) == TRUE) {
460 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
461 SDL_LockSurface (screen);
462
463 visual_video_set_buffer (video, screen->pixels);
464 if (visual_bin_get_depth (bin) == VISUAL_VIDEO_DEPTH_GL)
465 gl_plug = 1;
466 else
467 gl_plug = 0;
468
469 sdl_create (options->width, options->height);
470 visual_bin_sync (bin, TRUE);
471
472 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
473 SDL_UnlockSurface (screen);
474 }
475
476 render_time = SDL_GetTicks();
477
478 if (gl_plug == 1) {
479 visual_bin_run (bin);
480
481 SDL_GL_SwapBuffers ();
482 } else {
483 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
484 SDL_LockSurface (screen);
485
486 visual_bin_run (bin);
487
488 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
489 SDL_UnlockSurface (screen);
490
491 pal = visual_bin_get_palette (bin);
492 sdl_set_pal ();
493
494 sdl_draw (screen);
495 }
496
497 now = SDL_GetTicks();
498 idle_time = now - render_time;
499
500 if (idle_time < frame_length)
501 usleep(idle_time * 900);
502
503 sdl_event_handle ();
504
505 if (options->fullscreen && !(screen->flags & SDL_FULLSCREEN))
506 SDL_WM_ToggleFullScreen (screen);
507 frames++;
508 /*
509 * Sometime we actualize the frame_length, because we let user
510 * choose maximum FPS dinamically.
511 */
512 if (frames > options->fps) {
513 frames = 0;
514 frame_length = (1.0 / options->fps) * 1000;
515 }
516 }
517
518 visual_stopped = 1;
519 return 0;
520 }
521
522 static int sdl_event_handle ()
523 {
524 SDL_Event event;
525 VisEventQueue *vevent;
526 const char *next_plugin;
527
528 while (SDL_PollEvent (&event)) {
529 vevent = visual_plugin_get_eventqueue (visual_actor_get_plugin (visual_bin_get_actor (bin)));
530
531 switch (event.type) {
532 case SDL_KEYUP:
533 visual_event_queue_add_keyboard (vevent, event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_UP);
534 break;
535
536 case SDL_KEYDOWN:
537 visual_event_queue_add_keyboard (vevent, event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_DOWN);
538
539 switch (event.key.keysym.sym) {
540 /* XMMS CONTROLS */
541 case SDLK_UP:
542 xmms_remote_set_main_volume (lv_bmp_vp.xmms_session,
543 xmms_remote_get_main_volume (lv_bmp_vp.xmms_session) + 1);
544 break;
545 case SDLK_DOWN:
546 xmms_remote_set_main_volume (lv_bmp_vp.xmms_session,
547 xmms_remote_get_main_volume (lv_bmp_vp.xmms_session) - 1);
548 break;
549 case SDLK_LEFT:
550 if (xmms_remote_is_playing (lv_bmp_vp.xmms_session))
551 xmms_remote_jump_to_time (lv_bmp_vp.xmms_session,
552 xmms_remote_get_output_time (lv_bmp_vp.xmms_session) - 5000);
553 break;
554 case SDLK_RIGHT:
555 if (xmms_remote_is_playing (lv_bmp_vp.xmms_session))
556 xmms_remote_jump_to_time (lv_bmp_vp.xmms_session,
557 xmms_remote_get_output_time (lv_bmp_vp.xmms_session) + 5000);
558 break;
559 case SDLK_z:
560 xmms_remote_playlist_prev (lv_bmp_vp.xmms_session);
561 break;
562
563 case SDLK_x:
564 xmms_remote_play (lv_bmp_vp.xmms_session);
565 break;
566
567 case SDLK_c:
568 xmms_remote_pause (lv_bmp_vp.xmms_session);
569 break;
570
571 case SDLK_v:
572 xmms_remote_stop (lv_bmp_vp.xmms_session);
573 break;
574
575 case SDLK_b:
576 xmms_remote_playlist_next (lv_bmp_vp.xmms_session);
577 break;
578
579 /* PLUGIN CONTROLS */
580 case SDLK_F11:
581 case SDLK_TAB:
582 SDL_WM_ToggleFullScreen (screen);
583 lv_bmp_config_toggle_fullscreen();
584
585 if ((screen->flags & SDL_FULLSCREEN) > 0)
586 SDL_ShowCursor (SDL_DISABLE);
587 else
588 SDL_ShowCursor (SDL_ENABLE);
589
590 break;
591
592 case SDLK_a:
593 next_plugin = lv_bmp_config_get_prev_actor ();
594
595 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
596 SDL_LockSurface (screen);
597
598 if (next_plugin != NULL && (strcmp (next_plugin, cur_lv_plugin) != 0)) {
599 lv_bmp_config_set_current_actor (next_plugin);
600 cur_lv_plugin = next_plugin;
601 visual_bin_set_morph_by_name (bin, lv_bmp_config_morph_plugin());
602 visual_bin_switch_actor_by_name (bin, cur_lv_plugin);
603 }
604
605 SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin);
606
607 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
608 SDL_UnlockSurface (screen);
609
610 break;
611
612 case SDLK_s:
613 next_plugin = lv_bmp_config_get_next_actor ();
614
615 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
616 SDL_LockSurface (screen);
617
618 if (next_plugin != NULL && (strcmp (next_plugin, cur_lv_plugin) != 0)) {
619 lv_bmp_config_set_current_actor (next_plugin);
620 cur_lv_plugin = next_plugin;
621 visual_bin_set_morph_by_name (bin, lv_bmp_config_morph_plugin());
622 visual_bin_switch_actor_by_name (bin, cur_lv_plugin);
623 }
624
625 SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin);
626
627 if (SDL_MUSTLOCK (screen) == SDL_TRUE)
628 SDL_UnlockSurface (screen);
629
630 break;
631
632 default: /* to avoid warnings */
633 break;
634 }
635 break;
636
637 case SDL_VIDEORESIZE:
638 visual_resize (event.resize.w, event.resize.h);
639 break;
640
641 case SDL_MOUSEMOTION:
642 visual_event_queue_add_mousemotion (vevent, event.motion.x, event.motion.y);
643 break;
644
645 case SDL_MOUSEBUTTONDOWN:
646 visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_DOWN,
647 event.button.x, event.button.y);
648 break;
649
650 case SDL_MOUSEBUTTONUP:
651 visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_UP,
652 event.button.x, event.button.y);
653 break;
654
655 case SDL_QUIT:
656 GDK_THREADS_ENTER ();
657 gtk_idle_add (disable_func, NULL);
658 GDK_THREADS_LEAVE ();
659 break;
660
661 default: /* to avoid warnings */
662 break;
663 }
664 }
665
666 return 0;
667 }
668
669 static gint disable_func (gpointer data)
670 {
671 lv_bmp_vp.disable_plugin (&lv_bmp_vp);
672
673 return FALSE;
674 }
675
676
677 static void dummy (GtkWidget *widget, gpointer data)
678 {
679 }
680