1 /*****************************************************************************
2 * scope.c : Scope effect module
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: scope.c,v 1.8 2002/06/01 18:04:48 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
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 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
28 #include <string.h> /* strdup() */
35 #define SCOPE_WIDTH 320
36 #define SCOPE_HEIGHT 240
37 #define SCOPE_ASPECT (VOUT_ASPECT_FACTOR*SCOPE_WIDTH/SCOPE_HEIGHT)
39 /*****************************************************************************
40 * aout_sys_t: scope audio output method descriptor
41 *****************************************************************************
42 * This structure is part of the audio output thread descriptor.
43 * It describes some scope specific variables.
44 *****************************************************************************/
48 aout_fifo_t *p_aout_fifo;
50 vout_thread_t *p_vout;
53 /*****************************************************************************
55 *****************************************************************************/
56 static void aout_getfunctions( function_list_t * p_function_list );
58 static int aout_Open ( aout_thread_t *p_aout );
59 static int aout_SetFormat ( aout_thread_t *p_aout );
60 static int aout_GetBufInfo ( aout_thread_t *p_aout, int i_buffer_info );
61 static void aout_Play ( aout_thread_t *p_aout,
62 byte_t *buffer, int i_size );
63 static void aout_Close ( aout_thread_t *p_aout );
65 /*****************************************************************************
66 * Build configuration tree.
67 *****************************************************************************/
72 SET_DESCRIPTION( _("scope effect module") )
73 ADD_CAPABILITY( AOUT, 0 )
74 ADD_SHORTCUT( "scope" )
78 aout_getfunctions( &p_module->p_functions->aout );
81 MODULE_DEACTIVATE_START
82 MODULE_DEACTIVATE_STOP
84 /*****************************************************************************
85 * Functions exported as capabilities. They are declared as static so that
86 * we don't pollute the namespace too much.
87 *****************************************************************************/
88 static void aout_getfunctions( function_list_t * p_function_list )
90 p_function_list->functions.aout.pf_open = aout_Open;
91 p_function_list->functions.aout.pf_setformat = aout_SetFormat;
92 p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
93 p_function_list->functions.aout.pf_play = aout_Play;
94 p_function_list->functions.aout.pf_close = aout_Close;
97 /*****************************************************************************
98 * aout_Open: open a scope effect plugin
99 *****************************************************************************/
100 static int aout_Open( aout_thread_t *p_aout )
104 /* Allocate structure */
105 p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
106 if( p_aout->p_sys == NULL )
108 msg_Err( p_aout, "out of memory" );
112 psz_method = config_GetPsz( p_aout, "aout" );
126 /* Open video output */
127 p_aout->p_sys->p_vout =
128 vout_CreateThread( p_aout, SCOPE_WIDTH, SCOPE_HEIGHT,
129 FOURCC_I420, SCOPE_ASPECT );
131 if( p_aout->p_sys->p_vout == NULL )
133 msg_Err( p_aout, "no suitable vout module" );
134 free( p_aout->p_sys );
138 /* Open audio output */
139 p_aout->p_sys->aout.i_format = p_aout->i_format;
140 p_aout->p_sys->aout.i_rate = p_aout->i_rate;
141 p_aout->p_sys->aout.i_channels = p_aout->i_channels;
143 p_aout->p_sys->aout.p_module =
144 module_Need( p_aout, MODULE_CAPABILITY_AOUT,
145 "", (void *)&p_aout->p_sys->aout );
146 if( p_aout->p_sys->aout.p_module == NULL )
148 msg_Err( p_aout, "no suitable aout module" );
149 vout_DestroyThread( p_aout->p_sys->p_vout );
150 free( p_aout->p_sys );
154 #define aout_functions p_aout->p_sys->aout.p_module->p_functions->aout.functions.aout
155 p_aout->p_sys->aout.pf_open = aout_functions.pf_open;
156 p_aout->p_sys->aout.pf_setformat = aout_functions.pf_setformat;
157 p_aout->p_sys->aout.pf_getbufinfo = aout_functions.pf_getbufinfo;
158 p_aout->p_sys->aout.pf_play = aout_functions.pf_play;
159 p_aout->p_sys->aout.pf_close = aout_functions.pf_close;
160 #undef aout_functions
165 /*****************************************************************************
166 * aout_SetFormat: set the output format
167 *****************************************************************************/
168 static int aout_SetFormat( aout_thread_t *p_aout )
172 /* Force the output method */
173 p_aout->p_sys->aout.i_format = p_aout->i_format;
174 p_aout->p_sys->aout.i_channels = p_aout->i_channels;
175 p_aout->p_sys->aout.i_rate = p_aout->i_rate;
178 * Initialize audio device
180 i_ret = p_aout->p_sys->aout.pf_setformat( &p_aout->p_sys->aout );
187 if( p_aout->p_sys->aout.i_format != p_aout->i_format
188 || p_aout->p_sys->aout.i_channels != p_aout->i_channels )
190 msg_Err( p_aout, "plugin is not very cooperative" );
194 p_aout->i_channels = p_aout->p_sys->aout.i_channels;
195 p_aout->i_format = p_aout->p_sys->aout.i_format;
196 p_aout->i_rate = p_aout->p_sys->aout.i_rate;
201 /*****************************************************************************
202 * aout_GetBufInfo: buffer status query
203 *****************************************************************************/
204 static int aout_GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
206 return p_aout->p_sys->aout.pf_getbufinfo( &p_aout->p_sys->aout,
210 /*****************************************************************************
211 * aout_Play: play a sound samples buffer
212 *****************************************************************************
213 * This function writes a buffer of i_length bytes in the socket
214 *****************************************************************************/
215 static void aout_Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
218 int i_index, i_image;
222 /* Play the real sound */
223 p_aout->p_sys->aout.pf_play( &p_aout->p_sys->aout, p_buffer, i_size );
225 for( i_image = 0; (i_image + 1) * SCOPE_WIDTH * 8 < i_size ; i_image++ )
227 /* Don't stay here forever */
228 if( mdate() >= p_aout->date - 10000 )
233 /* This is a new frame. Get a structure from the video_output. */
234 while( ( p_outpic = vout_CreatePicture( p_aout->p_sys->p_vout, 0, 0, 0 ) )
241 msleep( VOUT_OUTMEM_SLEEP );
244 /* Blank the picture */
245 for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
247 memset( p_outpic->p[i_index].p_pixels, i_index ? 0x80 : 0x00,
248 p_outpic->p[i_index].i_lines * p_outpic->p[i_index].i_pitch );
251 /* We only support 2 channels for now */
252 for( i_index = 0 ; i_index < 2 ; i_index++ )
255 for( j = 0 ; j < 3 ; j++ )
257 ppp_area[i_index][j] =
258 p_outpic->p[j].p_pixels + i_index * p_outpic->p[j].i_lines
259 / p_aout->i_channels * p_outpic->p[j].i_pitch;
263 for( i_index = 0, p_sample = (u16*)p_buffer;
264 i_index < SCOPE_WIDTH;
270 for( i = 0 ; i < 2 ; i++ )
273 i_value = *p_sample++ / 256 + 128;
275 + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
276 + p_outpic->p[0].i_lines * i_value / 512
277 * p_outpic->p[0].i_pitch) = 0xbf;
279 + p_outpic->p[1].i_pitch * i_index / SCOPE_WIDTH
280 + p_outpic->p[1].i_lines * i_value / 512
281 * p_outpic->p[1].i_pitch) = 0xff;
284 i_value = *p_sample++ / 256 + 128;
286 + p_outpic->p[0].i_pitch * i_index / SCOPE_WIDTH
287 + p_outpic->p[0].i_lines * i_value / 512
288 * p_outpic->p[0].i_pitch) = 0x9f;
290 + p_outpic->p[2].i_pitch * i_index / SCOPE_WIDTH
291 + p_outpic->p[2].i_lines * i_value / 512
292 * p_outpic->p[2].i_pitch) = 0xdd;
296 /* Display the picture - FIXME: find a better date :-) */
297 vout_DatePicture( p_aout->p_sys->p_vout, p_outpic,
298 p_aout->date + i_image * 20000 );
299 vout_DisplayPicture( p_aout->p_sys->p_vout, p_outpic );
301 p_buffer += SCOPE_WIDTH * 4;
305 /*****************************************************************************
306 * aout_Close: close the Esound socket
307 *****************************************************************************/
308 static void aout_Close( aout_thread_t *p_aout )
310 p_aout->p_sys->aout.pf_close( &p_aout->p_sys->aout );
311 module_Unneed( p_aout->p_sys->aout.p_module );
312 vout_DestroyThread( p_aout->p_sys->p_vout );
313 free( p_aout->p_sys );