]> git.sesse.net Git - vlc/blob - modules/visualization/visual/visual.c
* modules/visualisation/visual/visual.c: thou shall not use //
[vlc] / modules / visualization / visual / visual.c
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 $
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@via.ecp.fr>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "visual.h"
28
29 #include <vlc/vlc.h>
30
31 /*****************************************************************************
32  * Local prototypes
33  *****************************************************************************/
34 static int  Open         ( vlc_object_t * );             
35 static void Close        ( vlc_object_t * );                   
36
37 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
38                                         aout_buffer_t * );
39
40 /*****************************************************************************
41  * Module descriptor
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" )
47
48 #define WIDTH_TEXT N_( "Video width" )
49 #define HEIGHT_LONGTEXT N_( \
50       "The width of the effects video window, in pixels." )
51
52 #define HEIGHT_TEXT N_( "Video width" )
53 #define WIDTH_LONGTEXT N_( \
54       "The width of the effects video window, in pixels." )
55
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" )
59
60 #define SEPAR_TEXT N_( "Band separator" )
61 #define SEPAR_LONGTEXT N_( \
62         "Number of blank pixels between bands")
63       
64 #define AMP_TEXT N_( "Amplification" )
65 #define AMP_LONGTEXT N_( \
66         "This is a coefficient that modifies the height of the bands")
67       
68 #define PEAKS_TEXT N_( "Enable peaks" )
69 #define PEAKS_LONGTEXT N_( \
70         "Defines whether to draw peaks" )
71
72 #define STARS_TEXT N_( "Number of stars" )
73 #define STARS_LONGTEXT N_( \
74         "Defines the number of stars to draw with random effect" )
75
76 vlc_module_begin();
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");
98 vlc_module_end();
99
100 /*****************************************************************************
101  * Open: open the visualizer
102  *****************************************************************************/
103 static int Open( vlc_object_t *p_this )
104 {
105     aout_filter_t *p_filter = (aout_filter_t *)p_this;
106
107     char *psz_effects;
108     char  *psz_eof; /* Used to parse effect list */
109     char *psz_eoa, *psz_boa;     /* Used to parse arg lists */
110      
111     vlc_bool_t b_end = VLC_FALSE;
112     
113     visual_effect_t *p_current_effect = NULL;
114
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')) )
117     {
118             return -1;
119     }
120
121     p_filter->p_sys = malloc(sizeof(struct aout_filter_sys_t));
122     if ( p_filter->p_sys == NULL )
123     {
124         msg_Err( p_filter, "out of memory" );
125         return -1;
126     }
127
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");
130
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;
135     
136     if( (p_filter->p_sys->i_height % 2 ) != 0 )
137         p_filter->p_sys->i_height --;
138    
139     if( (p_filter->p_sys->i_width % 2 ) != 0 )
140         p_filter->p_sys->i_width --;
141     
142     /* Parse the effect list */
143     psz_effects = config_GetPsz( p_filter, "effect-list" );
144     msg_Dbg( p_filter , "Building list of effects" );
145     
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 ) 
149     {
150         msg_Err( p_filter, "Out of memory" );
151         return -1;
152     }
153
154     p_current_effect = p_filter->p_sys->p_first_effect;
155     p_current_effect->p_next = NULL;
156     while(1)
157     {
158         psz_eof = strchr( psz_effects , ','  );
159         if( !psz_eof )
160         {
161             b_end = VLC_TRUE;
162             psz_eof = strchr( psz_effects,'\0');
163         }
164         if( psz_eof )
165         {
166             *psz_eof = '\0';
167         }
168
169         p_current_effect->p_next =
170                 (visual_effect_t *)malloc( sizeof( visual_effect_t ) );
171         if( !p_current_effect )
172         {
173             msg_Err( p_filter, "Out of memory" );
174         }
175         
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;
182
183 #if 0
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;
194 #endif
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 ) ;
200         
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, '{' );
205         if( psz_boa )
206         {
207             psz_eoa = strchr( psz_effects, '}');
208             if( ! psz_eoa )
209             {
210                msg_Err( p_filter, "Unable to parse effect list. Aborting");
211                return -1;
212             }
213             *psz_eoa = '\0';
214             p_current_effect->psz_args = strdup(++psz_boa);
215             psz_effects = psz_eoa;
216         }
217         psz_effects =  psz_eof;
218         psz_effects ++;
219
220         if( b_end == VLC_TRUE )
221             break;
222     }
223                 
224     p_filter->pf_do_work = DoWork;
225     p_filter->b_in_place= 1;
226
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  );        
235
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 );*/
242     
243     if( p_filter->p_sys->p_vout == NULL )
244     {
245         msg_Err( p_filter, "no suitable vout module" );
246         if(p_filter->p_sys)
247             free( p_filter->p_sys );
248         return -1;
249     }
250             
251     msg_Dbg(p_filter,"Visualizer initialized");
252     return 0 ;
253 }
254
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 )
262 {
263     picture_t *p_outpic;
264        
265     visual_effect_t *p_current_effect;
266     
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;
271     int i_index;
272         
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;
275
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 )
279     {
280             if(p_aout->b_die )
281                return;
282             msleep( VOUT_OUTMEM_SLEEP );
283     }
284
285     /* Blank the picture */
286     for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
287     {
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 );
290     }
291
292     /* We can now call our visualization effects */
293     p_current_effect = p_filter->p_sys->p_first_effect;
294
295     while( p_current_effect )  
296     {
297
298         if( !strcasecmp( p_current_effect->psz_func, "dummy" ) )
299         {
300             dummy_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
301         }
302         else if( !strcasecmp( p_current_effect->psz_func, "scope" ) )
303         {
304             scope_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
305         }
306         else if( !strcasecmp( p_current_effect->psz_func, "random" ) )
307         {
308             random_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
309         }
310         else if( !strcasecmp( p_current_effect->psz_func, "spectrum" ) )
311         {
312             spectrum_Run(p_current_effect, p_aout, p_out_buf , p_outpic );
313         }
314         p_current_effect = p_current_effect->p_next;
315     }
316    
317     vout_DatePicture ( p_filter->p_sys->p_vout,p_outpic,
318                   ( p_in_buf->start_date + p_in_buf->end_date) /2 );
319     
320     
321     vout_DisplayPicture ( p_filter->p_sys->p_vout, p_outpic );
322
323     
324     
325 }
326
327 /*****************************************************************************
328  * Close: close the plugin
329  *****************************************************************************/
330 static void Close( vlc_object_t *p_this )
331 {
332     aout_filter_t * p_filter = (aout_filter_t *)p_this;
333
334     visual_effect_t *p_old;
335     visual_effect_t *p_cur = p_filter->p_sys->p_first_effect;
336     
337     if( p_filter->p_sys->p_vout ) 
338     {
339         vlc_object_detach( p_filter->p_sys->p_vout) ;
340         vout_Destroy( p_filter->p_sys->p_vout );
341     }
342    
343     /* Free the list */ 
344     while( p_cur )
345     {
346         p_old = p_cur;
347         p_cur = p_cur->p_next;
348         if( p_old ) free( p_old );
349     }
350                     
351     if( p_filter->p_sys != NULL )
352         free( p_filter->p_sys);
353 }