1 /*****************************************************************************
2 * visual.c : Visualisation system
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: visual.c,v 1.7 2003/09/14 16:41:48 zorglub Exp $
7 * Authors: Clément Stenac <zorglub@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 /*****************************************************************************
33 *****************************************************************************/
34 static int Open ( vlc_object_t * );
35 static void Close ( vlc_object_t * );
37 static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
40 /*****************************************************************************
42 *****************************************************************************/
43 #define ELIST_TEXT N_( "Effects list" )
44 #define ELIST_LONGTEXT N_( \
45 "A list of visual effect, separated by commas.\n" \
46 "Current effects include: dummy, random, scope, spectrum" )
48 #define WIDTH_TEXT N_( "Video width" )
49 #define HEIGHT_LONGTEXT N_( \
50 "The width of the effects video window, in pixels." )
52 #define HEIGHT_TEXT N_( "Video width" )
53 #define WIDTH_LONGTEXT N_( \
54 "The width of the effects video window, in pixels." )
56 #define NBBANDS_TEXT N_( "Number of bands" )
57 #define NBBANDS_LONGTEXT N_( \
58 "Number of bands used by spectrum analizer, should be 20 or 80" )
60 #define SEPAR_TEXT N_( "Band separator" )
61 #define SEPAR_LONGTEXT N_( \
62 "Number of blank pixels between bands")
64 #define AMP_TEXT N_( "Amplification" )
65 #define AMP_LONGTEXT N_( \
66 "This is a coefficient that modifies the height of the bands")
68 #define PEAKS_TEXT N_( "Enable peaks" )
69 #define PEAKS_LONGTEXT N_( \
70 "Defines whether to draw peaks" )
72 #define STARS_TEXT N_( "Number of stars" )
73 #define STARS_LONGTEXT N_( \
74 "Defines the number of stars to draw with random effect" )
77 add_category_hint( N_("visualizer") , NULL , VLC_FALSE);
78 set_description( _("visualizer filter") );
79 add_string("effect-list", "dummy", NULL,
80 ELIST_TEXT, ELIST_LONGTEXT, VLC_TRUE );
81 add_integer("effect-width",VOUT_WIDTH,NULL,
82 WIDTH_TEXT, WIDTH_LONGTEXT, VLC_FALSE );
83 add_integer("effect-height" , VOUT_HEIGHT , NULL,
84 HEIGHT_TEXT, HEIGHT_LONGTEXT, VLC_FALSE );
85 add_integer("visual-nbbands", 80, NULL,
86 NBBANDS_TEXT, NBBANDS_LONGTEXT, VLC_FALSE );
87 add_integer("visual-separ", 1, NULL,
88 SEPAR_TEXT, SEPAR_LONGTEXT, VLC_FALSE );
89 add_integer("visual-amp", 3, NULL,
90 AMP_TEXT, AMP_LONGTEXT, VLC_FALSE );
91 add_bool("visual-peaks", VLC_TRUE, NULL,
92 PEAKS_TEXT, PEAKS_LONGTEXT, VLC_FALSE );
93 add_integer("visual-stars", 200, NULL,
94 STARS_TEXT, STARS_LONGTEXT, VLC_FALSE );
95 set_capability( "audio filter", 0 );
96 set_callbacks( Open, Close );
97 add_shortcut( "visualizer");
100 /*****************************************************************************
101 * Open: open the visualizer
102 *****************************************************************************/
103 static int Open( vlc_object_t *p_this )
105 aout_filter_t *p_filter = (aout_filter_t *)p_this;
108 char *psz_eof; /* Used to parse effect list */
109 char *psz_eoa, *psz_boa; /* Used to parse arg lists */
111 vlc_bool_t b_end = VLC_FALSE;
113 visual_effect_t *p_current_effect = NULL;
115 if( (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
116 && p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) )
121 p_filter->p_sys = malloc(sizeof(struct aout_filter_sys_t));
122 if ( p_filter->p_sys == NULL )
124 msg_Err( p_filter, "out of memory" );
128 p_filter->p_sys->i_height = config_GetInt( p_filter , "effect-height");
129 p_filter->p_sys->i_width = config_GetInt( p_filter , "effect-width");
131 if ( p_filter->p_sys->i_height < 20 )
132 p_filter->p_sys->i_height = 20;
133 if ( p_filter->p_sys->i_width < 20 )
134 p_filter->p_sys->i_width = 20;
136 if( (p_filter->p_sys->i_height % 2 ) != 0 )
137 p_filter->p_sys->i_height --;
139 if( (p_filter->p_sys->i_width % 2 ) != 0 )
140 p_filter->p_sys->i_width --;
142 /* Parse the effect list */
143 psz_effects = config_GetPsz( p_filter, "effect-list" );
144 msg_Dbg( p_filter , "Building list of effects" );
146 p_filter->p_sys->p_first_effect =
147 (visual_effect_t *)malloc( sizeof( visual_effect_t ) );
148 if( !p_filter->p_sys->p_first_effect )
150 msg_Err( p_filter, "Out of memory" );
154 p_current_effect = p_filter->p_sys->p_first_effect;
155 p_current_effect->p_next = NULL;
158 psz_eof = strchr( psz_effects , ',' );
162 psz_eof = strchr( psz_effects,'\0');
169 p_current_effect->p_next =
170 (visual_effect_t *)malloc( sizeof( visual_effect_t ) );
171 if( !p_current_effect )
173 msg_Err( p_filter, "Out of memory" );
176 p_current_effect = p_current_effect -> p_next;
177 p_current_effect->psz_func = strdup("dummy");
178 p_current_effect->p_next = NULL;
179 p_current_effect->i_width = p_filter->p_sys->i_width;
180 p_current_effect->i_height = p_filter->p_sys->i_height;
181 p_current_effect->p_data = NULL;
184 if(! strncasecmp(psz_effects,"dummy",5))
185 p_current_effect->pf_run = dummy_Run;
186 else if(! strncasecmp(psz_effects,"scope",5) )
187 p_current_effect->pf_run = scope_Run;
188 else if(! strncasecmp(psz_effects,"spectrum",8) )
189 p_current_effect->pf_run = spectrum_Run;
190 else if(! strncasecmp(psz_effects,"random",6) )
191 p_current_effect->pf_run = random_Run;
192 else if(! strncasecmp(psz_effects,"blur",4) )
193 p_current_effect->pf_run = blur_Run;
195 if(! ( strncasecmp(psz_effects,"dummy",5) &&
196 strncasecmp(psz_effects,"scope",5) &&
197 strncasecmp(psz_effects,"spectrum",8) &&
198 strncasecmp(psz_effects,"random",6) ) )
199 p_current_effect->psz_func = strdup( psz_effects ) ;
201 p_current_effect->psz_args = NULL;
202 p_current_effect->i_nb_chans =
203 aout_FormatNbChannels( &p_filter->input);
204 psz_boa = strchr( psz_effects, '{' );
207 psz_eoa = strchr( psz_effects, '}');
210 msg_Err( p_filter, "Unable to parse effect list. Aborting");
214 p_current_effect->psz_args = strdup(++psz_boa);
215 psz_effects = psz_eoa;
217 psz_effects = psz_eof;
220 if( b_end == VLC_TRUE )
224 p_filter->pf_do_work = DoWork;
225 p_filter->b_in_place= 1;
227 /* Open the video output */
228 p_filter->p_sys->p_vout =
229 vout_Request( p_filter, NULL,
230 p_filter->p_sys->i_width,
231 p_filter->p_sys->i_height,
232 VLC_FOURCC('I','4','2','0'),
233 VOUT_ASPECT_FACTOR * p_filter->p_sys->i_width/
234 p_filter->p_sys->i_height );
236 /* vout_Create( p_filter,
237 p_filter->p_sys->i_width,
238 p_filter->p_sys->i_height,
239 VLC_FOURCC('I','4','2','0'),
240 VOUT_ASPECT_FACTOR * p_filter->p_sys->i_width/
241 p_filter->p_sys->i_height );*/
243 if( p_filter->p_sys->p_vout == NULL )
245 msg_Err( p_filter, "no suitable vout module" );
247 free( p_filter->p_sys );
251 msg_Dbg(p_filter,"Visualizer initialized");
255 /*****************************************************************************
256 * DoWork: convert a buffer
257 *****************************************************************************
258 * Audio part pasted from trivial.c
259 ****************************************************************************/
260 static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
261 aout_buffer_t *p_in_buf, aout_buffer_t *p_out_buf )
265 visual_effect_t *p_current_effect;
267 int i_input_nb = aout_FormatNbChannels( &p_filter->input );
268 int i_output_nb = aout_FormatNbChannels( &p_filter->output );
269 s32 * p_dest = (s32 *)p_out_buf->p_buffer;
270 s32 * p_src = (s32 *)p_in_buf->p_buffer;
273 p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
274 p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb;
276 /* First, get a new picture */
277 while( ( p_outpic = vout_CreatePicture( p_filter->p_sys->p_vout,
278 VLC_FALSE, VLC_FALSE, 3 ) ) == NULL )
282 msleep( VOUT_OUTMEM_SLEEP );
285 /* Blank the picture */
286 for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
288 memset( p_outpic->p[i_index].p_pixels, i_index ? 0x80 : 0x00,
289 p_outpic->p[i_index].i_lines * p_outpic->p[i_index].i_pitch );
292 /* We can now call our visualization effects */
293 p_current_effect = p_filter->p_sys->p_first_effect;
295 while( p_current_effect )
298 if( !strcasecmp( p_current_effect->psz_func, "dummy" ) )
300 dummy_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
302 else if( !strcasecmp( p_current_effect->psz_func, "scope" ) )
304 scope_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
306 else if( !strcasecmp( p_current_effect->psz_func, "random" ) )
308 random_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
310 else if( !strcasecmp( p_current_effect->psz_func, "spectrum" ) )
312 spectrum_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
314 p_current_effect = p_current_effect->p_next;
317 vout_DatePicture ( p_filter->p_sys->p_vout,p_outpic,
318 ( p_in_buf->start_date + p_in_buf->end_date) /2 );
321 vout_DisplayPicture ( p_filter->p_sys->p_vout, p_outpic );
327 /*****************************************************************************
328 * Close: close the plugin
329 *****************************************************************************/
330 static void Close( vlc_object_t *p_this )
332 aout_filter_t * p_filter = (aout_filter_t *)p_this;
334 visual_effect_t *p_old;
335 visual_effect_t *p_cur = p_filter->p_sys->p_first_effect;
337 if( p_filter->p_sys->p_vout )
339 vlc_object_detach( p_filter->p_sys->p_vout) ;
340 vout_Destroy( p_filter->p_sys->p_vout );
347 p_cur = p_cur->p_next;
348 if( p_old ) free( p_old );
351 if( p_filter->p_sys != NULL )
352 free( p_filter->p_sys);