]> git.sesse.net Git - vlc/blob - modules/visualization/galaktos/plugin.c
c02b23c37d3f7040176bd93d1d7e7fc633c6bef6
[vlc] / modules / visualization / galaktos / plugin.c
1 /*****************************************************************************
2  * plugin.c:
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet <asmax@videolan.org>
8  *          Implementation of the winamp plugin MilkDrop
9  *          based on projectM http://xmms-projectm.sourceforge.net
10  *          and SciVi http://xmms-scivi.sourceforge.net
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30
31 #include "plugin.h"
32 #include "main.h"
33 #include "PCM.h"
34 #include "video_init.h"
35 #include <GL/glu.h>
36
37 #include <vlc_input.h>
38 #include <vlc_playlist.h>
39 #include <vlc_plugin.h>
40
41 /*****************************************************************************
42  * Module descriptor
43  *****************************************************************************/
44 static int  Open         ( vlc_object_t * );
45 static void Close        ( vlc_object_t * );
46
47
48 #define WIDTH_TEXT N_("Video width")
49 #define WIDTH_LONGTEXT N_("The width of the video window, in pixels.")
50
51 #define HEIGHT_TEXT N_("Video height")
52 #define HEIGHT_LONGTEXT N_("The height of the video window, in pixels.")
53
54
55 vlc_module_begin ()
56     set_description( N_("GaLaktos visualization") )
57     set_capability( "visualization", 0 )
58     set_callbacks( Open, Close )
59     add_shortcut( "galaktos" )
60     add_integer( "galaktos-width", 640, NULL, WIDTH_TEXT, WIDTH_LONGTEXT,
61                  false )
62     add_integer( "galaktos-height", 480, NULL, HEIGHT_TEXT, HEIGHT_LONGTEXT,
63                  false )
64 vlc_module_end ()
65
66 /*****************************************************************************
67  * Local prototypes
68  *****************************************************************************/
69 struct aout_filter_sys_t
70 {
71     galaktos_thread_t *p_thread;
72
73 };
74
75 static void DoWork   ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
76                        aout_buffer_t * );
77
78 static void* Thread   ( vlc_object_t * );
79
80 static char *TitleGet( vlc_object_t * );
81
82
83 extern GLuint RenderTargetTextureID;
84
85 /*****************************************************************************
86  * Open: open a scope effect plugin
87  *****************************************************************************/
88 static int Open( vlc_object_t *p_this )
89 {
90     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
91     aout_filter_sys_t *p_sys;
92     galaktos_thread_t *p_thread;
93
94     if( p_filter->input.i_format != VLC_CODEC_FL32 ||
95         p_filter->output.i_format != VLC_CODEC_FL32 )
96     {
97         msg_Warn( p_filter, "bad input or output format" );
98         return VLC_EGENERIC;
99     }
100     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
101     {
102         msg_Warn( p_filter, "input and output formats are not similar" );
103         return VLC_EGENERIC;
104     }
105
106     p_filter->pf_do_work = DoWork;
107     p_filter->b_in_place = 1;
108
109     /* Allocate structure */
110     p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) );
111
112     /* Create galaktos thread */
113     p_sys->p_thread = p_thread =
114         vlc_object_create( p_filter, sizeof( galaktos_thread_t ) );
115     vlc_object_attach( p_thread, p_this );
116
117     p_thread->i_cur_sample = 0;
118     bzero( p_thread->p_data, 2*2*512 );
119
120     p_thread->i_width = var_CreateGetInteger( p_thread, "galaktos-width" );
121     p_thread->i_height = var_CreateGetInteger( p_thread, "galaktos-height" );
122     p_thread->b_fullscreen = 0;
123     galaktos_init( p_thread );
124
125     p_thread->i_channels = aout_FormatNbChannels( &p_filter->input );
126
127     p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) );
128
129     if( vlc_thread_create( p_thread, "galaktos update thread", Thread,
130                            VLC_THREAD_PRIORITY_LOW ) )
131     {
132         msg_Err( p_filter, "cannot lauch galaktos thread" );
133         free( p_thread->psz_title );
134         vlc_object_detach( p_thread );
135         vlc_object_release( p_thread );
136         free( p_sys );
137         return VLC_EGENERIC;
138     }
139
140     return VLC_SUCCESS;
141 }
142
143 /*****************************************************************************
144  * float to s16 conversion
145  *****************************************************************************/
146 static inline int16_t FloatToInt16( float f )
147 {
148     if( f >= 1.0 )
149         return 32767;
150     else if( f < -1.0 )
151         return -32768;
152     else
153         return (int16_t)( f * 32768.0 );
154 }
155
156 /*****************************************************************************
157  * DoWork: process samples buffer
158  *****************************************************************************
159  * This function queues the audio buffer to be processed by the galaktos thread
160  *****************************************************************************/
161 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
162                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
163 {
164     int i_samples;
165     int i_channels;
166     float *p_float;
167     galaktos_thread_t *p_thread = p_filter->p_sys->p_thread;
168
169     p_float = (float *)p_in_buf->p_buffer;
170     i_channels = p_thread->i_channels;
171
172     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
173     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
174
175     for( i_samples = p_in_buf->i_nb_samples; i_samples > 0; i_samples-- )
176     {
177         int i_cur_sample = p_thread->i_cur_sample;
178
179         p_thread->p_data[0][i_cur_sample] = FloatToInt16( p_float[0] );
180         if( i_channels > 1 )
181         {
182             p_thread->p_data[1][i_cur_sample] = FloatToInt16( p_float[1] );
183         }
184         p_float += i_channels;
185
186         if( ++(p_thread->i_cur_sample) == 512 )
187         {
188             addPCM( p_thread->p_data );
189             p_thread->i_cur_sample = 0;
190         }
191     }
192 }
193
194 /*****************************************************************************
195  * Thread:
196  *****************************************************************************/
197 static void* Thread( vlc_object_t *p_this )
198 {
199     galaktos_thread_t *p_thread = (galaktos_thread_t*)p_this;
200
201     int count=0;
202     double realfps=0,fpsstart=0;
203     int timed=0;
204     int timestart=0;
205     int mspf=0;
206     int canc = vlc_savecancel ();
207
208     /* Get on OpenGL provider */
209     p_thread->p_opengl =
210         (vout_thread_t *)vlc_object_create( p_this, sizeof( vout_thread_t ) );
211     if( p_thread->p_opengl == NULL )
212     {
213         vlc_restorecancel (canc);
214         return NULL;
215     }
216     vlc_object_attach( p_thread->p_opengl, p_this );
217
218     /* Initialize vout parameters */
219     video_format_Setup( &p_thread->p_opengl->fmt_in,
220                         VLC_CODEC_RGB32, p_thread->i_width, p_thread->i_height, 1 );
221     p_thread->p_opengl->i_window_width = p_thread->i_width;
222     p_thread->p_opengl->i_window_height = p_thread->i_height;
223     p_thread->p_opengl->render.i_width = p_thread->i_width;
224     p_thread->p_opengl->render.i_height = p_thread->i_width;
225     p_thread->p_opengl->render.i_aspect = VOUT_ASPECT_FACTOR;
226     p_thread->p_opengl->b_fullscreen = false;
227     p_thread->p_opengl->i_alignment = 0;
228     p_thread->p_opengl->fmt_in.i_sar_num = 1;
229     p_thread->p_opengl->fmt_in.i_sar_den = 1;
230     p_thread->p_opengl->fmt_render = p_thread->p_opengl->fmt_in;
231
232     p_thread->p_module =
233         module_need( p_thread->p_opengl, "opengl provider", NULL, false );
234     if( p_thread->p_module == NULL )
235     {
236         msg_Err( p_thread, "unable to initialize OpenGL" );
237         vlc_object_detach( p_thread->p_opengl );
238         vlc_object_release( p_thread->p_opengl );
239         vlc_restorecancel (canc);
240         return NULL;
241     }
242
243     p_thread->p_opengl->pf_init( p_thread->p_opengl );
244
245     setup_opengl( p_thread->i_width, p_thread->i_height );
246     CreateRenderTarget(512, &RenderTargetTextureID, NULL);
247
248     timestart=mdate()/1000;
249
250     while( vlc_object_alive (p_thread) )
251     {
252         mspf = 1000 / 60;
253         if( galaktos_update( p_thread ) == 1 )
254         {
255             vlc_object_kill( p_thread );
256         }
257         free( p_thread->psz_title );
258         p_thread->psz_title = NULL;
259
260         mtime_t now = mdate();
261         if (++count%100==0)
262         {
263             realfps=100/((now/1000-fpsstart)/1000);
264  //           printf("%f\n",realfps);
265             fpsstart=now/1000;
266         }
267         //framerate limiter
268         timed=mspf-(now/1000-timestart);
269       //   printf("%d,%d\n",time,mspf);
270         if (timed>0) msleep(1000*timed);
271     //     printf("Limiter %d\n",(mdate()/1000-timestart));
272         timestart=mdate()/1000;
273     }
274
275     /* Free the openGL provider */
276     module_unneed( p_thread->p_opengl, p_thread->p_module );
277     vlc_object_detach( p_thread->p_opengl );
278     vlc_object_release( p_thread->p_opengl );
279     vlc_restorecancel (canc);
280     return NULL;
281 }
282
283 /*****************************************************************************
284  * Close: close the plugin
285  *****************************************************************************/
286 static void Close( vlc_object_t *p_this )
287 {
288     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
289     aout_filter_sys_t *p_sys = p_filter->p_sys;
290
291     /* Stop galaktos Thread */
292     vlc_object_kill( p_sys->p_thread );
293
294     galaktos_done( p_sys->p_thread );
295
296     vlc_thread_join( p_sys->p_thread );
297
298     /* Free data */
299     vlc_object_detach( p_sys->p_thread );
300     vlc_object_release( p_sys->p_thread );
301
302     free( p_sys );
303 }
304
305 static char *TitleGet( vlc_object_t *p_this )
306 {
307     char *psz_title = NULL;
308     input_thread_t *p_input =
309         vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
310
311     if( p_input )
312     {
313         char *psz_orig = input_item_GetURI( input_GetItem( p_input ) );
314         char *psz = strrchr( psz_orig, '/' );
315
316         if( psz )
317         {
318             psz++;
319         }
320         else
321         {
322             psz = psz_orig;
323         }
324         if( psz && *psz )
325         {
326             psz_title = strdup( psz );
327         }
328         free( psz_orig );
329         vlc_object_release( p_input );
330     }
331
332     return psz_title;
333 }