Files
veejay/veejay-current/veejay-server/libvje/plugload.c
2014-11-22 20:49:06 +01:00

1016 lines
25 KiB
C

/*
* Copyright (C) 2002-2006 Niels Elburg <nwelburg@gmail.com>
*
* This program is free software you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/*
Plugin Loader
* FreeFrame
* frei0r
* Livido (pending)
*/
/*
inspired by http://onsight.id.gu.se/~gabor/
http://www.gephex.org/
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <libhash/hash.h>
#include <libvjmsg/vj-msg.h>
#include <libvjmem/vjmem.h>
#include <libvevo/vevo.h>
#include <libvje/vje.h>
#include <libvevo/libvevo.h>
#include <libyuv/yuvconv.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libvevo/vevo.h>
#include <libvje/plugload.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <dirent.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define LINUX 1
#include <libvje/specs/FreeFrame.h>
#include <libvje/specs/frei0r.h>
#define V_BITS 24
#include <assert.h>
#define livido_port_t vevo_port_t
typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height);
typedef void (*f0r_destruct_f)(f0r_instance_t instance);
typedef void (*f0r_deinit_f)(void);
typedef int (*f0r_init_f)(void);
typedef void (*f0r_get_plugin_info_f)(f0r_plugin_info_t *info);
typedef void (*f0r_get_param_info_f)(f0r_param_info_t *info, int param_index);
typedef void (*f0r_update_f)(f0r_instance_t instance, double time, const uint32_t *inframe, uint32_t *outframe);
typedef void (*f0r_update2_f)(f0r_instance_t instance, double time, const uint32_t *inframe1, const uint32_t *inframe2, const uint32_t *inframe3, uint32_t *outframe);
typedef void (*f0r_set_param_value_f)(f0r_instance_t *instance, f0r_param_t *param, int param_index);
#define VEVO_FF_PORT 10 // free frame port
#define VEVO_FF_PARAM_PORT 11 // free frame parameter port
#define VEVO_FR_PORT 20 // frei0r port
#define VEVO_FR_PARAM_PORT 21 // frei0r parameter port
//@@ missing specification on http://livido.dyne.org ! livido ignored for now
#define VEVO_LIVIDO_PORT 30 // livido port
#define VEVO_LIVIDO_PARAM_PORT 31 // livido parameter port
#define VEVO_ILLEGAL 100
#if (V_BITS == 32)
#define FF_CAP_V_BITS_VIDEO FF_CAP_32BITVIDEO
#elif (V_BITS == 24)
#define FF_CAP_V_BITS_VIDEO FF_CAP_24BITVIDEO
#else // V_BITS = 16
#define FF_CAP_V_BITS_VIDEO FF_CAP_16BITVIDEO
#endif
static void *convert_yuv = NULL;
static void *convert_rgb = NULL;
static vevo_port_t **index_map_ = NULL;
static vevo_port_t *illegal_plugins_ =NULL;
static int index_ = 0;
static void *buffer_ = NULL;
static void *buffer2_ = NULL;
static void *buffer_b_ = NULL;
static int base_width_ =0;
static int base_height_ =0;
static int n_ff_ = 0;
static int n_fr_ = 0;
static int n_lvd_ = 0;
static int select_f( const struct dirent *d )
{
return ( strstr( d->d_name, ".so" ) != NULL );
}
static int init_param_livido( void *port, int p, int hint )
{
return 0;
}
static void free_parameters( void *port, int n )
{
int i;
for ( i = 0; i < n ; i ++ )
{
char key[10];
void *param = NULL;
sprintf(key, "p%d", i );
vevo_property_get(port, key,0, param );
if( param )
vevo_port_free( param );
}
}
static int init_param_fr( void *port, int p, int hint)
{
void *parameter = vpn( VEVO_FR_PARAM_PORT );
int min = 0;
int max = 100;
int dv = 50;
int n_values = 0;
switch(hint)
{
case F0R_PARAM_DOUBLE:
n_values = 1;
break;
case F0R_PARAM_BOOL:
max = 1;
dv = 0;
n_values = 1;
break;
case F0R_PARAM_COLOR:
n_values = 3;
break;
case F0R_PARAM_POSITION:
n_values = 2;
break;
default:
break;
}
if( n_values > 0 )
{
int values[n_values];
int k;
for( k = 0; k < n_values; k ++ ) values[k] = 0;
vevo_property_set( parameter, "value", VEVO_ATOM_TYPE_INT, n_values, &values );
}
vevo_property_set( parameter, "value", VEVO_ATOM_TYPE_INT, 0, NULL );
vevo_property_set( parameter, "min", VEVO_ATOM_TYPE_INT,1, &min );
vevo_property_set( parameter, "max", VEVO_ATOM_TYPE_INT,1, &max );
vevo_property_set( parameter, "default", VEVO_ATOM_TYPE_INT,1, &dv );
vevo_property_set( parameter, "hint", VEVO_ATOM_TYPE_INT,1, &hint );
char key[20];
snprintf(key,20, "p%d", p );
vevo_property_set( port, key, VEVO_ATOM_TYPE_VOIDPTR, 1, &parameter );
return n_values;
}
static void* deal_with_livido( void *handle, char *name )
{
/* void *port = vevo_port_new( VEVO_LIVIDO_PORT );
char *plugin_name = NULL;
livido_setup_f livido_setup = dlsym( handle, "livido_setup" );
livido_setup_t setup[] = {
{ (void(*)()) vj_malloc },
{ (void(*)()) free },
{ (void(*)())memset },
{ (void(*)())memcpy },
{ (void(*)())vevo_port_new },
{ (void(*)())vevo_port_free },
{ (void(*)())vevo_property_set },
{ (void(*)())vevo_property_get },
{ (void(*)())vevo_property_num_elements },
{ (void(*)())vevo_property_atom_type },
{ (void(*)())vevo_property_element_size },
{ (void(*)())vevo_list_properties }
};
void *livido_plugin = livido_setup( setup, 100 );
if(!livido_plugin)
{
veejay_msg(VEEJAY_MSG_ERROR, "Error setting up '%s'",name );
vevo_port_free( port );
return NULL;
}
vevo_property_set( port, "lvd", LIVIDO_ATOM_TYPE_VOIDPTR, 1,&livido_plugin );
vevo_property_set( port, "handle", LIVIDO_ATOM_TYPE_VOIDPTR,1,&handle );
return port;
*/
return NULL;
}
static void* deal_with_fr( void *handle, char *name)
{
void *port = vpn( VEVO_FR_PORT );
f0r_init_f f0r_init = dlsym( handle, "f0r_init" );
if( f0r_init == NULL )
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror());
vevo_port_free( port );
return NULL;
}
f0r_deinit_f f0r_deinit = dlsym( handle, "f0r_deinit" );
if( f0r_deinit == NULL )
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror());
vevo_port_free( port );
return NULL;
}
f0r_get_plugin_info_f f0r_info = dlsym( handle, "f0r_get_plugin_info");
if( f0r_info == NULL )
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror());
vevo_port_free( port );
return NULL;
}
f0r_get_param_info_f f0r_param= dlsym( handle, "f0r_get_param_info" );
if( f0r_param == NULL )
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror());
vevo_port_free( port );
return NULL;
}
//@ gamble
void *f0r_construct = dlsym( handle, "f0r_construct" );
void *f0r_destruct = dlsym( handle, "f0r_destruct" );
void *processf = dlsym( handle, "f0r_update" );
// void *processm = dlsym( handle, "f0r_update2" );
void *set_params = dlsym( handle, "f0r_set_param_value" );
vevo_property_set( port, "handle", VEVO_ATOM_TYPE_VOIDPTR,1, &handle );
vevo_property_set( port, "init", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_init );
vevo_property_set( port, "deinit", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_deinit );
vevo_property_set( port, "info", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_info );
vevo_property_set( port, "parameters", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_param );
vevo_property_set( port, "construct", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_construct );
vevo_property_set( port, "destruct", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_destruct );
vevo_property_set( port, "process", VEVO_ATOM_TYPE_VOIDPTR, 1, &processf);
// vevo_property_set( port, "process_mix", VEVO_ATOM_TYPE_VOIDPTR, 1, &processm);
vevo_property_set( port, "set_params", VEVO_ATOM_TYPE_VOIDPTR,1,&set_params);
f0r_plugin_info_t finfo;
f0r_param_info_t pinfo;
memset( &finfo,0,sizeof(f0r_plugin_info_t));
memset( &pinfo,0,sizeof(f0r_param_info_t));
if( (*f0r_init)() == 0)
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': ", name);
vevo_port_free( port );
return NULL;
}
(*f0r_info)(&finfo);
if( finfo.frei0r_version != FREI0R_MAJOR_VERSION )
{
(*f0r_deinit)();
vevo_port_free(port);
return NULL;
}
int extra = 0;
//@ fixme
// if( finfo.plugin_type == F0R_PLUGIN_TYPE_MIXER2 )
// extra = 1;
int n_params = finfo.num_params;
int r_params = 0;
int p = 0;
for ( p = 0; p < n_params; p ++ )
{
(*f0r_param)(&pinfo,p);
r_params += init_param_fr( port, p, pinfo.type );
}
if( r_params > 8 )
r_params = 8;
char new_name[512];
sprintf(new_name, "Frei0r %s", finfo.name );
char *plug_x_name = strdup( new_name );
vevo_property_set( port, "n_params", VEVO_ATOM_TYPE_INT, 1, &r_params );
vevo_property_set( port, "f0r_p", VEVO_ATOM_TYPE_INT,1, &n_params );
vevo_property_set( port, "name", VEVO_ATOM_TYPE_STRING,1, &plug_x_name );
vevo_property_set( port, "mixer", VEVO_ATOM_TYPE_INT,1, &extra );
free(plug_x_name);
return port;
}
static void* deal_with_ff( void *handle, char *name )
{
void *port = vpn( VEVO_FF_PORT );
char *plugin_name = NULL;
plugMainType *q = (plugMainType*) dlsym( handle, "plugMain" );
if( q == NULL )
{
veejay_msg(VEEJAY_MSG_ERROR,"\tBorked FF plugin '%s': %s", name, dlerror());
vevo_port_free( port );
return NULL;
}
PlugInfoStruct *pis = (q(FF_GETINFO, NULL, 0)).PISvalue;
if ((q(FF_GETPLUGINCAPS, (LPVOID)FF_CAP_V_BITS_VIDEO, 0)).ivalue != FF_TRUE)
{
veejay_msg(VEEJAY_MSG_ERROR, "Unable to get capabilities for plugin %s",name );
vevo_port_free(port);
return NULL;
}
if (pis->APIMajorVersion < 1)
{
veejay_msg(VEEJAY_MSG_ERROR, "Cowardly refusing FF API version < 1.0" );
vevo_port_free(port);
return NULL;
}
char new_name[512];
sprintf(new_name, "FreeFrame %s", pis->pluginName );
plugin_name = strdup( new_name );
if ( (q(FF_INITIALISE, NULL, 0 )).ivalue == FF_FAIL )
{
veejay_msg(VEEJAY_MSG_ERROR, "Cannot call init()");
vevo_port_free(port);
if(plugin_name) free(plugin_name);
return NULL;
}
int n_params = q( FF_GETNUMPARAMETERS, NULL, 0 ).ivalue;
if( n_params == FF_FAIL )
{
veejay_msg(VEEJAY_MSG_ERROR, "Cannot get number of parameters");
vevo_port_free(port);
if(plugin_name) free(plugin_name);
return NULL;
}
void *base = (void*) q;
vevo_property_set( port, "handle", VEVO_ATOM_TYPE_VOIDPTR,1, &handle );
vevo_property_set( port, "name", VEVO_ATOM_TYPE_STRING,1, &plugin_name );
vevo_property_set( port, "base", VEVO_ATOM_TYPE_VOIDPTR, 1, &base );
vevo_property_set( port, "instance", VEVO_ATOM_TYPE_INT, 0, NULL );
vevo_property_set( port, "n_params", VEVO_ATOM_TYPE_INT, 1,&n_params );
int p;
for( p= 0; p < n_params; p ++ )
{
void *parameter = vpn( VEVO_FF_PARAM_PORT );
#ifdef STRICT_CHECKING
assert( parameter != NULL );
#endif
int type = q( FF_GETPARAMETERTYPE, (LPVOID) p, 0 ).ivalue;
// name, kind, flags, description, min,max,default,transition
vevo_property_set( parameter, "type", VEVO_ATOM_TYPE_INT, 1, &type);
int min = 0;
int max = 100;
if( type == FF_TYPE_BOOLEAN )
{
min = 0;
max = 1;
}
else if( type == FF_TYPE_TEXT )
{
min = 0;
max = 0;
}
vevo_property_set( parameter, "min", VEVO_ATOM_TYPE_INT,1, &min );
vevo_property_set( parameter, "max", VEVO_ATOM_TYPE_INT,1, &max );
float dvalue = 0.0;
dvalue = q( FF_GETPARAMETERDEFAULT, (LPVOID) p, 0).fvalue;
int ivalue = (int)(dvalue * 100.0);
vevo_property_set( parameter, "default", VEVO_ATOM_TYPE_INT,1 ,&ivalue );
char key[20];
snprintf(key,20, "p%d", p );
vevo_property_set( port, key, VEVO_ATOM_TYPE_VOIDPTR, 1, &parameter );
}
free(plugin_name);
return port;
}
static int instantiate_plugin( void *plugin, int w , int h )
{
int type = 0;
assert( plugin != NULL );
vevo_property_get( plugin, "type", 0, &type);
if( type == VEVO_FF_PORT )
{
VideoInfoStruct v;
v.frameWidth = w;
v.frameHeight = h;
v.orientation = 1;
v.bitDepth = FF_CAP_V_BITS_VIDEO;
void *base = NULL;
vevo_property_get( plugin, "base", 0, &base);
plugMainType *q = (plugMainType*) base;
void *instance = (void*) q( FF_INSTANTIATE, &v, 0).ivalue;
if( instance == (void*) FF_FAIL )
{
veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize plugin");
return 0;
}
vevo_property_set( plugin, "instance", VEVO_ATOM_TYPE_INT, 1, &instance );
return 1;
}
else if( type == VEVO_FR_PORT )
{
f0r_construct_f base;
vevo_property_get( plugin, "construct", 0, &base);
f0r_instance_t k = (*base)(w,h);
vevo_property_set(plugin, "instance", VEVO_ATOM_TYPE_VOIDPTR, 1, &k);
if( k == NULL )
veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize plugin");
// store instance running status
int state = 1;
vevo_property_set( plugin, "running", VEVO_ATOM_TYPE_INT, 1, &state );
return state;
}
else if ( type == VEVO_LIVIDO_PORT )
{
return 0;
}
return 0;
}
static void deinstantiate_plugin( void *plugin )
{
if(plugin == NULL)
return;
int type = 0;
assert( plugin != NULL);
vevo_property_get( plugin, "type", 0, &type);
if( type == VEVO_FF_PORT )
{
void *base = NULL;
vevo_property_get( plugin, "base", 0, &base);
plugMainType *q = (plugMainType*) base;
void *instance = NULL;
vevo_property_get( plugin, "instance", 0, &instance );
if( instance )
q( FF_DEINSTANTIATE, NULL, instance );
}
else if ( type == VEVO_FR_PORT )
{
int state = 0;
vevo_property_get( plugin, "state", 0, &state );
if(!state)
return;
f0r_destruct_f base;
vevo_property_get( plugin, "destruct", 0, &base);
f0r_instance_t instance;
vevo_property_get( plugin, "instance", 0, &instance );
(*base)(instance);
}
else if ( type == VEVO_LIVIDO_PORT )
{
}
}
static int is_so( const char *file )
{
if( strstr(file, ".so" ) || strstr( file, ".SO" ) )
return 1;
return 0;
}
static int is_valid_plugin( const char *file )
{
if(!file)
return 0;
struct stat l;
veejay_memset( &l, 0, sizeof( struct stat));
if ( lstat( file, &l ) < 0 )
return 0;
if( S_ISDIR( l.st_mode ))
return 0;
if( S_ISREG( l.st_mode ))
{
if( is_so(file) )
return 1;
}
return 0;
}
static void add_to_plugin_list( const char *path )
{
if(!path)
return;
int i;
char fullname[PATH_MAX];
struct dirent **files = NULL;
struct stat sbuf;
int res = 0;
memset( &sbuf,0 ,sizeof(struct stat));
res = stat( path, &sbuf );
if( res != 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "File or directory '%s' does not exist (skip)", path);
return;
}
if( S_ISREG( sbuf.st_mode ) )
{
vevo_property_set( illegal_plugins_, path, VEVO_ATOM_TYPE_STRING, 0, NULL );
return;
}
if( !S_ISDIR( sbuf.st_mode ) )
{
veejay_msg(VEEJAY_MSG_ERROR, "Not a directory : '%s'", path );
return;
}
int n_files = scandir( path, &files, select_f, alphasort );
if( n_files <= 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "No FF plugins found in %s", path );
return;
}
for( i = 0 ; i < n_files; i ++ )
{
char *name = files[i]->d_name;
if(!name)
continue;
if( vevo_property_get( illegal_plugins_, name, 0 , NULL ) == 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "'%s' marked as bad", name);
continue;
}
sprintf(fullname, "%s/%s", path,name );
//@ check if name is regular file
if( is_valid_plugin( fullname ) == 0 )
{
continue;
}
void *handle = dlopen(fullname, RTLD_NOW );
if(handle)
{
if(dlsym( handle, "plugMain" ))
{
void *plugin = deal_with_ff( handle, name );
if( plugin )
{
index_map_[ index_ ] = plugin;
index_ ++;
n_ff_ ++;
}
else
dlclose( handle );
}
else if (dlsym( handle, "f0r_construct" ))
{
void *plugin = deal_with_fr( handle, name );
if( plugin )
{
index_map_[ index_ ] = plugin;
index_ ++;
n_fr_ ++;
}
else
dlclose( handle );
}
else
dlclose(handle);
}
}
for( i = 0; i < n_files; i ++ )
free( files[i] );
free(files);
}
static void free_plugin(void *plugin)
{
if(plugin == NULL)
return;
int type = 0;
vevo_property_get( plugin, "type", 0, &type);
int n = 0;
if( type == VEVO_FF_PORT )
{
void *base = NULL;
vevo_property_get( plugin, "base", 0, &base);
plugMainType *q = (plugMainType*) base;
q( FF_DEINITIALISE, NULL, 0 );
vevo_property_get( plugin, "n_params", 0, &n );
}
else if ( type == VEVO_FR_PORT )
{
//@@ clear parameters
f0r_deinit_f base;
vevo_property_get( plugin, "deinit", 0, &base);
(*base)();
vevo_property_get( plugin, "f0r_p", 0, &n );
}
else if ( type == VEVO_LIVIDO_PORT )
{
}
free_parameters(plugin,n);
void *handle = NULL;
vevo_property_get( plugin, "handle", 0 , &handle );
if( handle ) dlclose( handle );
vevo_port_free( plugin );
}
static void free_plugins()
{
int i;
for( i = 0; i < index_ ; i ++ )
{
deinstantiate_plugin( index_map_[i] );
free_plugin( index_map_[i]);
}
free( index_map_ );
index_ = 0;
}
#define CONFIG_FILE_LEN 65535
static void scan_plugins()
{
char *home = getenv( "HOME" );
char path[PATH_MAX];
char data[CONFIG_FILE_LEN];
if(!home)
{
veejay_msg(VEEJAY_MSG_ERROR, "Environment variable HOME not set!");
return;
}
sprintf( path , "%s/.veejay/plugins.cfg" , home );
int fd = open( path, O_RDONLY );
if( fd < 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "Cant open %s", path);
return;
}
veejay_memset( data, 0, CONFIG_FILE_LEN );
if( read( fd, data, CONFIG_FILE_LEN ) > 0 )
{
int len = strlen(data);
int j;
int k = 0;
char value[PATH_MAX];
veejay_memset( value,0, PATH_MAX );
for( j=0; j < len; j ++ )
{
if(data[j] == '\0' )
break;
if( data[j] == '\n' )
{ add_to_plugin_list( value ); veejay_memset(value,0,PATH_MAX); k =0;}
if( isascii( data[j] ) && data[j] != '\n')
{ value[k] = data[j]; if( k < PATH_MAX) k ++; }
}
}
}
static void process_plug_x_plugin( void *plugin, void *buffer , void *out_buffer)
{
int type = 0;
vevo_property_get( plugin, "type", 0, &type);
if( type == VEVO_FF_PORT )
{
void *base = NULL;
vevo_property_get( plugin, "base", 0, &base);
plugMainType *q = (plugMainType*) base;
void *instance = NULL;
vevo_property_get( plugin, "instance",0, &instance );
q( FF_PROCESSFRAME, buffer, instance );
}
else if (type == VEVO_FR_PORT )
{
f0r_update_f base;
vevo_property_get( plugin, "process", 0, &base );
f0r_instance_t instance;
vevo_property_get( plugin, "instance",0, &instance );
(*base)( instance, rand(), buffer, out_buffer );
}
else if (type == VEVO_LIVIDO_PORT )
{
}
}
/* public IF */
void plug_x_free(void)
{
free_plugins();
if( convert_rgb )
yuv_fx_context_destroy( convert_rgb );
if( convert_yuv )
yuv_fx_context_destroy( convert_yuv );
if( buffer_ )
free( buffer_ );
if( buffer2_ )
free( buffer2_ );
if( buffer_b_)
free( buffer_b_ );
}
void plug_x_init( int w, int h )
{
buffer_ = (void*) vj_calloc( w * h * (V_BITS >> 3));
buffer2_ = (void*) vj_calloc( w * h * (V_BITS >> 3));
buffer_b_ = (void*) vj_calloc( w * h * (V_BITS >> 3));
base_width_ = w;
base_height_ = h;
}
int plug_x_detect_plugins(void)
{
index_map_ = (vevo_port_t**) vj_calloc(sizeof(vevo_port_t*) * 256 );
illegal_plugins_ = vpn( VEVO_ILLEGAL );
scan_plugins();
//@ display copyright notice in binary form
if(n_ff_ > 0 )
{
veejay_msg(VEEJAY_MSG_INFO, "FreeFrame Copyright (c) 2002, Marcus Clements www.freeframe.org. All Rights reserved.");
veejay_msg(VEEJAY_MSG_INFO, "http://freeframe.sourceforge.net");
veejay_msg(VEEJAY_MSG_INFO,"Loaded %d FreeFrame %s",
n_ff_ , n_ff_ == 1 ? "plugin" : "plugins" );
}
if(n_fr_ > 0 )
{
veejay_msg(VEEJAY_MSG_INFO, "frei0r - a minimalistic plugin API for video effects");
veejay_msg(VEEJAY_MSG_INFO, "http://www.piksel.org/frei0r");
veejay_msg(VEEJAY_MSG_INFO, "Loaded %d frei0r %s",
n_fr_ , n_fr_ == 1 ? "plugin" : "plugins" );
}
if(n_lvd_ > 0 )
{
veejay_msg(VEEJAY_MSG_INFO, "Livido - (Linux) Video Objects" );
veejay_msg(VEEJAY_MSG_INFO, "Loaded %d Livido %s",
n_lvd_, n_lvd_ == 1 ? "plugin" :"plugins" );
}
vevo_port_free( illegal_plugins_ );
return index_;
}
vj_effect *plug_x_get_plugin( int n )
{
vj_effect *vje = (vj_effect*) vj_calloc(sizeof(vj_effect));
vevo_port_t *port = index_map_[n];
size_t name_len = vevo_property_element_size( port, "name", 0 );
vje->description = (char*) vj_calloc( name_len );
vevo_property_get( port, "name", 0, &(vje->description));
vevo_property_get( port, "n_params", 0, &(vje->num_params));
vevo_property_get( port, "mixer", 0, &(vje->extra_frame));
if( vje->num_params > 0 )
{
if( vje->num_params > 8 )
{
veejay_msg(VEEJAY_MSG_WARNING, "%s has %d parameters, clip to 8",
vje->description, vje->num_params );
vje->num_params = 8;
}
vje->defaults = (int*) vj_calloc(sizeof(int) * vje->num_params );
vje->limits[0] = (int*) vj_calloc(sizeof(int) * vje->num_params );
vje->limits[1] = (int*) vj_calloc(sizeof(int) * vje->num_params );
int k = 0;
int valid_p = 0;
char **param_descr = NULL;
if( vje->num_params > 0 )
param_descr = (char**) vj_malloc(sizeof(char*) * vje->num_params );
for( k = 0; k < vje->num_params;k++ )
{
char key[20];
sprintf(key, "p%d", k );
void *parameter = NULL;
vevo_property_get( port, key, 0, &parameter );
if(parameter)
{
vevo_property_get( parameter, "min", 0, &(vje->limits[0][k]));
vevo_property_get( parameter, "max", 0, &(vje->limits[1][k]));
vevo_property_get( parameter, "default", 0,&(vje->defaults[k]));
param_descr[valid_p] = strdup( "Number" );
valid_p ++;
}
}
vevo_property_set( port, "n_params",VEVO_ATOM_TYPE_INT, 1,&valid_p);
vje->num_params = valid_p;
vje->param_description = param_descr;
}
return vje;
}
int plug_x_activate( int fx_id )
{
return instantiate_plugin( index_map_[fx_id], base_width_, base_height_ );
}
void plug_x_deactivate( int fx_id )
{
deinstantiate_plugin( index_map_[fx_id] );
}
void plug_x_control( int fx_id, int *args )
{
vevo_port_t *port = index_map_[ fx_id ];
int type = 0;
vevo_property_get( port, "type", 0, &type);
if( type == VEVO_FF_PORT )
{
SetParameterStruct v;
void *base = NULL;
vevo_property_get( port, "base", 0, &base);
plugMainType *q = (plugMainType*) base;
int p,num_params=0;
void *instance = NULL;
vevo_property_get( port, "n_params", 0, &num_params);
vevo_property_get( port, "instance", 0, &instance );
for( p = 0; p < num_params; p ++ )
{
v.value = ((float) args[p]) * 0.01;
v.index = p;
q( FF_SETPARAMETER, &v, instance );
}
}
else if ( type == VEVO_FR_PORT )
{
int p,num_params=0;
vevo_property_get( port, "n_params", 0, &num_params);
int v_params = 0;
f0r_set_param_value_f q;
vevo_property_get( port, "set_params", 0, &q);
for( p = 0; p < num_params; p ++ )
{
char key[20];
sprintf(key, "p%d", p );
void *param = NULL;
vevo_property_get( port, key, 0, &param );
if( param ) continue;
int n = vevo_property_element_size( param, "value", p );
f0r_param_position_t pos;
f0r_param_color_t col;
double value = 0.0;
//nt instance = 0;
void *instance = NULL;
vevo_property_get( port, "instance", 0, &instance );
int max = 0;
vevo_property_get( param, "max",0,&max);
void *fparam = NULL;
switch(n)
{
case 0:
case 1:
value = ( (double) args[v_params] * (max == 100 ? 0.01: 1));
fparam = &value;
v_params ++;
break;
case 2:
pos.x = ( (double) args[v_params] * 0.01 );
v_params ++;
pos.y = ( (double) args[v_params] * 0.01 );
v_params ++;
fparam = &pos;
break;
case 3:
col.r = ( (double) args[v_params] * 0.01 );
v_params ++;
col.g = ( (double) args[v_params] * 0.01 );
v_params ++;
col.b = ( (double) args[v_params] * 0.01 );
v_params ++;
fparam = &col;
break;
default:
break;
}
if( fparam )
(*q)( instance, fparam, p );
}
}
else if ( type == VEVO_LIVIDO_PORT )
{
}
}
void plug_x_process( VJFrame *frame,VJFrame *b, int fx_id, int src_fmt )
{
AVPicture p1,p2;
AVPicture o1,o2;
void *plugin = index_map_[fx_id];
int is_mix = 0;
vevo_property_get( plugin, "mixer", 0, &is_mix );
if( is_mix )
{
veejay_msg(0, "Not supporting mixing plugins yet");
return;
}
VJFrame *dst1 = yuv_rgb_template( buffer_, frame->width,frame->height,
PIX_FMT_RGB24 );
if(!convert_yuv)
convert_yuv = yuv_fx_context_create( frame,dst1,src_fmt,dst1->format );
if(!convert_rgb )
convert_rgb = yuv_fx_context_create( dst1, frame, dst1->format, src_fmt );
// yuv_convert_any_ac( frame, dst1, src_fmt, dst1->format );
yuv_fx_context_process( convert_yuv, frame,dst1 );
process_plug_x_plugin( plugin, buffer_, buffer2_ );
yuv_fx_context_process( convert_rgb, dst1, frame );
// yuv_convert_any_ac( dst1, frame, dst1->format, src_fmt );
free(dst1);
}