Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

plugin.c

00001 /*****************************************************************************
00002  * plugin.c:
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: plugin.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet <[email protected]>
00008  *          Implementation of the winamp plugin MilkDrop
00009  *          based on projectM http://xmms-projectm.sourceforge.net
00010  *          and SciVi http://xmms-scivi.sourceforge.net
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028  * Preamble
00029  *****************************************************************************/
00030 
00031 #include "plugin.h"
00032 #include "main.h"
00033 #include "PCM.h"
00034 #include "video_init.h"
00035 #include <GL/glu.h>
00036 
00037 #include <vlc/input.h>
00038 #include <vlc/vout.h>
00039 #include "aout_internal.h"
00040 
00041 /*****************************************************************************
00042  * Module descriptor
00043  *****************************************************************************/
00044 static int  Open         ( vlc_object_t * );
00045 static void Close        ( vlc_object_t * );
00046 
00047 vlc_module_begin();
00048     set_description( _("GaLaktos visualization plugin") );
00049     set_capability( "visualization", 0 );
00050     set_callbacks( Open, Close );
00051     add_shortcut( "galaktos" );
00052 vlc_module_end();
00053 
00054 /*****************************************************************************
00055  * Local prototypes
00056  *****************************************************************************/
00057 typedef struct aout_filter_sys_t
00058 {
00059     galaktos_thread_t *p_thread;
00060 
00061 } aout_filter_sys_t;
00062 
00063 static void DoWork   ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
00064                        aout_buffer_t * );
00065 
00066 static void Thread   ( vlc_object_t * );
00067 
00068 static char *TitleGet( vlc_object_t * );
00069 
00070 
00071 extern GLuint RenderTargetTextureID;
00072 
00073 /*****************************************************************************
00074  * Open: open a scope effect plugin
00075  *****************************************************************************/
00076 static int Open( vlc_object_t *p_this )
00077 {
00078     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
00079     aout_filter_sys_t *p_sys;
00080     galaktos_thread_t *p_thread;
00081 
00082     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' )
00083          || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
00084     {
00085         msg_Warn( p_filter, "Bad input or output format" );
00086         return VLC_EGENERIC;
00087     }
00088     if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) )
00089     {
00090         msg_Warn( p_filter, "input and output formats are not similar" );
00091         return VLC_EGENERIC;
00092     }
00093 
00094     p_filter->pf_do_work = DoWork;
00095     p_filter->b_in_place = 1;
00096 
00097     /* Allocate structure */
00098     p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) );
00099 
00100     /* Create galaktos thread */
00101     p_sys->p_thread = p_thread =
00102         vlc_object_create( p_filter, sizeof( galaktos_thread_t ) );
00103     vlc_object_attach( p_thread, p_this );
00104 
00105 /*
00106     var_Create( p_thread, "galaktos-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00107     var_Get( p_thread, "galaktos-width", &width );
00108     var_Create( p_thread, "galaktos-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
00109     var_Get( p_thread, "galaktos-height", &height );
00110 */
00111     p_thread->i_cur_sample = 0;
00112     bzero( p_thread->p_data, 2*2*512 );
00113 
00114     p_thread->i_width = 600;
00115     p_thread->i_height = 600;
00116     p_thread->b_fullscreen = 0;
00117     galaktos_init( p_thread );
00118 
00119     p_thread->i_channels = aout_FormatNbChannels( &p_filter->input );
00120 
00121     p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) );
00122 
00123     if( vlc_thread_create( p_thread, "galaktos update thread", Thread,
00124                            VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00125     {
00126         msg_Err( p_filter, "cannot lauch galaktos thread" );
00127         if( p_thread->psz_title ) free( p_thread->psz_title );
00128         vlc_object_detach( p_thread );
00129         vlc_object_destroy( p_thread );
00130         free( p_sys );
00131         return VLC_EGENERIC;
00132     }
00133 
00134     return VLC_SUCCESS;
00135 }
00136 
00137 /*****************************************************************************
00138  * float to s16 conversion
00139  *****************************************************************************/
00140 static inline int16_t FloatToInt16( float f )
00141 {
00142     if( f >= 1.0 )
00143         return 32767;
00144     else if( f < -1.0 )
00145         return -32768;
00146     else
00147         return (int16_t)( f * 32768.0 );
00148 }
00149 
00150 /*****************************************************************************
00151  * DoWork: process samples buffer
00152  *****************************************************************************
00153  * This function queues the audio buffer to be processed by the galaktos thread
00154  *****************************************************************************/
00155 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
00156                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
00157 {
00158     int i_samples;
00159     int i_channels;
00160     float *p_float;
00161     galaktos_thread_t *p_thread = p_filter->p_sys->p_thread;
00162 
00163     p_float = (float *)p_in_buf->p_buffer;
00164     i_channels = p_thread->i_channels;
00165 
00166     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
00167     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes;
00168 
00169     for( i_samples = p_in_buf->i_nb_samples; i_samples > 0; i_samples-- )
00170     {
00171         int i_cur_sample = p_thread->i_cur_sample;
00172 
00173         p_thread->p_data[0][i_cur_sample] = FloatToInt16( p_float[0] );
00174         if( i_channels > 1 )
00175         {
00176             p_thread->p_data[1][i_cur_sample] = FloatToInt16( p_float[1] );
00177         }
00178         p_float += i_channels;
00179 
00180         if( ++(p_thread->i_cur_sample) == 512 )
00181         {
00182             addPCM( p_thread->p_data );
00183             p_thread->i_cur_sample = 0;
00184         }
00185     }
00186 }
00187 
00188 /*****************************************************************************
00189  * Thread:
00190  *****************************************************************************/
00191 static void Thread( vlc_object_t *p_this )
00192 {
00193     galaktos_thread_t *p_thread = (galaktos_thread_t*)p_this;
00194 
00195     int count=0;
00196     double realfps=0,fpsstart=0;
00197     int timed=0;
00198     int timestart=0;
00199     int mspf=0;
00200 
00201     /* Get on OpenGL provider */
00202     p_thread->p_opengl =
00203         (vout_thread_t *)vlc_object_create( p_this, VLC_OBJECT_OPENGL );
00204     if( p_thread->p_opengl == NULL )
00205     {
00206         msg_Err( p_thread, "out of memory" );
00207         return;
00208     }
00209     vlc_object_attach( p_thread->p_opengl, p_this );
00210 
00211     p_thread->p_opengl->i_window_width = p_thread->i_width;
00212     p_thread->p_opengl->i_window_height = p_thread->i_height;
00213     p_thread->p_opengl->render.i_width = p_thread->i_width;
00214     p_thread->p_opengl->render.i_height = p_thread->i_width;
00215     p_thread->p_opengl->render.i_aspect = VOUT_ASPECT_FACTOR;
00216     p_thread->p_opengl->b_scale = VLC_TRUE;
00217 
00218     p_thread->p_module =
00219         module_Need( p_thread->p_opengl, "opengl provider", NULL, 0 );
00220     if( p_thread->p_module == NULL )
00221     {
00222         msg_Err( p_thread, "No OpenGL provider found" );
00223         vlc_object_detach( p_thread->p_opengl );
00224         vlc_object_destroy( p_thread->p_opengl );
00225         return;
00226     }
00227 
00228     p_thread->p_opengl->pf_init( p_thread->p_opengl );
00229 
00230     setup_opengl( p_thread->i_width, p_thread->i_height );
00231     CreateRenderTarget(512, &RenderTargetTextureID, NULL);
00232 
00233     timestart=mdate()/1000;
00234 
00235     while( !p_thread->b_die )
00236     {
00237         mspf = 1000 / 60;
00238         if( galaktos_update( p_thread ) == 1 )
00239         {
00240             p_thread->b_die = 1;
00241         }
00242         if( p_thread->psz_title )
00243         {
00244             free( p_thread->psz_title );
00245             p_thread->psz_title = NULL;
00246         }
00247 
00248         if (++count%100==0)
00249         {
00250             realfps=100/((mdate()/1000-fpsstart)/1000);
00251  //           printf("%f\n",realfps);
00252             fpsstart=mdate()/1000;
00253         }
00254         //framerate limiter
00255         timed=mspf-(mdate()/1000-timestart);
00256       //   printf("%d,%d\n",time,mspf);
00257         if (timed>0) msleep(1000*timed);
00258     //     printf("Limiter %d\n",(mdate()/1000-timestart));
00259         timestart=mdate()/1000;
00260     }
00261 
00262     /* Free the openGL provider */
00263     module_Unneed( p_thread->p_opengl, p_thread->p_module );
00264     vlc_object_detach( p_thread->p_opengl );
00265     vlc_object_destroy( p_thread->p_opengl );
00266 }
00267 
00268 /*****************************************************************************
00269  * Close: close the plugin
00270  *****************************************************************************/
00271 static void Close( vlc_object_t *p_this )
00272 {
00273     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
00274     aout_filter_sys_t *p_sys = p_filter->p_sys;
00275 
00276     /* Stop galaktos Thread */
00277     p_sys->p_thread->b_die = VLC_TRUE;
00278 
00279     galaktos_done( p_sys->p_thread );
00280 
00281     vlc_thread_join( p_sys->p_thread );
00282 
00283     /* Free data */
00284     vlc_object_detach( p_sys->p_thread );
00285     vlc_object_destroy( p_sys->p_thread );
00286 
00287     free( p_sys );
00288 }
00289 
00290 static char *TitleGet( vlc_object_t *p_this )
00291 {
00292     char *psz_title = NULL;
00293     input_thread_t *p_input =
00294         vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
00295 
00296     if( p_input )
00297     {
00298         char *psz = strrchr( p_input->input.p_item->psz_uri, '/' );
00299 
00300         if( psz )
00301         {
00302             psz++;
00303         }
00304         else
00305         {
00306             psz = p_input->input.p_item->psz_uri;
00307         }
00308         if( psz && *psz )
00309         {
00310             psz_title = strdup( psz );
00311         }
00312         vlc_object_release( p_input );
00313     }
00314 
00315     return psz_title;
00316 }

Generated on Tue Dec 20 10:14:59 2005 for vlc-0.8.4a by  doxygen 1.4.2