/* scivi - visualization plugin for XMMS * Copyright (C) 2003 Vitaly V. Bursov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include "common.h" #include "scivi.h" #include "dynam.h" #include "gui.h" #include "fpsctl.h" #include "wave.h" #include "utilf.h" #include "utilx.h" #include "utilsnd.h" #include "presets.h" static void image_postprocess(Scivi *scivi, DynamicsData *dyn_data, GLuint *tex_main, GLuint list_main); /***************************************************************************** */ static void setup_texture_filter(Scivi *scivi, int mipmap) { if (mipmap && GL_HAS(GL_SGIS_generate_mipmap)){ sc_glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, TRUE); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } static void setup_opengl_int(Scivi *scivi) { float alight[4] = { 1.0f, 1.0f, 1.0f, 1.0f}; sc_glEnable(GL_LINE_SMOOTH); sc_glEnable(GL_POINT_SMOOTH); sc_glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); sc_glViewport( 0, 0, scivi->pbuf_w, scivi->pbuf_h ); sc_glMatrixMode(GL_PROJECTION); sc_glLoadIdentity(); sc_glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0, 1.0); /* TODO get rid of this */ sc_glEnable(GL_LIGHTING); sc_glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alight); // sc_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, alight); sc_glEnable(GL_BLEND); sc_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); sc_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); setup_texture_filter(scivi, 1); } static void setup_opengl_view(Scivi *scivi) { float alight[4] = { 1.0f, 1.0f, 1.0f, 1.0f}; sc_glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); sc_glViewport( 0, 0, scivi->width, scivi->height ); sc_glMatrixMode(GL_PROJECTION); sc_glLoadIdentity(); sc_glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0); /* TODO get rid of this */ // sc_glEnable(GL_LIGHTING); // sc_glLightModelfv(GL_LIGHT_MODEL_AMBIENT, alight); // sc_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, alight); sc_glEnable(GL_BLEND); sc_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); sc_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } /* * * * * * */ #define C(x) (dyn_data-> x) static int plugin_thread_process_event(Scivi *scivi, DynamicsData *dyn_data, Gui gui) { XEvent ev; gint tmp; gint pl_pos; gint out_time; gint pl_time; XNextEvent(XDPY, &ev); switch (ev.type){ #define SHIFT (ev.xkey.state & ShiftMask) #define KEY (ev.xkey.keycode) case KeyPress:{ KeySym ks; if (ev.xkey.window != XWIN) break; ks = XKeycodeToKeysym(XDPY, KEY, 0); switch (ks){ /* * * XMMS Control * */ case XK_space: if (xmms_remote_is_playing(SES)) xmms_remote_pause(SES); else xmms_remote_play(SES); break; /* Next/Prev song */ case XK_Page_Up: xmms_remote_playlist_prev(SES); break; case XK_Page_Down: xmms_remote_playlist_next(SES); break; /* Seek +- 5 sec */ case XK_Left: out_time = xmms_remote_get_output_time(SES) - 5000; if (out_time < 0) out_time = 0; xmms_remote_jump_to_time(SES, out_time); break; case XK_Right: pl_pos = xmms_remote_get_playlist_pos(SES); pl_time = xmms_remote_get_playlist_time(SES, pl_pos); out_time = xmms_remote_get_output_time(SES) + 5000; if (out_time > pl_time) out_time = pl_time; xmms_remote_jump_to_time(SES, out_time + 5000); break; /* * * SCIVI Control * */ case XK_r: if (SHIFT){ C(osc_resolution)--; if (C(osc_resolution) < 0) C(osc_resolution) = 0; } else { C(osc_resolution)++; } dprintf("osc_resolution set to %f\n", C(osc_resolution)); break; case XK_o: if (SHIFT){ C(osc_type)--; if (C(osc_type) < 0) C(osc_type) = 0; } else { C(osc_type)++; } dprintf("osc_type set to %f\n", C(osc_type)); break; case XK_v: GDK_THREADS_ENTER(); gtk_idle_add(scivi->contols_spawn_func, NULL); GDK_THREADS_LEAVE(); scivi_switchto_root(scivi); dprintf("scivi_switchto_root()\n"); break; case XK_w: C(opt_wireframe) = !C(opt_wireframe); dprintf("opt_wireframe set to %f\n", C(opt_wireframe)); break; case XK_p: if (SHIFT){ C(opt_active_preset)--; if (C(opt_active_preset) < 0) C(opt_active_preset) = 0; } else { C(opt_active_preset)++; } dprintf("opt_active_preset set to %d\n", C(opt_active_preset)); break; case XK_f: C(opt_reread_presets) = 1; dprintf("opt_reread_presets set to %d\n", C(opt_reread_presets)); break; case XK_s: scivi->plugin_toggle_fullscreen = 1; break; } break; } #undef SHIFT #undef KEY case ClientMessage: if ((ev.xclient.format == 32) && (ev.xclient.data.l[0] == scivi->X.wm_delete)){ GDK_THREADS_ENTER(); gtk_idle_add(scivi->disable_func, NULL); GDK_THREADS_LEAVE(); scivi->thread_quit_flag = 1; return 1; } } return 0; } static int plugin_thread_handle_events(Scivi *scivi, DynamicsData *dyn_data, Gui gui) { if (XEventsQueued(XDPY, QueuedAfterReading)){ return plugin_thread_process_event(scivi, dyn_data, gui); } return 0; } void *scivi_plugin_thread(void *p) { Scivi *scivi = (Scivi *)p; DynamicsData *dyn_data; FPSControl fps_control; FPSController *fps; Gui gui; unsigned int tmp; int tmpi; GLfloat matstart[4]; GLfloat matdecay[4]; GLfloat matosc[4]; GLfloat vc0[3]; int first = 1; float (*pcm_data)[512] = NULL; float pcm_data_count = 0; float (*freq_data)[256] = NULL; float freq_data_count = 0; /* TODO: is it better to interleve data??? */ float waveform[2][512]; int mesh_size_x = 40; int mesh_size_y = 40; /* TODO: is it better to interleve data??? */ /* float mesh_x[ mesh_size_x+1 ][ mesh_size_y+1 ]; float mesh_y[ mesh_size_x+1 ][ mesh_size_y+1 ]; float mesh_tex_x[ mesh_size_x+1 ][ mesh_size_y+1 ]; float mesh_tex_y[ mesh_size_x+1 ][ mesh_size_y+1 ]; */ /* row: x11 x12 x13 x14 y11 y12 y13 y14 u11 u12 u13 u14 v11 v12 v13 v14 x15... .... */ float mesh_c[ (mesh_size_y+1) * (mesh_size_x+10)*4 ]; int mesh_cnt, mesh_lx, mesh_ly; /* preset stuff */ PresetInfo *presets = NULL; int presets_count = 0; int preset_active; #define TEXTURES_ALLOC 5 GLuint tex_main[TEXTURES_ALLOC]; #define LISTS_ALLOC 5 GLuint list_main; scivi->visual_mode = -1; scivi->width = 640; scivi->height = 480; scivi->pbuf_want_w = 512; scivi->pbuf_want_h = 512; scivi->fps_limit_method = 0; scivi->max_fps = 0; scivi->vsync_enable = 0; SCIVICFG_LOCK(); scivi_plugin_read_config(scivi); SCIVICFG_UNLOCK(); scivi->aspect = (float)scivi->width/scivi->height; if ((tmpi = scivi_init_x(scivi))){ scivi_finit_x(scivi, tmpi); return (void*)3; } scivi_switchto_window(scivi); scivi_check_gl_extensions(); dyn_data = scivi_dyn_data_init(); if (dyn_data == NULL){ scivi_finit_x(scivi, 0); return (void*)2; } C(osc_resolution) = 0; C(opt_active_preset) = 0; C(opt_reread_presets) = 0; /* Do basic OpenGL setup */ scivi_activate_pbuffer(scivi); setup_opengl_int(scivi); scivi_activate_window(scivi); setup_opengl_view(scivi); /* initialize screen size-dependent variables */ C(width) = 2.0f*scivi->aspect; C(height) = 2.0f; C(right) = C(width)/2; C(left) = -C(right); C(top) = C(height)/2; C(bottom) = -C(top); SCIVICFG_LOCK(); presets_count = scivi_preset_load_from_dirs(scivi->preset_dirs, &presets); SCIVICFG_UNLOCK(); gui = gui_setup(scivi->font_filename); #if 0 if (!gui) eprintf("GUI initialization failed.\n"); #endif gui_set_dimensions(gui, scivi->width, scivi->height); if (presets_count <= 0){ Xprintf("warning: no presets loaded\n"); preset_active = -1; scivi_dyn_init_code_from_strings( dyn_data, "reset();" "decay = 0.95;", NULL, NULL, NULL); } else { dprintf("loaded %d presets\n", presets_count); preset_active = C(opt_active_preset); scivi_dyn_init_code( dyn_data, &presets[preset_active]); } sc_glGenTextures(TEXTURES_ALLOC, tex_main); list_main = sc_glGenLists(LISTS_ALLOC); if (presets && (preset_active >= 0)) gui_set_presetinfo(gui, &presets[preset_active]); fps = scivi_get_fps_ctl_by_uid(scivi->fps_limit_method); fps_control = fps->fps_control_init(scivi, dyn_data, gui); scivi_waveform_init(); /* Initialize mesh */ { int i, j, p; float t; /* for (i=0;i<=mesh_size_x;i++) for (j=0;j<=mesh_size_y;j++){ mesh_x[i][j] = (2.0f / mesh_size_x * i - 1.0f)*scivi->aspect; mesh_y[i][j] = (2.0f / mesh_size_y * j - 1.0f); } */ p=0; mesh_cnt = 0; /* TODO calculate */ mesh_ly = 0; for (j=0;j<=mesh_size_y;j++){ t = (2.0f / mesh_size_y * j - 1.0f); if (j == mesh_size_y) mesh_ly = p; for (i=0;i<=mesh_size_x;i+=4){ mesh_c[p+0] = (2.0f / mesh_size_x * (i+0) - 1.0f)*scivi->aspect; mesh_c[p+1] = (2.0f / mesh_size_x * (i+1) - 1.0f)*scivi->aspect; mesh_c[p+2] = (2.0f / mesh_size_x * (i+2) - 1.0f)*scivi->aspect; mesh_c[p+3] = (2.0f / mesh_size_x * (i+3) - 1.0f)*scivi->aspect; mesh_c[p+4] = t; mesh_c[p+5] = t; mesh_c[p+6] = t; mesh_c[p+7] = t; p+=4*4; mesh_cnt += 4; } } } #define LIST_DRAW_MAIN_TEX (list_main+0) sc_glNewList(LIST_DRAW_MAIN_TEX, GL_COMPILE); sc_glBindTexture(GL_TEXTURE_2D, tex_main[0]); sc_glEnable(GL_TEXTURE_2D); sc_glBegin(GL_TRIANGLE_STRIP); sc_glTexCoord2f(0.0f, 0.0f); sc_glVertex2f( 0.0f, 0.0f); sc_glTexCoord2f(1.0f, 0.0f); sc_glVertex2f( 1.0f, 0.0f); sc_glTexCoord2f(0.0f, 1.0f); sc_glVertex2f( 0.0f, 1.0f); sc_glTexCoord2f(1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); sc_glDisable(GL_TEXTURE_2D); sc_glEndList(); #define LIST_DRAW_LINE_RECT (list_main+1) sc_glNewList(LIST_DRAW_LINE_RECT, GL_COMPILE); sc_glBegin(GL_LINE_LOOP); sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glVertex2f( -1.0f, 1.0f); sc_glEnd(); sc_glEndList(); #define LIST_DRAW_DECAY_FIX_RECT (list_main+2) sc_glNewList(LIST_DRAW_DECAY_FIX_RECT, GL_COMPILE); sc_glBlendFunc(GL_ONE, GL_SRC_ALPHA); sc_glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); sc_glBegin(GL_TRIANGLE_STRIP); sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( -1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); sc_glEndList(); #define LIST_DRAW_DECAY_RECT (list_main+3) sc_glNewList(LIST_DRAW_DECAY_RECT, GL_COMPILE); sc_glBlendEquation(GL_FUNC_ADD); sc_glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); sc_glBegin(GL_TRIANGLE_STRIP); sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( -1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); sc_glEndList(); #define LIST_DRAW_TEX_RECT (list_main+4) sc_glNewList(LIST_DRAW_TEX_RECT, GL_COMPILE); sc_glEnable(GL_TEXTURE_2D); sc_glBegin(GL_TRIANGLE_STRIP); sc_glTexCoord2f(0.0f, 0.0f); sc_glVertex2f( 0.0f, 0.0f); sc_glTexCoord2f(1.0f, 0.0f); sc_glVertex2f( 1.0f, 0.0f); sc_glTexCoord2f(0.0f, 1.0f); sc_glVertex2f( 0.0f, 1.0f); sc_glTexCoord2f(1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); sc_glDisable(GL_TEXTURE_2D); sc_glEndList(); while (!scivi->thread_quit_flag) { int cn; int i, j; int force_preset_reload; if (plugin_thread_handle_events(scivi, dyn_data, gui)) break; switch (scivi->plugin_ctrl_message){ case SCIVI_CTRL_RETURN_TO_WINDOW_MODE: scivi->plugin_ctrl_message = SCIVI_CTRL_NONE; scivi_switchto_window(scivi); break; case SCIVI_CTRL_PRESETS_RELOAD: scivi->plugin_ctrl_message = SCIVI_CTRL_NONE; C(opt_reread_presets) = 1; break; case SCIVI_CTRL_PRESETS_PREVIOUS: scivi->plugin_ctrl_message = SCIVI_CTRL_NONE; C(opt_active_preset)--; if (C(opt_active_preset) < 0) C(opt_active_preset) = 0; break; case SCIVI_CTRL_PRESETS_NEXT: scivi->plugin_ctrl_message = SCIVI_CTRL_NONE; C(opt_active_preset)++; break; } #if 0 if (scivi->plugin_toggle_fullscreen){ int cs; SDL_WM_ToggleFullScreen(s); cs = SDL_ShowCursor(SDL_QUERY); SDL_ShowCursor(cs == SDL_ENABLE ? SDL_DISABLE : SDL_ENABLE); scivi->plugin_toggle_fullscreen = 0; } #endif SCIVI_LOCK(); /* * grab PCM data */ if (scivi->plugin_pcm_fdata_count > 0){ /* get the old buffer */ pcm_data = scivi->plugin_pcm_fdata[scivi->plugin_pcm_fdata_buffer]; pcm_data_count = scivi->plugin_pcm_fdata_count; /* prepare new buffer */ scivi->plugin_pcm_fdata_buffer = scivi->plugin_pcm_fdata_buffer ? 0 : 1; memset(scivi->plugin_pcm_fdata[scivi->plugin_pcm_fdata_buffer], 0, sizeof(float)*2*512); scivi->plugin_pcm_fdata_count = 0; } else if ((pcm_data == NULL) || (pcm_data_count == 0)) { SCIVI_UNLOCK(); usleep(1000); continue; } /* * grab FREQ data */ if (scivi->plugin_freq_fdata_count > 0){ /* get the old buffer */ freq_data = scivi->plugin_freq_fdata[scivi->plugin_freq_fdata_buffer]; freq_data_count = scivi->plugin_freq_fdata_count; /* prepare new buffer */ scivi->plugin_freq_fdata_buffer = scivi->plugin_freq_fdata_buffer ? 0 : 1; memset(scivi->plugin_freq_fdata[scivi->plugin_freq_fdata_buffer], 0, sizeof(float)*2*256); scivi->plugin_freq_fdata_count = 0; } else if (freq_data == NULL) { SCIVI_UNLOCK(); usleep(1000); continue; } SCIVI_UNLOCK(); if (freq_data_count > 0){ scivi_freq_analyzer(dyn_data, freq_data, freq_data_count); freq_data_count = 0; } if (fps->fps_control_frame_start(scivi, fps_control, dyn_data, gui)) continue; force_preset_reload = 0; if (C(opt_reread_presets)){ int n_presets_count; PresetInfo *n_presets; dprintf("reloading presets...\n"); SCIVICFG_LOCK(); n_presets_count = scivi_preset_load_from_dirs(scivi->preset_dirs, &n_presets); SCIVICFG_UNLOCK(); dprintf("loaded %d presets\n", n_presets_count); if (n_presets_count > 0){ C(opt_active_preset) = 0; if (presets_count > 0){ char *uuid = presets[preset_active].uuid; if (uuid && (uuid[0] != '\0')){ int i; for (i=0;i= 0) && (C(opt_active_preset) != preset_active)) || force_preset_reload){ int r; preset_active = C(opt_active_preset); if (preset_active >= presets_count) { preset_active = presets_count-1; C(opt_active_preset) = preset_active; } r = scivi_dyn_init_code( dyn_data, &presets[preset_active]); if (r){ eprintf("failed to switch preset\n"); } else { gui_set_presetinfo(gui, &presets[preset_active]); } } dyn_data->data_osc = pcm_data; dyn_data->data_freq = freq_data; /* * Process waveform data * */ /* TODO wf smothing can be optimized */ for (i=0;i<512;i++){ int res = C(osc_resolution); float y1; float y2; float y; float t; int l; int c; c = 0; if (res > 0){ y1 = 0.0f; y2 = 0.0f; for (l=(-res);(l<=res) && ((l+i) < 512);l++) if ((l+i) >= 0){ y1 += pcm_data[0][i+l]; y2 += pcm_data[1][i+l]; c++; } } else { y1 = pcm_data[0][i]; y2 = pcm_data[1][i]; c = 1; } t = C(osc_amplitude) / (c*pcm_data_count); y1 *= t; y2 *= t; waveform[0][i] = y1; waveform[1][i] = y2; } if (!first) scivi_activate_swapbuffers(scivi); scivi_activate_pbuffer(scivi); scivi_query_pointer(scivi, dyn_data); scivi_dyn_frame_process(dyn_data); sc_glLineWidth(C(osc_look_param1)); sc_glPointSize(C(osc_look_param1)); /* * * DRAW PREVIOUS SCREEN * */ sc_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); matstart[0] = C(envR); matstart[1] = C(envG); matstart[2] = C(envB); matstart[3] = 1.0f; /* should be here to restore material opacy */ sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matstart); sc_glMatrixMode(GL_TEXTURE); sc_glPushMatrix(); sc_glTranslatef(0.5f, 0.5f, 0.0f); sc_glScalef(0.5f, 0.5f, 1.0f); /* center of rot */ sc_glTranslatef(C(cx), C(cy), 0.0f); /* rotate */ sc_glRotatef(C(rot)*180/M_PI, 0.0f, 0.0f, 1.0f); /* zoom factor */ sc_glScalef(1.0f/C(zoom), 1.0f/C(zoom), 1.0f); sc_glScalef(1.0f/C(sx), 1.0f/C(sy), 1.0f); sc_glTranslatef(-C(cx)-C(dx), -C(cy)-C(dy), 0.0f); sc_glScalef(1.0f/scivi->aspect, 1.0f, 1.0f); sc_glMatrixMode(GL_PROJECTION); sc_glPushMatrix(); sc_glScalef(1.0f/scivi->aspect, 1.0f, 1.0f); #if 0 /* left for debug reasons */ sc_glBegin(GL_TRIANGLE_STRIP); sc_glTexCoord2f(-1.0f, -1.0f); sc_glVertex2f( -1.0f, -1.0f); sc_glTexCoord2f(1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glTexCoord2f(-1.0f, 1.0f); sc_glVertex2f( -1.0f, 1.0f); sc_glTexCoord2f(1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); #else { int p=0, k=0; for (j=0;j<=mesh_size_y;j++) for (i=0;i<=mesh_size_x;i+=4){ scivi_dyn_pixel_process(dyn_data, mesh_c[p+0], mesh_c[p+4], &mesh_c[p+8], &mesh_c[p+12]); scivi_dyn_pixel_process(dyn_data, mesh_c[p+1], mesh_c[p+5], &mesh_c[p+9], &mesh_c[p+13]); scivi_dyn_pixel_process(dyn_data, mesh_c[p+2], mesh_c[p+6], &mesh_c[p+10], &mesh_c[p+14]); scivi_dyn_pixel_process(dyn_data, mesh_c[p+3], mesh_c[p+7], &mesh_c[p+11], &mesh_c[p+15]); p+=16; } } if (!first) { sc_glEnable(GL_TEXTURE_2D); sc_glBindTexture(GL_TEXTURE_2D, tex_main[0]); } sc_glDisable(GL_BLEND); if (C(opt_wireframe)){ int p = 0, l = (mesh_size_x+4)*4, k; float color[4]; sc_glDisable(GL_TEXTURE_2D); sc_glClear(GL_COLOR_BUFFER_BIT); sc_glBegin(GL_LINES); color[0] = 0.8f; color[1] = 0.8f; color[2] = 0.8f; color[3] = 1.0f; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); i=0; for (j=0;j p; for (k=0;k<3;k++){ /* top */ sc_glVertex2f( mesh_c[p+8+k], mesh_c[p+12+k]); sc_glVertex2f( mesh_c[p+9+k], mesh_c[p+13+k]); /* left */ if (nl){ sc_glVertex2f( mesh_c[p+8+k], mesh_c[p+12+k]); sc_glVertex2f( mesh_c[l+8+k], mesh_c[l+12+k]); } } if (nl){ /* left */ sc_glVertex2f( mesh_c[p+11], mesh_c[p+15]); sc_glVertex2f( mesh_c[l+11], mesh_c[l+15]); } if (i >= (mesh_size_x)){ i=0; } else { /* top */ sc_glVertex2f( mesh_c[p+8+16], mesh_c[p+12+16]); sc_glVertex2f( mesh_c[p+11], mesh_c[p+15]); i+=4; } p+=16; l+=16; } sc_glEnd(); } else { int p = 0, l = (mesh_size_x+4)*4; for (j=0;jfps_control_post_decay_frames_cnt(scivi, fps_control) * dx + 1.0f/1024 ; /* prec. timid loss */ if (da >= 1.0f){ float daf = floorf(da); matdecay[0] = daf/255; matdecay[1] = daf/255; matdecay[2] = daf/255; matdecay[3] = 1.0f; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matdecay); sc_glCallList(LIST_DRAW_DECAY_FIX_RECT); /* TODO: use daf for more precision ??? */ fps->fps_control_decay_point(scivi, fps_control); } } #endif sc_glBlendEquation(GL_FUNC_ADD); matosc[0] = C(oscR); matosc[1] = C(oscG); matosc[2] = C(oscB); matosc[3] = C(oscA); if (C(osc_additive)){ sc_glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA); } else { sc_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matosc); sc_glBindTexture(GL_TEXTURE_2D, 0); /* if visible */ if (dyn_data->oscA > 1.0f/512.0f){ sc_glPushMatrix(); sc_glScalef(1.0f/scivi->aspect, 1.0f, 1.0f); sc_glTranslatef(C(ox), C(oy), 0.0f); sc_glRotatef(-C(osc_angle)*180.0f/M_PI, 0.0f ,0.0f ,1.0f); scivi_waveform_draw(dyn_data, gui, waveform); sc_glPopMatrix(); } sc_glPushMatrix(); sc_glScalef(1.0f/scivi->aspect, 1.0f, 1.0f); scivi_dyn_postframe_process(dyn_data); sc_glPopMatrix(); if (C(osc_additive)){ sc_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); sc_glBlendEquation(GL_FUNC_ADD); } #if 1 if ((dyn_data->obA != 0.0f) && (dyn_data->ob_width > 0.0f)){ float obc[4]; float w = dyn_data->ob_width; obc[0] = dyn_data->obR; obc[1] = dyn_data->obG; obc[2] = dyn_data->obB; obc[3] = dyn_data->obA; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, obc); sc_glBegin(GL_TRIANGLES); /* left */ sc_glVertex2f( -1.0f, 1.0f); sc_glVertex2f( -1.0f+w, 1.0f-w); sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( -1.0f+w, -1.0f+w); sc_glVertex2f( -1.0f+w, 1.0f-w); /* right */ sc_glVertex2f( 1.0f, 1.0f); sc_glVertex2f( 1.0f-w, 1.0f-w); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( 1.0f-w, -1.0f+w); sc_glVertex2f( 1.0f-w, 1.0f-w); /* top */ sc_glVertex2f( -1.0f, 1.0f); sc_glVertex2f( -1.0f+w, 1.0f-w); sc_glVertex2f( 1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glVertex2f( 1.0f-w, 1.0f-w); sc_glVertex2f( -1.0f+w, 1.0f-w); /* bottom */ sc_glVertex2f( -1.0f, -1.0f); sc_glVertex2f( -1.0f+w, -1.0f+w); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glVertex2f( 1.0f-w, -1.0f+w); sc_glVertex2f( -1.0f+w, -1.0f+w); sc_glEnd(); } if ((dyn_data->ibA != 0.0f) && (dyn_data->ib_width > 0.0f)){ float ibc[4]; float e = dyn_data->ib_width; float ly = 1.0f - dyn_data->ob_width; float lx = 1.0f - dyn_data->ob_width; ibc[0] = dyn_data->ibR; ibc[1] = dyn_data->ibG; ibc[2] = dyn_data->ibB; ibc[3] = dyn_data->ibA; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, ibc); sc_glBegin(GL_TRIANGLES); /* left */ sc_glVertex2f( -lx, ly); sc_glVertex2f( -lx+e, ly-e); sc_glVertex2f( -lx, -ly); sc_glVertex2f( -lx, -ly); sc_glVertex2f( -lx+e, -ly+e); sc_glVertex2f( -lx+e, ly-e); /* right */ sc_glVertex2f( lx, ly); sc_glVertex2f( lx-e, ly-e); sc_glVertex2f( lx, -ly); sc_glVertex2f( lx, -ly); sc_glVertex2f( lx-e, -ly+e); sc_glVertex2f( lx-e, ly-e); /* top */ sc_glVertex2f( -lx, ly); sc_glVertex2f( -lx+e, ly-e); sc_glVertex2f( lx, ly); sc_glVertex2f( lx, ly); sc_glVertex2f( lx-e, ly-e); sc_glVertex2f( -lx+e, ly-e); /* bottom */ sc_glVertex2f( -lx, -ly); sc_glVertex2f( -lx+e, -ly+e); sc_glVertex2f( lx, -ly); sc_glVertex2f( lx, -ly); sc_glVertex2f( lx-e, -ly+e); sc_glVertex2f( -lx+e, -ly+e); sc_glEnd(); } #endif if ((dyn_data->ib_width == 0.0f) && (dyn_data->ob_width == 0.0f)){ /* draw border to avoid clamping artefacts */ matdecay[0] = matstart[0]; matdecay[1] = matstart[1]; matdecay[2] = matstart[2]; matdecay[3] = 1.0f; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matdecay); sc_glCallList(LIST_DRAW_LINE_RECT); } /* restore alpha value */ matdecay[0] = matstart[0]; matdecay[1] = matstart[1]; matdecay[2] = matstart[2]; matdecay[3] = 1.0f; sc_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matdecay); sc_glBindTexture(GL_TEXTURE_2D, tex_main[0]); setup_texture_filter(scivi, 1); if (C(tex_wrap)){ sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); } else { sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } sc_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, scivi->pbuf_w, scivi->pbuf_h, 0); sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glPushMatrix(); image_postprocess(scivi, dyn_data, tex_main, list_main); #if 0 if (scivi->bgscaler > 1.0f){ sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); sc_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); sc_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, scivi->texture_bg_x, scivi->texture_bg_y, scivi->texture_bg_width, scivi->texture_bg_height, 0); sc_glScalef(scivi->bgscaler, scivi->bgscaler, 0.0f); sc_glEnable(GL_TEXTURE_2D); sc_glBegin(GL_TRIANGLE_STRIP); sc_glTexCoord2f(0.0f, 0.0f); sc_glVertex2f( -1.0f, -1.0f); sc_glTexCoord2f(1.0f, 0.0f); sc_glVertex2f( 1.0f, -1.0f); sc_glTexCoord2f(0.0f, 1.0f); sc_glVertex2f( -1.0f, 1.0f); sc_glTexCoord2f(1.0f, 1.0f); sc_glVertex2f( 1.0f, 1.0f); sc_glEnd(); sc_glDisable(GL_TEXTURE_2D); } #endif sc_glPopMatrix(); #if 0 sc_glPushMatrix(); sc_glScalef(scivi->dxscaler, scivi->dyscaler, 0.0f); gui_draw(gui); sc_glPopMatrix(); #endif sc_glFlush(); first = 0; fps->fps_control_frame_end(scivi, fps_control, dyn_data, gui); scivi_freq_analyzer_end(dyn_data); } if (dyn_data) scivi_dyn_data_finit(dyn_data); if (presets) scivi_presets_free(presets, presets_count); sc_glDeleteTextures(TEXTURES_ALLOC, tex_main); sc_glDeleteLists(list_main, LISTS_ALLOC); fps->fps_control_finit(scivi, fps_control); SCIVICFG_LOCK(); scivi_plugin_read_config_finit(scivi); SCIVICFG_UNLOCK(); gui_finit(gui); scivi_waveform_finit(); /* X cleanup */ scivi_finit_x(scivi, 0); return NULL; } static void image_postprocess(Scivi *scivi, DynamicsData *dyn_data, GLuint *tex_main, GLuint list_main) { #define DRAW_SQ \ sc_glBegin(GL_TRIANGLE_STRIP); \ sc_glTexCoord2f(0.0f, 0.0f); \ sc_glVertex2f( -1.0f, -1.0f); \ sc_glTexCoord2f(1.0f, 0.0f); \ sc_glVertex2f( 1.0f, -1.0f); \ sc_glTexCoord2f(0.0f, 1.0f); \ sc_glVertex2f( -1.0f, 1.0f); \ sc_glTexCoord2f(1.0f, 1.0f); \ sc_glVertex2f( 1.0f, 1.0f); \ sc_glEnd(); int texture_base = 0; if (C(tex_solarize) && GL_HAS(GL_ARB_imaging)){ sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glPushAttrib(GL_COLOR_BUFFER_BIT); sc_glClearColor(0.5f, 0.5f, 0.5f, 1.0f); sc_glClear(GL_COLOR_BUFFER_BIT); sc_glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); sc_glBlendFunc(GL_ONE, GL_ONE); sc_glBindTexture(GL_TEXTURE_2D, tex_main[0]); sc_glEnable(GL_TEXTURE_2D); DRAW_SQ sc_glDisable(GL_TEXTURE_2D); /* GRAB: 0.5 - Source */ sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); setup_texture_filter(scivi,0); sc_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, scivi->pbuf_w, scivi->pbuf_h, 0); sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glClearColor(0.5f, 0.5f, 0.5f, 1.0f); sc_glClear(GL_COLOR_BUFFER_BIT); sc_glBlendFunc(GL_ONE, GL_ONE); sc_glBlendEquation(GL_FUNC_SUBTRACT); sc_glBindTexture(GL_TEXTURE_2D, tex_main[0]); sc_glEnable(GL_TEXTURE_2D); DRAW_SQ sc_glDisable(GL_TEXTURE_2D); sc_glBlendEquation(GL_FUNC_ADD); sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); sc_glEnable(GL_TEXTURE_2D); DRAW_SQ sc_glDisable(GL_TEXTURE_2D); sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); setup_texture_filter(scivi,0); sc_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, scivi->pbuf_w, scivi->pbuf_h, 0); sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glClearColor(0.5f, 0.5f, 0.5f, 1.0f); sc_glClear(GL_COLOR_BUFFER_BIT); sc_glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); sc_glEnable(GL_TEXTURE_2D); DRAW_SQ sc_glDisable(GL_TEXTURE_2D); texture_base = 1; sc_glBindTexture(GL_TEXTURE_2D, tex_main[1]); setup_texture_filter(scivi, 1); sc_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, scivi->pbuf_w, scivi->pbuf_h, 0); sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glPopAttrib(); } scivi_activate_window(scivi); if (C(tex_invert) && GL_HAS(GL_ARB_imaging)){ sc_glBindTexture(GL_TEXTURE_2D, tex_main[texture_base]); sc_glPushAttrib(GL_COLOR_BUFFER_BIT); sc_glClearColor(1.0f, 1.0f, 1.0f, 1.0f); sc_glClear(GL_COLOR_BUFFER_BIT); sc_glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); sc_glBlendFunc(GL_ONE, GL_SRC_ALPHA); sc_glCallList(LIST_DRAW_TEX_RECT); sc_glBindTexture(GL_TEXTURE_2D, 0); sc_glPopAttrib(); return; } sc_glBindTexture(GL_TEXTURE_2D, tex_main[texture_base]); sc_glCallList(LIST_DRAW_TEX_RECT); #undef DRAW_SQ }