e9dbf10d8b5efc843c6f725dfff10021afa017d5
[vlc.git] / plugins / fx / scope.c
1 /*****************************************************************************
2  * scope.c : Scope effect module
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: scope.c,v 1.2 2002/02/27 22:57:10 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
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 <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>                                              /* strdup() */
29 #include <errno.h>
30
31 #include <videolan/vlc.h>
32
33 #include "video.h"
34 #include "video_output.h"
35
36 #include "audio_output.h"                                   /* aout_thread_t */
37
38 #define SCOPE_WIDTH 640
39 #define SCOPE_HEIGHT 200
40 #define SCOPE_ASPECT (VOUT_ASPECT_FACTOR*SCOPE_WIDTH/SCOPE_HEIGHT)
41
42 /*****************************************************************************
43  * Capabilities defined in the other files.
44  *****************************************************************************/
45 static void aout_getfunctions( function_list_t * p_function_list );
46
47 /*****************************************************************************
48  * aout_sys_t: scope audio output method descriptor
49  *****************************************************************************
50  * This structure is part of the audio output thread descriptor.
51  * It describes some scope specific variables.
52  *****************************************************************************/
53 typedef struct aout_sys_s
54 {
55     struct aout_thread_s aout;
56     struct aout_fifo_s *p_aout_fifo;
57
58     struct vout_thread_s *p_vout;
59
60 } aout_sys_t;
61
62 /*****************************************************************************
63  * Build configuration tree.
64  *****************************************************************************/
65 MODULE_CONFIG_START
66 MODULE_CONFIG_STOP
67
68 MODULE_INIT_START
69     SET_DESCRIPTION( "scope effect module" )
70     ADD_CAPABILITY( AOUT, 0 )
71     ADD_SHORTCUT( "scope" )
72 MODULE_INIT_STOP
73
74 MODULE_ACTIVATE_START
75     aout_getfunctions( &p_module->p_functions->aout );
76 MODULE_ACTIVATE_STOP
77
78 MODULE_DEACTIVATE_START
79 MODULE_DEACTIVATE_STOP
80
81 /*****************************************************************************
82  * Local prototypes.
83  *****************************************************************************/
84 static int     aout_Open        ( aout_thread_t *p_aout );
85 static int     aout_SetFormat   ( aout_thread_t *p_aout );
86 static int     aout_GetBufInfo  ( aout_thread_t *p_aout, int i_buffer_info );
87 static void    aout_Play        ( aout_thread_t *p_aout,
88                                   byte_t *buffer, int i_size );
89 static void    aout_Close       ( aout_thread_t *p_aout );
90
91 /*****************************************************************************
92  * Functions exported as capabilities. They are declared as static so that
93  * we don't pollute the namespace too much.
94  *****************************************************************************/
95 static void aout_getfunctions( function_list_t * p_function_list )
96 {
97     p_function_list->functions.aout.pf_open = aout_Open;
98     p_function_list->functions.aout.pf_setformat = aout_SetFormat;
99     p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
100     p_function_list->functions.aout.pf_play = aout_Play;
101     p_function_list->functions.aout.pf_close = aout_Close;
102 }
103
104 /*****************************************************************************
105  * aout_Open: open a scope effect plugin
106  *****************************************************************************/
107 static int aout_Open( aout_thread_t *p_aout )
108 {
109     /* Allocate structure */
110     p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
111     if( p_aout->p_sys == NULL )
112     {
113         intf_ErrMsg("error: %s", strerror(ENOMEM) );
114         return( 1 );
115     }
116
117     p_aout->p_sys->p_vout =
118         vout_CreateThread( NULL, SCOPE_WIDTH, SCOPE_HEIGHT,
119                            FOURCC_I420, SCOPE_ASPECT );
120
121     return( 0 );
122 }
123
124 /*****************************************************************************
125  * aout_SetFormat: set the output format
126  *****************************************************************************/
127 static int aout_SetFormat( aout_thread_t *p_aout )
128 {
129     /* Force the output method */
130     p_aout->i_format = AOUT_FMT_U16_LE;
131     p_aout->i_channels = 2;
132
133     p_aout->p_sys->aout.i_format = p_aout->i_format;
134     p_aout->p_sys->aout.i_channels = p_aout->i_channels;
135     p_aout->p_sys->aout.i_rate = p_aout->i_rate;
136
137     return( 0 );
138 }
139
140 /*****************************************************************************
141  * aout_GetBufInfo: buffer status query
142  *****************************************************************************/
143 static int aout_GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
144 {
145     /* arbitrary value that should be changed */
146     return( i_buffer_limit );
147 }
148
149 /*****************************************************************************
150  * aout_Play: play a sound samples buffer
151  *****************************************************************************
152  * This function writes a buffer of i_length bytes in the socket
153  *****************************************************************************/
154 static void aout_Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
155 {
156     picture_t *p_outpic;
157     int i_index;
158     u8 *p_pixel;
159     u16 *p_sample;
160
161     /* This is a new frame. Get a structure from the video_output. */
162     while( ( p_outpic = vout_CreatePicture( p_aout->p_sys->p_vout, 0, 0, 0 ) )
163               == NULL )
164     {
165         if( p_aout->b_die )
166         {
167             return;
168         }
169         msleep( VOUT_OUTMEM_SLEEP );
170     }
171
172     /* Blank the picture */
173     for( i_index = 0 ; i_index < p_outpic->i_planes ; i_index++ )
174     {
175         memset( p_outpic->p[i_index].p_pixels, i_index ? 0x80 : 0x00,
176                 p_outpic->p[i_index].i_lines * p_outpic->p[i_index].i_pitch );
177     }
178
179     /* Left channel */
180     for( i_index = 0, p_sample = (u16*)p_buffer;
181          i_index < SCOPE_WIDTH && i_index < i_size / 2;
182          i_index++ )
183     {
184         int i;
185         u8 i_value = *p_sample / 256;
186
187         for( i = 0 ; i < 8 ; i++ )
188         {
189             p_pixel = p_outpic->p[0].p_pixels + (p_outpic->p[0].i_pitch * i_index) / SCOPE_WIDTH + p_outpic->p[0].i_lines * (u8)(i_value+128) / 512 * p_outpic->p[0].i_pitch;
190             *p_pixel = 0x9f;
191             p_pixel = p_outpic->p[1].p_pixels + (p_outpic->p[1].i_pitch * i_index) / SCOPE_WIDTH + p_outpic->p[1].i_lines * (u8)(i_value+128) / 512 * p_outpic->p[1].i_pitch;
192             *p_pixel = 0x00;
193             p_sample += 2;
194         }
195     }
196
197     /* Right channel */
198     for( i_index = 0, p_sample = (u16*)p_buffer + 1;
199          i_index < SCOPE_WIDTH && i_index < i_size / 2;
200          i_index++ )
201     {
202         int i;
203         u8 i_value = *p_sample / 256;
204
205         for( i = 0 ; i < 8 ; i++ )
206         {
207             p_pixel = p_outpic->p[0].p_pixels + (p_outpic->p[0].i_pitch * i_index) / SCOPE_WIDTH + (p_outpic->p[0].i_lines * (u8)(i_value+128) / 512 + p_outpic->p[0].i_lines / 2) * p_outpic->p[0].i_pitch;
208             *p_pixel = 0x7f;
209             p_pixel = p_outpic->p[2].p_pixels + (p_outpic->p[2].i_pitch * i_index) / SCOPE_WIDTH + (p_outpic->p[2].i_lines * (u8)(i_value+128) / 512 + p_outpic->p[2].i_lines / 2) * p_outpic->p[2].i_pitch;
210             *p_pixel = 0xdd;
211             p_sample += 2;
212         }
213     }
214
215     /* Display the picture */
216     vout_DatePicture( p_aout->p_sys->p_vout, p_outpic, p_aout->date );
217     vout_DisplayPicture( p_aout->p_sys->p_vout, p_outpic );
218 }
219
220 /*****************************************************************************
221  * aout_Close: close the Esound socket
222  *****************************************************************************/
223 static void aout_Close( aout_thread_t *p_aout )
224 {
225     vout_DestroyThread( p_aout->p_sys->p_vout, NULL );
226     free( p_aout->p_sys );
227 }
228