comparison src/audacious/widgets/vis.c @ 2313:3149d4b1a9a9 trunk

[svn] - objective-make autodepend fixes - move all sourcecode into src/ and adjust Makefiles accordingly
author nenolod
date Fri, 12 Jan 2007 11:43:40 -0800
parents
children d88558b0de0a
comparison
equal deleted inserted replaced
2312:e1a5a66fb9cc 2313:3149d4b1a9a9
1 /* BMP - Cross-platform multimedia player
2 * Copyright (C) 2003-2004 BMP development team.
3 *
4 * Based on XMMS:
5 * Copyright (C) 1998-2003 XMMS development team.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include "widgetcore.h"
23
24 #include <glib.h>
25 #include <gdk/gdk.h>
26 #include <string.h>
27
28 #include "main.h"
29 #include "skin.h"
30 #include "widget.h"
31
32 static const gfloat vis_afalloff_speeds[] = { 0.34, 0.5, 1.0, 1.3, 1.6 };
33 static const gfloat vis_pfalloff_speeds[] = { 1.2, 1.3, 1.4, 1.5, 1.6 };
34 static const gint vis_redraw_delays[] = { 1, 2, 4, 8 };
35 static const guint8 vis_scope_colors[] =
36 { 21, 21, 20, 20, 19, 19, 18, 19, 19, 20, 20, 21, 21 };
37 //static guint8 vs_data_ext[76 * 16 * 4];
38 static guchar voiceprint_data[76*16];
39 //static guchar voiceprint_data_normal[76*16];
40 //static guchar voiceprint_data_rgb[76*16*4];
41
42 void
43 vis_timeout_func(Vis * vis, guchar * data)
44 {
45 static GTimer *timer = NULL;
46 gulong micros = 9999999;
47 gboolean falloff = FALSE;
48 gint i, n;
49
50 if (!timer) {
51 timer = g_timer_new();
52 g_timer_start(timer);
53 }
54 else {
55 g_timer_elapsed(timer, &micros);
56 if (micros > 14000)
57 g_timer_reset(timer);
58 }
59 if (cfg.vis_type == VIS_ANALYZER) {
60 if (micros > 14000)
61 falloff = TRUE;
62 if (data || falloff) {
63 for (i = 0; i < 75; i++) {
64 if (data && data[i] > vis->vs_data[i]) {
65 vis->vs_data[i] = data[i];
66 if (vis->vs_data[i] > vis->vs_peak[i]) {
67 vis->vs_peak[i] = vis->vs_data[i];
68 vis->vs_peak_speed[i] = 0.01;
69
70 }
71 else if (vis->vs_peak[i] > 0.0) {
72 vis->vs_peak[i] -= vis->vs_peak_speed[i];
73 vis->vs_peak_speed[i] *=
74 vis_pfalloff_speeds[cfg.peaks_falloff];
75 if (vis->vs_peak[i] < vis->vs_data[i])
76 vis->vs_peak[i] = vis->vs_data[i];
77 if (vis->vs_peak[i] < 0.0)
78 vis->vs_peak[i] = 0.0;
79 }
80 }
81 else if (falloff) {
82 if (vis->vs_data[i] > 0.0) {
83 vis->vs_data[i] -=
84 vis_afalloff_speeds[cfg.analyzer_falloff];
85 if (vis->vs_data[i] < 0.0)
86 vis->vs_data[i] = 0.0;
87 }
88 if (vis->vs_peak[i] > 0.0) {
89 vis->vs_peak[i] -= vis->vs_peak_speed[i];
90 vis->vs_peak_speed[i] *=
91 vis_pfalloff_speeds[cfg.peaks_falloff];
92 if (vis->vs_peak[i] < vis->vs_data[i])
93 vis->vs_peak[i] = vis->vs_data[i];
94 if (vis->vs_peak[i] < 0.0)
95 vis->vs_peak[i] = 0.0;
96 }
97 }
98 }
99 }
100 }
101 else if (cfg.vis_type == VIS_VOICEPRINT && data){
102 for(i = 0; i < 16; i++)
103 {
104 vis->vs_data[i] = data[15 - i];
105 }
106 }
107 else if (data) {
108 for (i = 0; i < 75; i++)
109 vis->vs_data[i] = data[i];
110 }
111
112 if (micros > 14000) {
113 if (!vis->vs_refresh_delay) {
114 vis_draw((Widget *) vis);
115 vis->vs_refresh_delay = vis_redraw_delays[cfg.vis_refresh];
116
117 }
118 vis->vs_refresh_delay--;
119 }
120 }
121 void
122 vis_draw(Widget * w)
123 {
124 Vis *vis = (Vis *) w;
125 gint x, y, n, h = 0, h2;
126 guchar vis_color[24][3];
127 guchar rgb_data[76 * 16 * 3 * 2 * 2], *ptr, c;
128 guint32 colors[24];
129 GdkRgbCmap *cmap;
130
131 if (!vis->vs_widget.visible)
132 return;
133
134 skin_get_viscolor(bmp_active_skin, vis_color);
135 for (y = 0; y < 24; y++) {
136 colors[y] =
137 vis_color[y][0] << 16 | vis_color[y][1] << 8 | vis_color[y][2];
138 }
139 cmap = gdk_rgb_cmap_new(colors, 24);
140
141 if (!vis->vs_doublesize) {
142 if(cfg.vis_type == VIS_VOICEPRINT && cfg.voiceprint_mode != VOICEPRINT_NORMAL){
143 memset(rgb_data, 0, 76 * 16 * 3);
144 }
145 else{
146 memset(rgb_data, 0, 76 * 16);
147 for (y = 1; y < 16; y += 2) {
148 ptr = rgb_data + (y * 76);
149 for (x = 0; x < 76; x += 2, ptr += 2)
150 *ptr = 1;
151 }
152 }
153 }
154 else{
155 if(cfg.vis_type == VIS_VOICEPRINT && cfg.voiceprint_mode != VOICEPRINT_NORMAL){
156 memset(rgb_data, 0, 3 * 4 * 16 * 76);
157 }
158 else{
159 memset(rgb_data, 0, 152 * 32);
160 for (y = 1; y < 16; y += 2) {
161 ptr = rgb_data + (y * 304);
162 for (x = 0; x < 76; x += 2, ptr += 4) {
163 *ptr = 1;
164 *(ptr + 1) = 1;
165 *(ptr + 152) = 1;
166 *(ptr + 153) = 1;
167 }
168 }
169 }
170 }
171 if (cfg.vis_type == VIS_ANALYZER) {
172 for (x = 0; x < 75; x++) {
173 if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
174 h = vis->vs_data[x >> 2];
175 else if (cfg.analyzer_type == ANALYZER_LINES)
176 h = vis->vs_data[x];
177 if (h && (cfg.analyzer_type == ANALYZER_LINES ||
178 (x % 4) != 3)) {
179 if (!vis->vs_doublesize) {
180 ptr = rgb_data + ((16 - h) * 76) + x;
181 switch (cfg.analyzer_mode) {
182 case ANALYZER_NORMAL:
183 for (y = 0; y < h; y++, ptr += 76)
184 *ptr = 18 - h + y;
185 break;
186 case ANALYZER_FIRE:
187 for (y = 0; y < h; y++, ptr += 76)
188 *ptr = y + 2;
189 break;
190 case ANALYZER_VLINES:
191 for (y = 0; y < h; y++, ptr += 76)
192 *ptr = 18 - h;
193 break;
194 }
195 }
196 else{
197 ptr = rgb_data + ((16 - h) * 304) + (x << 1);
198 switch (cfg.analyzer_mode) {
199 case ANALYZER_NORMAL:
200 for (y = 0; y < h; y++, ptr += 304) {
201 *ptr = 18 - h + y;
202 *(ptr + 1) = 18 - h + y;
203 *(ptr + 152) = 18 - h + y;
204 *(ptr + 153) = 18 - h + y;
205 }
206 break;
207 case ANALYZER_FIRE:
208 for (y = 0; y < h; y++, ptr += 304) {
209 *ptr = y + 2;
210 *(ptr + 1) = y + 2;
211 *(ptr + 152) = y + 2;
212 *(ptr + 153) = y + 2;
213 }
214 break;
215 case ANALYZER_VLINES:
216 for (y = 0; y < h; y++, ptr += 304) {
217 *ptr = 18 - h;
218 *(ptr + 1) = 18 - h;
219 *(ptr + 152) = 18 - h;
220 *(ptr + 153) = 18 - h;
221 }
222
223 break;
224 }
225 }
226 }
227 }
228 if (cfg.analyzer_peaks) {
229 for (x = 0; x < 75; x++) {
230 if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
231 h = vis->vs_peak[x >> 2];
232 else if (cfg.analyzer_type == ANALYZER_LINES)
233 h = vis->vs_peak[x];
234 if (h && (cfg.analyzer_type == ANALYZER_LINES || (x % 4) != 3)){
235
236 if (!vis->vs_doublesize) {
237 rgb_data[(16 - h) * 76 + x] = 23;
238 }
239 else{
240 ptr = rgb_data + (16 - h) * 304 + (x << 1);
241 *ptr = 23;
242 *(ptr + 1) = 23;
243 *(ptr + 152) = 23;
244 *(ptr + 153) = 23;
245 }
246 }
247 }
248 }
249 }
250 else if (cfg.vis_type == VIS_VOICEPRINT) {
251 if(!playback_get_paused() && playback_get_playing()){/*Don't scroll when it's paused or stopped*/
252 for (y = 0; y < 16; y ++)
253 for (x = 75; x > 0; x--)
254 voiceprint_data[x + y * 76] = voiceprint_data[x-1+y*76];
255 for(y=0;y<16;y++)
256 voiceprint_data[y * 76] = vis->vs_data[y];
257 }
258 if(playback_get_playing()){ /*Only draw the data if we're playing*/
259 for (y = 0; y < 16; y ++){
260 for (x = 0; x < 76; x++){
261 guint8 d = voiceprint_data[x + y*76];
262 if(cfg.voiceprint_mode == VOICEPRINT_NORMAL){
263 d = d > 64 ? 17 : d >> 3 ;
264 if(!vis->vs_doublesize){
265 rgb_data[x + y * 76] = d;
266 }
267 else{
268 ptr = rgb_data + (x << 1) + y * 304;
269 *ptr = d;
270 *(ptr + 1) = d;
271 *(ptr + 152) = d;
272 *(ptr + 153) = d;
273 }
274 }
275 else{
276 guint8 c[3]; // R, G, B array
277 if(cfg.voiceprint_mode == VOICEPRINT_FIRE){
278 c[0] = d < 64 ? (d * 2) : 255; //R
279 c[1] = d < 64 ? 0 : (d < 128 ? (d-64) * 2 : 255); //G
280 c[2] = d < 128 ? 0 : (d-128) * 2; //B
281 }
282 else if(cfg.voiceprint_mode == VOICEPRINT_ICE){
283 //c[0] = d < 192 ? 0 : (d-192) * 4; //R
284 //c[1] = d < 192 ? 0 : (d-192) * 4; //G
285 c[0] = d; //R
286 c[1] = d < 128 ? d * 2 : 255; //G
287 c[2] = d < 64 ? d * 4 : 255; //B
288 }
289 if(!vis->vs_doublesize){
290 for(n=0;n<3;n++)
291 rgb_data[x * 3 + y * 76*3+n] = c[n];
292 }
293 else{
294 ptr = rgb_data + x * 3 * 2 + y * 2 * 76 * 3 * 2;
295 for(n=0;n<3;n++)
296 {
297 *(ptr + n) = c[n];
298 *(ptr + n + 3) = c[n];
299 *(ptr + n + 76 * 2 * 3) = c[n];
300 *(ptr + n + 3 + 76 * 2 * 3) = c[n];
301 }
302 }
303 }
304 }
305 }
306 }
307 }
308 if (cfg.vis_type == VIS_SCOPE) {
309 for (x = 0; x < 75; x++) {
310 switch (cfg.scope_mode) {
311 case SCOPE_DOT:
312 h = vis->vs_data[x];
313 if (!vis->vs_doublesize) {
314 ptr = rgb_data + ((14 - h) * 76) + x;
315 *ptr = vis_scope_colors[h + 1];
316 }else{
317 ptr = rgb_data + ((14 - h) * 304) + (x << 1);
318 *ptr = vis_scope_colors[h + 1];
319 *(ptr + 1) = vis_scope_colors[h + 1];
320 *(ptr + 152) = vis_scope_colors[h + 1];
321 *(ptr + 153) = vis_scope_colors[h + 1];
322 }
323 break;
324 case SCOPE_LINE:
325 if (x != 74) {
326 h = 14 - vis->vs_data[x];
327 h2 = 14 - vis->vs_data[x + 1];
328 if (h > h2) {
329 y = h;
330 h = h2;
331 h2 = y;
332 }
333 if (!vis->vs_doublesize) {
334 ptr = rgb_data + (h * 76) + x;
335 for (y = h; y <= h2; y++, ptr += 76)
336 *ptr = vis_scope_colors[y - 2];
337 }
338 else{
339 ptr = rgb_data + (h * 304) + (x << 1);
340 for (y = h; y <= h2; y++, ptr += 304) {
341 *ptr = vis_scope_colors[y - 2];
342 *(ptr + 1) = vis_scope_colors[y - 2];
343 *(ptr + 152) = vis_scope_colors[y - 2];
344 *(ptr + 153) = vis_scope_colors[y - 2];
345 }
346 }
347 }
348 else {
349 h = 14 - vis->vs_data[x];
350 if (!vis->vs_doublesize) {
351 ptr = rgb_data + (h * 76) + x;
352 *ptr = vis_scope_colors[h + 1];
353 }else{
354 ptr = rgb_data + (h * 304) + (x << 1);
355 *ptr = vis_scope_colors[h + 1];
356 *(ptr + 1) = vis_scope_colors[h + 1];
357 *(ptr + 152) = vis_scope_colors[h + 1];
358 *(ptr + 153) = vis_scope_colors[h + 1];
359 }
360 }
361 break;
362 case SCOPE_SOLID:
363 h = 14 - vis->vs_data[x];
364 h2 = 8;
365 c = vis_scope_colors[(gint) vis->vs_data[x]];
366 if (h > h2) {
367 y = h;
368 h = h2;
369 h2 = y;
370 }
371 if (!vis->vs_doublesize) {
372 ptr = rgb_data + (h * 76) + x;
373 for (y = h; y <= h2; y++, ptr += 76)
374 *ptr = c;
375 }else{
376 ptr = rgb_data + (h * 304) + (x << 1);
377 for (y = h; y <= h2; y++, ptr += 304) {
378 *ptr = c;
379 *(ptr + 1) = c;
380 *(ptr + 152) = c;
381 *(ptr + 153) = c;
382 }
383 }
384 break;
385 }
386 }
387 }
388
389
390
391 if (!vis->vs_doublesize) {
392 GDK_THREADS_ENTER();
393 if (cfg.vis_type == VIS_VOICEPRINT && cfg.voiceprint_mode != VOICEPRINT_NORMAL){
394 gdk_draw_rgb_image(vis->vs_window, vis->vs_widget.gc,
395 vis->vs_widget.x, vis->vs_widget.y,
396 vis->vs_widget.width, vis->vs_widget.height,
397 GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
398 76 * 3);
399 }
400 else{
401 gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
402 vis->vs_widget.x, vis->vs_widget.y,
403 vis->vs_widget.width, vis->vs_widget.height,
404 GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
405 76, cmap);
406 }
407 GDK_THREADS_LEAVE();
408 }
409 else {
410 GDK_THREADS_ENTER();
411 if (cfg.vis_type == VIS_VOICEPRINT && cfg.voiceprint_mode != VOICEPRINT_NORMAL){
412 gdk_draw_rgb_image(vis->vs_window, vis->vs_widget.gc,
413 vis->vs_widget.x << 1,
414 vis->vs_widget.y << 1,
415 vis->vs_widget.width << 1,
416 vis->vs_widget.height << 1,
417 GDK_RGB_DITHER_NONE, (guchar *) rgb_data,
418 76 * 2 * 3);
419 }
420 else{
421 gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
422 vis->vs_widget.x << 1,
423 vis->vs_widget.y << 1,
424 vis->vs_widget.width << 1,
425 vis->vs_widget.height << 1,
426 GDK_RGB_DITHER_NONE, (guchar *) rgb_data,
427 76 * 2 , cmap);
428 }
429 GDK_THREADS_LEAVE();
430 }
431 gdk_rgb_cmap_free(cmap);
432 }
433
434
435
436 void
437 vis_clear_data(Vis * vis)
438 {
439 gint i;
440
441 if (!vis)
442 return;
443 memset(voiceprint_data, 0, 16*76);
444 for (i = 0; i < 75; i++) {
445 vis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0;
446 vis->vs_peak[i] = 0;
447 }
448 }
449
450 void
451 vis_set_doublesize(Vis * vis, gboolean doublesize)
452 {
453 vis->vs_doublesize = doublesize;
454 }
455
456 void
457 vis_clear(Vis * vis)
458 {
459 if (!vis->vs_doublesize)
460 gdk_window_clear_area(vis->vs_window, vis->vs_widget.x,
461 vis->vs_widget.y, vis->vs_widget.width,
462 vis->vs_widget.height);
463 else
464 gdk_window_clear_area(vis->vs_window, vis->vs_widget.x << 1,
465 vis->vs_widget.y << 1,
466 vis->vs_widget.width << 1,
467 vis->vs_widget.height << 1);
468 }
469
470 void
471 vis_set_window(Vis * vis, GdkWindow * window)
472 {
473 vis->vs_window = window;
474 }
475
476 void vis_draw_pixel(Vis * vis, guchar* texture, gint x, gint y, guint8 colour){
477 if(vis->vs_doublesize){
478 texture[y * 76 + x] = colour;
479 texture[y * 76 + x + 1] = colour;
480 texture[y * 76 * 4 + x] = colour;
481 texture[y * 76 * 4 + x + 1] = colour;
482 }
483 else{
484 texture[y * 76 + x] = colour;
485 }
486 }
487
488
489 Vis *
490 create_vis(GList ** wlist,
491 GdkPixmap * parent,
492 GdkWindow * window,
493 GdkGC * gc,
494 gint x, gint y,
495 gint width,
496 gboolean doublesize)
497 {
498 Vis *vis;
499
500 vis = g_new0(Vis, 1);
501 memset(voiceprint_data, 0, 16*76);
502 widget_init(&vis->vs_widget, parent, gc, x, y, width, 16, 1);
503
504 vis->vs_doublesize = doublesize;
505
506 widget_list_add(wlist, WIDGET(vis));
507
508 return vis;
509 }