Mercurial > audlegacy
view Plugins/Visualization/libvisual-proxy/main.c @ 375:244cc47a7ae3 trunk
[svn] We have no choice but to continue as planned. Deploy the sentinels!
author | chainsaw |
---|---|
date | Sun, 01 Jan 2006 05:09:47 -0800 |
parents | bd81a73eadff |
children |
line wrap: on
line source
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <audacious/plugin.h> #include <libaudacious/util.h> #include <libaudacious/beepctrl.h> #include <SDL.h> #include <SDL_thread.h> #include <gtk/gtk.h> #include <glib/gi18n.h> #include <libvisual/libvisual.h> #include "config.h" #include "lv_bmp_config.h" #include "about.h" #define LV_XMMS_DEFAULT_INPUT_PLUGIN "alsa" #undef LV_XMMS_ENABLE_DEBUG /* SDL variables */ static SDL_Surface *screen = NULL; static SDL_Color sdlpal[256]; static SDL_Thread *render_thread; static SDL_mutex *pcm_mutex; /* Libvisual and visualisation variables */ static VisVideo *video; static VisPalette *pal; static char song_name[1024]; static char *cur_lv_plugin = NULL; static VisBin *bin = NULL; static VisSongInfo *songinfo; static Options *options; static int gl_plug = 0; static gint16 xmmspcm[2][512]; /* Thread state variables */ static int visual_running = 0; static int visual_stopped = 1; static void lv_bmp_init (void); static void lv_bmp_cleanup (void); static void lv_bmp_disable (VisPlugin *); static void lv_bmp_playback_start (void); static void lv_bmp_playback_stop (void); static void lv_bmp_render_pcm (gint16 data[2][512]); static int sdl_quit (void); static void sdl_set_pal (void); static void sdl_draw (SDL_Surface *screen); static int sdl_create (int width, int height); static int sdl_event_handle (void); static int visual_upload_callback (VisInput *input, VisAudio *audio, void *private); static int visual_resize (int width, int height); static int visual_initialize (int width, int height); static int visual_render (void*); static gint disable_func (gpointer data); static void dummy (GtkWidget *widget, gpointer data); VisPlugin *get_vplugin_info (void); VisPlugin lv_bmp_vp = { NULL, /* (void*) handle, filled in by xmms */ NULL, /* (char*) Filename, filled in by xmms */ 0, /* The session ID for attaching to the control socket */ "libvisual proxy plugin", /* description */ 2, /* Numbers of PCM channels wanted in the call to render_pcm */ 0, /* Numbers of freq channels wanted in the call to render_freq */ lv_bmp_init, /* init */ lv_bmp_cleanup, /* cleanup */ NULL, /* about */ NULL, /* configure */ lv_bmp_disable, /* disable plugin */ lv_bmp_playback_start, /* playback start */ lv_bmp_playback_stop, /* playback stop */ lv_bmp_render_pcm, /* render pcm */ NULL, /* render freq */ }; VisPlugin *get_vplugin_info () { return &lv_bmp_vp; } static char *lv_bmp_get_songname () { return xmms_remote_get_playlist_title (lv_bmp_vp.xmms_session, xmms_remote_get_playlist_pos (lv_bmp_vp.xmms_session)); } static void lv_bmp_init () { char **argv; int argc; gchar *msg; GtkWidget *msgwin; if (!visual_is_initialized ()) { argv = g_malloc (sizeof(char*)); argv[0] = g_strdup (_("Audacious plugin")); argc = 1; visual_init (&argc, &argv); g_free (argv[0]); g_free (argv); } #ifdef LV_XMMS_ENABLE_DEBUG visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_HIGH); #else visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_NONE); #endif options = lv_bmp_config_open (); if (!options) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot get options")); return; } lv_bmp_config_load_prefs (); if (SDL_Init (SDL_INIT_VIDEO) < 0) { msg = g_strconcat (_("Cannot initialize SDL!\n"), SDL_GetError(), "\n\n", PACKAGE_NAME, _(" will not be loaded."), NULL); msgwin = xmms_show_message ("libvisual-proxy", msg, _("Accept"), TRUE, GTK_SIGNAL_FUNC(dummy), NULL); gtk_widget_show (msgwin); g_free (msg); return; } pcm_mutex = SDL_CreateMutex (); if (strlen (options->last_plugin) <= 0 ) { visual_log (VISUAL_LOG_INFO, _("Last plugin: (none)")); } else { visual_log (VISUAL_LOG_INFO, _("Last plugin: %s"), options->last_plugin); } cur_lv_plugin = options->last_plugin; if (!(visual_actor_valid_by_name (cur_lv_plugin))) { visual_log (VISUAL_LOG_INFO, _("%s is not a valid actor plugin"), cur_lv_plugin); cur_lv_plugin = lv_bmp_config_get_next_actor (); } SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin); if (!cur_lv_plugin) { visual_log (VISUAL_LOG_CRITICAL, _("Could not get actor plugin")); lv_bmp_config_close (); return; } else { lv_bmp_config_set_current_actor (cur_lv_plugin); } visual_log (VISUAL_LOG_DEBUG, "calling SDL_CreateThread()"); render_thread = SDL_CreateThread ((void *) visual_render, NULL); } static void lv_bmp_cleanup () { visual_log (VISUAL_LOG_DEBUG, "entering cleanup..."); visual_running = 0; SDL_WaitThread (render_thread, NULL); render_thread = NULL; visual_stopped = 1; visual_log (VISUAL_LOG_DEBUG, "calling SDL_DestroyMutex()"); SDL_DestroyMutex (pcm_mutex); pcm_mutex = NULL; /* * WARNING This must be synchronized with config module. */ options->last_plugin = cur_lv_plugin; visual_log (VISUAL_LOG_DEBUG, "calling lv_bmp_config_save_prefs()"); lv_bmp_config_save_prefs (); visual_log (VISUAL_LOG_DEBUG, "closing config file"); lv_bmp_config_close (); visual_log (VISUAL_LOG_DEBUG, "destroying VisBin..."); visual_object_unref (VISUAL_OBJECT (bin)); visual_log (VISUAL_LOG_DEBUG, "calling sdl_quit()"); sdl_quit (); visual_log (VISUAL_LOG_DEBUG, "calling visual_quit()"); visual_quit (); } static void lv_bmp_disable (VisPlugin* plugin) { } static void lv_bmp_playback_start () { } static void lv_bmp_playback_stop () { } static void lv_bmp_render_pcm (gint16 data[2][512]) { if (visual_running == 1) { SDL_mutexP (pcm_mutex); memcpy (xmmspcm, data, sizeof(gint16)*2*512); strncpy (song_name, lv_bmp_get_songname (), 1023); SDL_mutexV (pcm_mutex); } } static int sdl_quit () { visual_log (VISUAL_LOG_DEBUG, "Calling SDL_FreeSurface()"); if (screen != NULL) SDL_FreeSurface (screen); screen = NULL; visual_log (VISUAL_LOG_DEBUG, "sdl_quit: calling SDL_Quit()"); /* * FIXME this doesn't work! */ SDL_Quit (); visual_log (VISUAL_LOG_DEBUG, "Leaving..."); return 0; } static void sdl_set_pal () { int i; visual_log_return_if_fail (screen != NULL); if (pal != NULL) { for (i = 0; i < 256; i ++) { sdlpal[i].r = pal->colors[i].r; sdlpal[i].g = pal->colors[i].g; sdlpal[i].b = pal->colors[i].b; } SDL_SetColors (screen, sdlpal, 0, 256); } } static void sdl_draw (SDL_Surface *screen) { visual_log_return_if_fail (screen != NULL); SDL_Flip (screen); } static int sdl_create (int width, int height) { const SDL_VideoInfo *videoinfo; int videoflags; if (screen != NULL) SDL_FreeSurface (screen); visual_log (VISUAL_LOG_DEBUG, "sdl_create video->bpp %d", video->bpp); visual_log (VISUAL_LOG_DEBUG, gl_plug ? "OpenGl plugin at create: yes" : "OpenGl plugin at create: no"); if (gl_plug == 1) { videoinfo = SDL_GetVideoInfo (); if (videoinfo == 0) { visual_log (VISUAL_LOG_CRITICAL, _("Could not get video info")); return -1; } videoflags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE; if (videoinfo->hw_available) videoflags |= SDL_HWSURFACE; else videoflags |= SDL_SWSURFACE; if (videoinfo->blit_hw) videoflags |= SDL_HWACCEL; SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); visual_log (VISUAL_LOG_DEBUG, "Setting video mode %dx%d", width, height); screen = SDL_SetVideoMode (width, height, 16, videoflags); } else { visual_log (VISUAL_LOG_DEBUG, "Setting video mode %dx%d", width, height); screen = SDL_SetVideoMode (width, height, video->bpp * 8, SDL_RESIZABLE); } SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY / 4, SDL_DEFAULT_REPEAT_INTERVAL / 4); visual_video_set_buffer (video, screen->pixels); visual_log (VISUAL_LOG_DEBUG, "pointer to the pixels: %p", screen->pixels); visual_video_set_pitch (video, screen->pitch); visual_log (VISUAL_LOG_DEBUG, "pitch: %d", video->pitch); return 0; } static int visual_initialize (int width, int height) { VisInput *input; VisVideoDepth depth; int ret; bin = visual_bin_new (); visual_bin_set_supported_depth (bin, VISUAL_VIDEO_DEPTH_ALL); // visual_bin_set_preferred_depth (bin, VISUAL_BIN_DEPTH_LOWEST); depth = visual_video_depth_enum_from_value (options->depth); if (depth == VISUAL_VIDEO_DEPTH_ERROR) depth = VISUAL_VIDEO_DEPTH_24BIT; options->depth = depth; video = visual_video_new (); ret = visual_video_set_depth (video, depth); if (ret < 0) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot set video depth")); return -1; } visual_video_set_dimension (video, width, height); ret = visual_bin_set_video (bin, video); if (ret < 0) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot set video")); return -1; } /*visual_bin_connect_by_names (bin, cur_lv_plugin, NULL);*/ visual_bin_connect_by_names (bin, cur_lv_plugin, LV_XMMS_DEFAULT_INPUT_PLUGIN); if (visual_bin_get_depth (bin) == VISUAL_VIDEO_DEPTH_GL) { visual_video_set_depth (video, VISUAL_VIDEO_DEPTH_GL); gl_plug = 1; } else { gl_plug = 0; } visual_log (VISUAL_LOG_DEBUG, gl_plug ? "OpenGl plugin: yes" : "OpenGl plugin: no"); ret = sdl_create (width, height); if (ret < 0) { return -1; } /* Called so the flag is set to FALSE, seen we create the initial environment here */ visual_bin_depth_changed (bin); input = visual_bin_get_input (bin); ret = visual_input_set_callback (input, visual_upload_callback, NULL); if (ret < 0) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot set input plugin callback")); return -1; } visual_bin_switch_set_style (bin, VISUAL_SWITCH_STYLE_MORPH); visual_bin_switch_set_automatic (bin, TRUE); visual_bin_switch_set_mode (bin, VISUAL_MORPH_MODE_TIME); visual_bin_switch_set_time (bin, 4, 0); visual_bin_realize (bin); visual_bin_sync (bin, FALSE); return 0; } static int visual_upload_callback (VisInput *input, VisAudio *audio, void *private_data) { int i; visual_log_return_val_if_fail (audio != NULL, -1); for (i = 0; i < 512; i++) { audio->plugpcm[0][i] = xmmspcm[0][i]; audio->plugpcm[1][i] = xmmspcm[1][i]; } return 0; } static int visual_resize (int width, int height) { visual_video_set_dimension (video, width, height); sdl_create (width, height); options->width = width; options->height = height; visual_bin_sync (bin, FALSE); return 0; } static int visual_render (void *arg) { visual_running = 1; visual_stopped = 0; static long render_time, now; long frame_length; long idle_time; long frames; int ret; ret = visual_initialize (options->width, options->height); if (ret < 0) { visual_log (VISUAL_LOG_CRITICAL, _("Cannot initialize plugin's visual stuff")); return -1; } frame_length = (1.0 / options->fps) * 1000; frames = 0; while (visual_running == 1) { /* Update songinfo */ songinfo = visual_actor_get_songinfo (visual_bin_get_actor (bin)); visual_songinfo_set_type (songinfo, VISUAL_SONGINFO_TYPE_SIMPLE); visual_songinfo_set_simple_name (songinfo, song_name); /* On depth change */ if (visual_bin_depth_changed (bin) == TRUE) { if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_LockSurface (screen); visual_video_set_buffer (video, screen->pixels); if (visual_bin_get_depth (bin) == VISUAL_VIDEO_DEPTH_GL) gl_plug = 1; else gl_plug = 0; sdl_create (options->width, options->height); visual_bin_sync (bin, TRUE); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_UnlockSurface (screen); } render_time = SDL_GetTicks(); if (gl_plug == 1) { visual_bin_run (bin); SDL_GL_SwapBuffers (); } else { if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_LockSurface (screen); visual_bin_run (bin); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_UnlockSurface (screen); pal = visual_bin_get_palette (bin); sdl_set_pal (); sdl_draw (screen); } now = SDL_GetTicks(); idle_time = now - render_time; if (idle_time < frame_length) usleep(idle_time * 900); sdl_event_handle (); if (options->fullscreen && !(screen->flags & SDL_FULLSCREEN)) SDL_WM_ToggleFullScreen (screen); frames++; /* * Sometime we actualize the frame_length, because we let user * choose maximum FPS dinamically. */ if (frames > options->fps) { frames = 0; frame_length = (1.0 / options->fps) * 1000; } } visual_stopped = 1; return 0; } static int sdl_event_handle () { SDL_Event event; VisEventQueue *vevent; char *next_plugin; while (SDL_PollEvent (&event)) { vevent = visual_plugin_get_eventqueue (visual_actor_get_plugin (visual_bin_get_actor (bin))); switch (event.type) { case SDL_KEYUP: visual_event_queue_add_keyboard (vevent, event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_UP); break; case SDL_KEYDOWN: visual_event_queue_add_keyboard (vevent, event.key.keysym.sym, event.key.keysym.mod, VISUAL_KEY_DOWN); switch (event.key.keysym.sym) { /* XMMS CONTROLS */ case SDLK_UP: xmms_remote_set_main_volume (lv_bmp_vp.xmms_session, xmms_remote_get_main_volume (lv_bmp_vp.xmms_session) + 1); break; case SDLK_DOWN: xmms_remote_set_main_volume (lv_bmp_vp.xmms_session, xmms_remote_get_main_volume (lv_bmp_vp.xmms_session) - 1); break; case SDLK_LEFT: if (xmms_remote_is_playing (lv_bmp_vp.xmms_session)) xmms_remote_jump_to_time (lv_bmp_vp.xmms_session, xmms_remote_get_output_time (lv_bmp_vp.xmms_session) - 5000); break; case SDLK_RIGHT: if (xmms_remote_is_playing (lv_bmp_vp.xmms_session)) xmms_remote_jump_to_time (lv_bmp_vp.xmms_session, xmms_remote_get_output_time (lv_bmp_vp.xmms_session) + 5000); break; case SDLK_z: xmms_remote_playlist_prev (lv_bmp_vp.xmms_session); break; case SDLK_x: xmms_remote_play (lv_bmp_vp.xmms_session); break; case SDLK_c: xmms_remote_pause (lv_bmp_vp.xmms_session); break; case SDLK_v: xmms_remote_stop (lv_bmp_vp.xmms_session); break; case SDLK_b: xmms_remote_playlist_next (lv_bmp_vp.xmms_session); break; /* PLUGIN CONTROLS */ case SDLK_F11: case SDLK_TAB: SDL_WM_ToggleFullScreen (screen); lv_bmp_config_toggle_fullscreen(); if ((screen->flags & SDL_FULLSCREEN) > 0) SDL_ShowCursor (SDL_DISABLE); else SDL_ShowCursor (SDL_ENABLE); break; case SDLK_a: next_plugin = lv_bmp_config_get_prev_actor (); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_LockSurface (screen); if (next_plugin != NULL && (strcmp (next_plugin, cur_lv_plugin) != 0)) { lv_bmp_config_set_current_actor (next_plugin); cur_lv_plugin = next_plugin; visual_bin_set_morph_by_name (bin, lv_bmp_config_morph_plugin()); visual_bin_switch_actor_by_name (bin, cur_lv_plugin); } SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_UnlockSurface (screen); break; case SDLK_s: next_plugin = lv_bmp_config_get_next_actor (); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_LockSurface (screen); if (next_plugin != NULL && (strcmp (next_plugin, cur_lv_plugin) != 0)) { lv_bmp_config_set_current_actor (next_plugin); cur_lv_plugin = next_plugin; visual_bin_set_morph_by_name (bin, lv_bmp_config_morph_plugin()); visual_bin_switch_actor_by_name (bin, cur_lv_plugin); } SDL_WM_SetCaption (cur_lv_plugin, cur_lv_plugin); if (SDL_MUSTLOCK (screen) == SDL_TRUE) SDL_UnlockSurface (screen); break; default: /* to avoid warnings */ break; } break; case SDL_VIDEORESIZE: visual_resize (event.resize.w, event.resize.h); break; case SDL_MOUSEMOTION: visual_event_queue_add_mousemotion (vevent, event.motion.x, event.motion.y); break; case SDL_MOUSEBUTTONDOWN: visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_DOWN, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: visual_event_queue_add_mousebutton (vevent, event.button.button, VISUAL_MOUSE_UP, event.button.x, event.button.y); break; case SDL_QUIT: GDK_THREADS_ENTER (); gtk_idle_add (disable_func, NULL); GDK_THREADS_LEAVE (); break; default: /* to avoid warnings */ break; } } return 0; } static gint disable_func (gpointer data) { lv_bmp_vp.disable_plugin (&lv_bmp_vp); return FALSE; } static void dummy (GtkWidget *widget, gpointer data) { }