1 /*****************************************************************************
2 * audiobargraph_v.c : audiobargraph video plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2003-2006 VLC authors and VideoLAN
6 * Authors: Clement CHESNIN <clement.chesnin@gmail.com>
7 * Philippe COENT <philippe.coent@tdf.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_filter.h>
38 #include <vlc_image.h>
44 /*****************************************************************************
46 *****************************************************************************/
48 #define I_VALUES_TEXT N_("Value of the audio channels levels")
49 #define I_VALUES_LONGTEXT N_("Value of the audio level of each channels between 0 and 1. " \
50 "Each level should be separated with ':'.")
51 #define POSX_TEXT N_("X coordinate")
52 #define POSX_LONGTEXT N_("X coordinate of the bargraph." )
53 #define POSY_TEXT N_("Y coordinate")
54 #define POSY_LONGTEXT N_("Y coordinate of the bargraph." )
55 #define TRANS_TEXT N_("Transparency of the bargraph")
56 #define TRANS_LONGTEXT N_("Bargraph transparency value " \
57 "(from 0 for full transparency to 255 for full opacity)." )
58 #define POS_TEXT N_("Bargraph position")
59 #define POS_LONGTEXT N_( \
60 "Enforce the bargraph position on the video " \
61 "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
62 "also use combinations of these values, eg 6 = top-right).")
63 #define ALARM_TEXT N_("Alarm")
64 #define ALARM_LONGTEXT N_("Signals a silence and displays and alert " \
65 "(0=no alarm, 1=alarm).")
66 #define BARWIDTH_TEXT N_("Bar width in pixel (default : 10)")
67 #define BARWIDTH_LONGTEXT N_("Width in pixel of each bar in the BarGraph to be displayed " \
70 #define CFG_PREFIX "audiobargraph_v-"
72 static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
73 static const char *const ppsz_pos_descriptions[] =
74 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
75 N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
77 static int OpenSub ( vlc_object_t * );
78 static int OpenVideo( vlc_object_t * );
79 static void Close ( vlc_object_t * );
83 set_category( CAT_VIDEO )
84 set_subcategory( SUBCAT_VIDEO_SUBPIC )
86 set_capability( "sub source", 0 )
87 set_callbacks( OpenSub, Close )
88 set_description( N_("Audio Bar Graph Video sub source") )
89 set_shortname( N_("Audio Bar Graph Video") )
90 add_shortcut( "audiobargraph_v" )
92 add_string( CFG_PREFIX "i_values", NULL, I_VALUES_TEXT, I_VALUES_LONGTEXT, false )
93 add_integer( CFG_PREFIX "x", 0, POSX_TEXT, POSX_LONGTEXT, true )
94 add_integer( CFG_PREFIX "y", 0, POSY_TEXT, POSY_LONGTEXT, true )
95 add_integer_with_range( CFG_PREFIX "transparency", 255, 0, 255,
96 TRANS_TEXT, TRANS_LONGTEXT, false )
97 add_integer( CFG_PREFIX "position", -1, POS_TEXT, POS_LONGTEXT, false )
98 change_integer_list( pi_pos_values, ppsz_pos_descriptions )
99 add_integer( CFG_PREFIX "alarm", 0, ALARM_TEXT, ALARM_LONGTEXT, true )
100 add_integer( CFG_PREFIX "barWidth", 10, BARWIDTH_TEXT, BARWIDTH_LONGTEXT, true )
102 /* video output filter submodule */
104 set_capability( "video filter2", 0 )
105 set_callbacks( OpenVideo, Close )
106 set_description( N_("Audio Bar Graph Video sub source") )
107 add_shortcut( "audiobargraph_v" )
111 /*****************************************************************************
113 *****************************************************************************/
115 /*****************************************************************************
116 * Structure to hold the Bar Graph properties
117 ****************************************************************************/
120 int i_alpha; /* -1 means use default alpha */
132 * Private data holder
140 BarGraph_t p_BarGraph;
147 /* On the fly control variable */
151 static const char *const ppsz_filter_options[] = {
152 "i_values", "x", "y", "transparency", "position", "alarm", "barWidth", NULL
155 static const char *const ppsz_filter_callbacks[] = {
156 "audiobargraph_v-i_values",
159 "audiobargraph_v-transparency",
160 "audiobargraph_v-position",
161 "audiobargraph_v-alarm",
162 "audiobargraph_v-barWidth",
166 static int OpenCommon( vlc_object_t *, bool b_sub );
168 static subpicture_t *FilterSub( filter_t *, mtime_t );
169 static picture_t *FilterVideo( filter_t *, picture_t * );
171 static int BarGraphCallback( vlc_object_t *, char const *,
172 vlc_value_t, vlc_value_t, void * );
174 static void LoadBarGraph( vlc_object_t *, BarGraph_t *);
175 void parse_i_values( BarGraph_t *p_BarGraph, char *i_values);
176 static float iec_scale(float dB);
179 * Open the sub source
181 static int OpenSub( vlc_object_t *p_this )
183 return OpenCommon( p_this, true );
187 * Open the video filter
189 static int OpenVideo( vlc_object_t *p_this )
191 return OpenCommon( p_this, false );
195 * Common open function
197 static int OpenCommon( vlc_object_t *p_this, bool b_sub )
199 filter_t *p_filter = (filter_t *)p_this;
201 BarGraph_t *p_BarGraph;
202 char* i_values = NULL;
205 if( !b_sub && !es_format_IsSimilar( &p_filter->fmt_in, &p_filter->fmt_out ) )
207 msg_Err( p_filter, "Input and output format does not match" );
213 p_filter->p_sys = p_sys = malloc( sizeof( *p_sys ) );
216 p_BarGraph = &(p_sys->p_BarGraph);
217 p_BarGraph->p_pic = NULL;
220 p_sys->p_blend = NULL;
224 p_sys->p_blend = filter_NewBlend( VLC_OBJECT(p_filter),
225 &p_filter->fmt_in.video );
226 if( !p_sys->p_blend )
228 //free( p_BarGraph );
235 config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
238 /* create and initialize variables */
239 p_sys->i_pos = var_CreateGetIntegerCommand( p_filter, "audiobargraph_v-position" );
240 p_sys->i_pos_x = var_CreateGetIntegerCommand( p_filter, "audiobargraph_v-x" );
241 p_sys->i_pos_y = var_CreateGetIntegerCommand( p_filter, "audiobargraph_v-y" );
242 p_BarGraph->i_alpha = var_CreateGetIntegerCommand( p_filter,
243 "audiobargraph_v-transparency" );
244 p_BarGraph->i_alpha = VLC_CLIP( p_BarGraph->i_alpha, 0, 255 );
245 i_values = var_CreateGetStringCommand( p_filter, "audiobargraph_v-i_values" );
246 //p_BarGraph->nbChannels = 0;
247 //p_BarGraph->i_values = NULL;
248 parse_i_values(p_BarGraph, i_values);
249 p_BarGraph->alarm = var_CreateGetIntegerCommand( p_filter, "audiobargraph_v-alarm" );
250 p_BarGraph->barWidth = var_CreateGetIntegerCommand( p_filter, "audiobargraph_v-barWidth" );
251 p_BarGraph->scale = 400;
253 /* Ignore aligment if a position is given for video filter */
254 if( !b_sub && p_sys->i_pos_x >= 0 && p_sys->i_pos_y >= 0 )
257 vlc_mutex_init( &p_sys->lock );
258 LoadBarGraph( p_this, p_BarGraph );
259 p_sys->b_spu_update = true;
261 for( int i = 0; ppsz_filter_callbacks[i]; i++ )
262 var_AddCallback( p_filter, ppsz_filter_callbacks[i],
263 BarGraphCallback, p_sys );
268 p_filter->pf_sub_source = FilterSub;
272 p_filter->pf_video_filter = FilterVideo;
280 * Common close function
282 static void Close( vlc_object_t *p_this )
284 filter_t *p_filter = (filter_t *)p_this;
285 filter_sys_t *p_sys = p_filter->p_sys;
286 BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph);
288 for( int i = 0; ppsz_filter_callbacks[i]; i++ )
289 var_DelCallback( p_filter, ppsz_filter_callbacks[i],
290 BarGraphCallback, p_sys );
293 filter_DeleteBlend( p_sys->p_blend );
295 vlc_mutex_destroy( &p_sys->lock );
297 if( p_BarGraph->p_pic )
299 picture_Release( p_BarGraph->p_pic );
300 p_BarGraph->p_pic = NULL;
302 free( p_BarGraph->i_values );
310 static subpicture_t *FilterSub( filter_t *p_filter, mtime_t date )
312 filter_sys_t *p_sys = p_filter->p_sys;
313 BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph);
316 subpicture_region_t *p_region;
320 vlc_mutex_lock( &p_sys->lock );
321 /* Basic test: b_spu_update occurs on a dynamic change */
322 if( !p_sys->b_spu_update )
324 vlc_mutex_unlock( &p_sys->lock );
328 p_pic = p_BarGraph->p_pic;
330 /* Allocate the subpicture internal data. */
331 p_spu = filter_NewSubpicture( p_filter );
335 p_spu->b_absolute = p_sys->b_absolute;
336 p_spu->i_start = date;
338 p_spu->b_ephemer = true;
340 /* Send an empty subpicture to clear the display when needed */
341 if( !p_pic || !p_BarGraph->i_alpha )
344 /* Create new SPU region */
345 memset( &fmt, 0, sizeof(video_format_t) );
346 fmt.i_chroma = VLC_CODEC_YUVA;
347 fmt.i_sar_num = fmt.i_sar_den = 1;
348 fmt.i_width = fmt.i_visible_width = p_pic->p[Y_PLANE].i_visible_pitch;
349 fmt.i_height = fmt.i_visible_height = p_pic->p[Y_PLANE].i_visible_lines;
350 fmt.i_x_offset = fmt.i_y_offset = 0;
351 p_region = subpicture_region_New( &fmt );
354 msg_Err( p_filter, "cannot allocate SPU region" );
355 p_filter->pf_sub_buffer_del( p_filter, p_spu );
361 picture_Copy( p_region->p_picture, p_pic );
363 /* where to locate the bar graph: */
364 if( p_sys->i_pos < 0 )
365 { /* set to an absolute xy */
366 p_region->i_align = SUBPICTURE_ALIGN_RIGHT | SUBPICTURE_ALIGN_TOP;
367 p_spu->b_absolute = true;
370 { /* set to one of the 9 relative locations */
371 p_region->i_align = p_sys->i_pos;
372 p_spu->b_absolute = false;
375 p_region->i_x = p_sys->i_pos_x;
376 p_region->i_y = p_sys->i_pos_y;
378 p_spu->p_region = p_region;
380 p_spu->i_alpha = p_BarGraph->i_alpha ;
383 vlc_mutex_unlock( &p_sys->lock );
391 static picture_t *FilterVideo( filter_t *p_filter, picture_t *p_src )
393 filter_sys_t *p_sys = p_filter->p_sys;
394 BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph);
396 picture_t *p_dst = filter_NewPicture( p_filter );
400 picture_Copy( p_dst, p_src );
403 vlc_mutex_lock( &p_sys->lock );
406 const picture_t *p_pic = p_BarGraph->p_pic;
409 const video_format_t *p_fmt = &p_pic->format;
410 const int i_dst_w = p_filter->fmt_out.video.i_visible_width;
411 const int i_dst_h = p_filter->fmt_out.video.i_visible_height;
415 if( p_sys->i_pos & SUBPICTURE_ALIGN_BOTTOM )
417 p_sys->i_pos_y = i_dst_h - p_fmt->i_visible_height;
419 else if ( !(p_sys->i_pos & SUBPICTURE_ALIGN_TOP) )
421 p_sys->i_pos_y = ( i_dst_h - p_fmt->i_visible_height ) / 2;
428 if( p_sys->i_pos & SUBPICTURE_ALIGN_RIGHT )
430 p_sys->i_pos_x = i_dst_w - p_fmt->i_visible_width;
432 else if ( !(p_sys->i_pos & SUBPICTURE_ALIGN_LEFT) )
434 p_sys->i_pos_x = ( i_dst_w - p_fmt->i_visible_width ) / 2;
443 const int i_alpha = p_BarGraph->i_alpha;
444 if( filter_ConfigureBlend( p_sys->p_blend, i_dst_w, i_dst_h, p_fmt ) ||
445 filter_Blend( p_sys->p_blend, p_dst, p_sys->i_pos_x, p_sys->i_pos_y,
448 msg_Err( p_filter, "failed to blend a picture" );
451 vlc_mutex_unlock( &p_sys->lock );
454 picture_Release( p_src );
458 /*****************************************************************************
459 * Callback to update params on the fly
460 *****************************************************************************/
461 static int BarGraphCallback( vlc_object_t *p_this, char const *psz_var,
462 vlc_value_t oldval, vlc_value_t newval, void *p_data )
465 filter_sys_t *p_sys = (filter_sys_t *)p_data;
466 BarGraph_t *p_BarGraph = &(p_sys->p_BarGraph);
469 vlc_mutex_lock( &p_sys->lock );
470 if ( !strcmp( psz_var, "audiobargraph_v-x" ) )
472 p_sys->i_pos_x = newval.i_int;
474 else if ( !strcmp( psz_var, "audiobargraph_v-y" ) )
476 p_sys->i_pos_y = newval.i_int;
478 else if ( !strcmp( psz_var, "audiobargraph_v-position" ) )
480 p_sys->i_pos = newval.i_int;
482 else if ( !strcmp( psz_var, "audiobargraph_v-transparency" ) )
484 p_BarGraph->i_alpha = VLC_CLIP( newval.i_int, 0, 255 );
486 else if ( !strcmp( psz_var, "audiobargraph_v-i_values" ) )
488 if( p_BarGraph->p_pic )
490 picture_Release( p_BarGraph->p_pic );
491 p_BarGraph->p_pic = NULL;
493 char *psz_i_values = strdup( newval.psz_string );
494 free(p_BarGraph->i_values);
495 //p_BarGraph->i_values = NULL;
496 //p_BarGraph->nbChannels = 0;
497 // in case many answer are received at the same time, only keep one
498 res = strchr(psz_i_values, '@');
501 parse_i_values( p_BarGraph, psz_i_values);
502 free( psz_i_values );
503 LoadBarGraph(p_this,p_BarGraph);
505 else if ( !strcmp( psz_var, "audiobargraph_v-alarm" ) )
507 if( p_BarGraph->p_pic )
509 picture_Release( p_BarGraph->p_pic );
510 p_BarGraph->p_pic = NULL;
512 p_BarGraph->alarm = newval.i_int;
513 LoadBarGraph(p_this,p_BarGraph);
515 else if ( !strcmp( psz_var, "audiobargraph_v-barWidth" ) )
517 if( p_BarGraph->p_pic )
519 picture_Release( p_BarGraph->p_pic );
520 p_BarGraph->p_pic = NULL;
522 p_BarGraph->barWidth = newval.i_int;
523 LoadBarGraph(p_this,p_BarGraph);
525 p_sys->b_spu_update = true;
526 vlc_mutex_unlock( &p_sys->lock );
531 /*****************************************************************************
532 * LoadImage: creates and returns the bar graph image
533 *****************************************************************************/
534 static picture_t *LoadImage( vlc_object_t *p_this, int nbChannels, int* i_values, int scale, int alarm, int barWidth)
541 int minus8, minus10, minus18, minus20, minus30, minus40, minus50, minus60;
543 if (nbChannels == 0) {
546 i_width = 2 * nbChannels * barWidth + 10;
548 minus8 = iec_scale(-8)*scale + 20;
549 minus10 = iec_scale(-10)*scale + 20;
550 minus18 = iec_scale(-18)*scale + 20;
551 minus20 = iec_scale(-20)*scale + 20;
552 minus30 = iec_scale(-30)*scale + 20;
553 minus40 = iec_scale(-40)*scale + 20;
554 minus50 = iec_scale(-50)*scale + 20;
555 minus60 = iec_scale(-60)*scale + 20;
557 p_pic = picture_New(VLC_FOURCC('Y','U','V','A'), i_width+20, scale+30, 1, 1);
560 #define DrawLine(a,b,Y,U,V,A) \
561 for (i=a; i<b; i++) {\
562 *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = Y;\
563 *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = U;\
564 *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = V;\
565 *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = A; \
567 #define DrawLineBlack(a,b) DrawLine(a,b,0,128,128,0xFF)
568 #define DrawLineWhite(a,b) DrawLine(a,b,255,128,128,0xFF)
570 // blacken the whole picture
571 for( i = 0 ; i < p_pic->i_planes ; i++ )
573 memset( p_pic->p[i].p_pixels, 0x00,
574 p_pic->p[i].i_visible_lines * p_pic->p[i].i_pitch );
579 for ( i_line = 20; i_line < scale+20; i_line++ ) {
581 DrawLineBlack(20,22);
582 DrawLineWhite(22,24);
585 if (i_line == minus10 - 2) {
587 DrawLineBlack(14,15);
589 DrawLineBlack(16,19);
591 if (i_line == minus10 - 1) {
593 DrawLineBlack(14,15);
595 DrawLineBlack(16,17);
596 DrawLineBlack(18,19);
598 DrawLineWhite(24,27); //White
600 if (i_line == minus10) {
602 DrawLineBlack(14,15);
604 DrawLineBlack(16,17);
605 DrawLineBlack(18,19);
607 DrawLineBlack(24,27);
609 if (i_line == minus10 + 1) {
611 DrawLineBlack(14,15);
613 DrawLineBlack(16,17);
614 DrawLineBlack(18,19);
616 DrawLineBlack(24,27);
618 if (i_line == minus10 + 2) {
620 DrawLineBlack(14,15);
622 DrawLineBlack(16,19);
626 if (i_line == minus20 - 2) {
628 DrawLineBlack(12,15);
630 DrawLineBlack(16,19);
632 if (i_line == minus20 - 1) {
634 DrawLineBlack(12,13);
636 DrawLineBlack(16,17);
637 DrawLineBlack(18,19);
639 DrawLineWhite(24,27); //White
641 if (i_line == minus20) {
643 DrawLineBlack(12,15);
645 DrawLineBlack(16,17);
646 DrawLineBlack(18,19);
648 DrawLineBlack(24,27);
650 if (i_line == minus20 + 1) {
652 DrawLineBlack(14,15);
654 DrawLineBlack(16,17);
655 DrawLineBlack(18,19);
657 DrawLineBlack(24,27);
659 if (i_line == minus20 + 2) {
661 DrawLineBlack(12,15);
663 DrawLineBlack(16,19);
667 if (i_line == minus30 - 2) {
669 DrawLineBlack(12,15);
671 DrawLineBlack(16,19);
673 if (i_line == minus30 - 1) {
675 DrawLineBlack(14,15);
677 DrawLineBlack(16,17);
678 DrawLineBlack(18,19);
680 DrawLineWhite(24,27); //White
682 if (i_line == minus30) {
684 DrawLineBlack(12,15);
686 DrawLineBlack(16,17);
687 DrawLineBlack(18,19);
689 DrawLineBlack(24,27);
691 if (i_line == minus30 + 1) {
693 DrawLineBlack(14,15);
695 DrawLineBlack(16,17);
696 DrawLineBlack(18,19);
698 DrawLineBlack(24,27);
700 if (i_line == minus30 + 2) {
702 DrawLineBlack(12,15);
704 DrawLineBlack(16,19);
708 if (i_line == minus40 - 2) {
710 DrawLineBlack(14,15);
712 DrawLineBlack(16,19);
714 if (i_line == minus40 - 1) {
716 DrawLineBlack(14,15);
718 DrawLineBlack(16,17);
719 DrawLineBlack(18,19);
721 DrawLineWhite(24,27); // white
723 if (i_line == minus40) {
725 DrawLineBlack(12,15);
727 DrawLineBlack(16,17);
728 DrawLineBlack(18,19);
730 DrawLineBlack(24,27);
732 if (i_line == minus40 + 1) {
734 DrawLineBlack(12,13);
735 DrawLineBlack(14,15);
737 DrawLineBlack(16,17);
738 DrawLineBlack(18,19);
740 DrawLineBlack(24,27);
742 if (i_line == minus40 + 2) {
744 DrawLineBlack(12,13);
745 DrawLineBlack(14,15);
747 DrawLineBlack(16,19);
751 if (i_line == minus50 - 2) {
753 DrawLineBlack(12,15);
755 DrawLineBlack(16,19);
757 if (i_line == minus50 - 1) {
759 DrawLineBlack(14,15);
761 DrawLineBlack(16,17);
762 DrawLineBlack(18,19);
764 DrawLineWhite(24,27); //White
766 if (i_line == minus50) {
768 DrawLineBlack(12,15);
770 DrawLineBlack(16,17);
771 DrawLineBlack(18,19);
773 DrawLineBlack(24,27);
775 if (i_line == minus50 + 1) {
777 DrawLineBlack(12,13);
779 DrawLineBlack(16,17);
780 DrawLineBlack(18,19);
782 DrawLineBlack(24,27);
784 if (i_line == minus50 + 2) {
786 DrawLineBlack(12,15);
788 DrawLineBlack(16,19);
791 if (i_line == minus60 - 2) {
793 DrawLineBlack(12,15);
795 DrawLineBlack(16,19);
797 if (i_line == minus60 - 1) {
799 DrawLineBlack(12,13);
800 DrawLineBlack(14,15);
802 DrawLineBlack(16,17);
803 DrawLineBlack(18,19);
805 DrawLineWhite(24,27); //White
807 if (i_line == minus60) {
809 DrawLineBlack(12,15);
811 DrawLineBlack(16,17);
812 DrawLineBlack(18,19);
814 DrawLineBlack(24,27);
816 if (i_line == minus60 + 1) {
818 DrawLineBlack(12,13);
820 DrawLineBlack(16,17);
821 DrawLineBlack(18,19);
823 DrawLineBlack(24,27);
825 if (i_line == minus60 + 2) {
827 DrawLineBlack(12,15);
829 DrawLineBlack(16,19);
833 #define drawPoint(offset,y,u,v,a) \
834 *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + offset ) = y; \
835 *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + offset ) = u; \
836 *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + offset ) = v; \
837 *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + offset ) = a;
840 // draw the bars and channel indicators
841 for (i=0; i<nbChannels; i++) {
842 pi = 25 + ((i+1)*5) + (i*barWidth) ; // 25 separació amb indicador, 5 separació entre barres
844 for( j = pi; j < pi + barWidth; j++)
846 // channel indicators
847 for ( i_line = 12; i_line < 20; i_line++ ) {
849 drawPoint(j,76,85,0xFF,0xFF); // red
852 drawPoint(j,0,128,128,0xFF); // black DrawLine(pi,pf,0xFF,128,128,0xFF);
857 for( i_line = 20; i_line < i_values[i]+20; i_line++ )
859 if (i_line < minus18) { // green if < -18 dB
860 drawPoint(j,150,44,21,0xFF);
861 //DrawLine(pi,pf,150,44,21,0xFF);
862 } else if (i_line < minus8) { // yellow if > -18dB and < -8dB
863 drawPoint(j,226,1,148,0xFF);
864 //DrawLine(pi,pf,226,1,148,0xFF);
865 } else { // red if > -8 dB
866 drawPoint(j,76,85,0xFF,0xFF);
867 //DrawLine(pi,pf,76,85,255,0xFF);
871 for( ; i_line < scale+20; i_line++ )
873 if (i_line < minus18) { // green if < -18 dB
874 drawPoint(j,74,85,74,0xFF);
875 //DrawLine(pi,pf,74,85,74,0xFF);
876 } else if (i_line < minus8) { // yellow if > -18dB and < -8dB
877 drawPoint(j,112,64,138,0xFF);
878 //DrawLine(pi,pf,112,64,138,0xFF);
879 } else { // red if > -8 dB
880 drawPoint(j,37,106,191,0xFF);
881 //DrawLine(pi,pf,37,106,191,0xFF);
890 /*****************************************************************************
891 * LoadBarGraph: loads the BarGraph images into memory
892 *****************************************************************************/
893 static void LoadBarGraph( vlc_object_t *p_this, BarGraph_t *p_BarGraph )
896 p_BarGraph->p_pic = LoadImage( p_this, p_BarGraph->nbChannels, p_BarGraph->i_values, p_BarGraph->scale, p_BarGraph->alarm, p_BarGraph->barWidth);
897 if( !p_BarGraph->p_pic )
899 msg_Warn( p_this, "error while creating picture" );
904 /*****************************************************************************
905 * parse_i_values : parse i_values parameter and store the corresponding values
906 *****************************************************************************/
907 void parse_i_values( BarGraph_t *p_BarGraph, char *i_values)
914 p_BarGraph->nbChannels = 0;
915 p_BarGraph->i_values = NULL;
916 res = strtok_r(i_values, delim, &tok);
917 while (res != NULL) {
918 p_BarGraph->nbChannels++;
919 p_BarGraph->i_values = xrealloc(p_BarGraph->i_values,
920 p_BarGraph->nbChannels*sizeof(int));
921 db = log10(atof(res)) * 20;
922 p_BarGraph->i_values[p_BarGraph->nbChannels-1] = VLC_CLIP( iec_scale(db)*p_BarGraph->scale, 0, p_BarGraph->scale );
923 res = strtok_r(NULL, delim, &tok);
928 /*****************************************************************************
929 * IEC 268-18 Source: meterbridge
930 *****************************************************************************/
931 static float iec_scale(float dB)
937 else if (dB < -60.0f)
938 fScale = (dB + 70.0f) * 0.0025f;
939 else if (dB < -50.0f)
940 fScale = (dB + 60.0f) * 0.005f + 0.025f;
942 fScale = (dB + 50.0f) * 0.0075f + 0.075f;
943 else if (dB < -30.0f)
944 fScale = (dB + 40.0f) * 0.015f + 0.15f;
945 else if (dB < -20.0f)
946 fScale = (dB + 30.0f) * 0.02f + 0.3f;
947 else if (dB < -0.001f || dB > 0.001f) /* if (dB < 0.0f) */
948 fScale = (dB + 20.0f) * 0.025f + 0.5f;