#include "autoconf.h"
#include "bcsignals.h"
#include "cplayback.h"
+#include "cstrdup.h"
#include "cwindow.h"
#include "edl.h"
#include "edlsession.h"
#include "floatautos.h"
+#include "format.inc"
#include "keyframes.h"
#include "localsession.h"
#include "mainerror.h"
#include "plugin.h"
#include "pluginaclient.h"
#include "pluginaclientlad.h"
+#include "pluginfclient.h"
#include "pluginclient.h"
#include "plugincommands.h"
#include "pluginserver.h"
#include "samples.h"
#include "sema.h"
#include "mainsession.h"
+#include "theme.h"
#include "trackcanvas.h"
#include "transportque.h"
#include "vdevicex11.h"
#include <sys/mman.h>
-PluginServer::PluginServer()
+void PluginServer::init()
{
reset_parameters();
+ this->plugin_type = PLUGIN_TYPE_UNKNOWN;
+ plugin_obj = new PluginObj();
modules = new ArrayList<Module*>;
nodes = new ArrayList<VirtualNode*>;
}
-PluginServer::PluginServer(char *path, MWindow *mwindow)
+PluginServer::PluginServer()
{
- reset_parameters();
- set_path(path);
- modules = new ArrayList<Module*>;
- nodes = new ArrayList<VirtualNode*>;
- this->mwindow = mwindow;
+ init();
}
-PluginServer::PluginServer(PluginServer &that)
+PluginServer::PluginServer(MWindow *mwindow, char *path, int type)
{
- reset_parameters();
-
- if(that.title)
- {
- title = new char[strlen(that.title) + 1];
- strcpy(title, that.title);
- }
-
- if(that.path)
- {
- path = new char[strlen(that.path) + 1];
- strcpy(path, that.path);
+ char fpath[BCTEXTLEN];
+ init();
+ this->plugin_type = type;
+ this->mwindow = mwindow;
+ if( type == PLUGIN_TYPE_FFMPEG ) {
+ ff_name = cstrdup(path);
+ sprintf(fpath, "ff_%s", path);
+ path = fpath;
}
+ set_path(path);
+}
+PluginServer::PluginServer(PluginServer &that)
+{
+ reset_parameters();
+ plugin_type = that.plugin_type;
+ plugin_obj = that.plugin_obj;
+ plugin_obj->add_user();
+ title = !that.title ? 0 : cstrdup(that.title);
+ path = !that.path ? 0 : cstrdup(that.path);
+ ff_name = !that.ff_name ? 0 : cstrdup(that.ff_name);
modules = new ArrayList<Module*>;
nodes = new ArrayList<VirtualNode*>;
keyframe = that.keyframe;
new_plugin = that.new_plugin;
- is_lad = that.is_lad;
lad_descriptor = that.lad_descriptor;
lad_descriptor_function = that.lad_descriptor_function;
lad_index = that.lad_index;
PluginServer::~PluginServer()
{
close_plugin();
- if(path) delete [] path;
- if(title) delete [] title;
- if(modules) delete modules;
- if(nodes) delete nodes;
- if(picon) delete picon;
+ delete [] path;
+ delete [] ff_name;
+ delete [] title;
+ delete modules;
+ delete nodes;
+ delete picon;
+ plugin_obj->remove_user();
}
// Done only once at creation
prompt = 0;
cleanup_plugin();
autos = 0;
- plugin = 0;
edl = 0;
preferences = 0;
title = 0;
path = 0;
+ ff_name = 0;
audio = video = theme = 0;
fileio = 0;
uses_gui = 0;
nodes = 0;
picon = 0;
- is_lad = 0;
lad_index = -1;
lad_descriptor_function = 0;
lad_descriptor = 0;
return 0;
}
-
// Done every time the plugin is opened or closed
int PluginServer::cleanup_plugin()
{
int PluginServer::is_ladspa()
{
- return is_lad;
+ return plugin_type == PLUGIN_TYPE_LADSPA ? 1 : 0;
}
-int PluginServer::set_path(char *path)
+int PluginServer::is_ffmpeg()
{
- if(this->path) delete [] this->path;
- this->path = new char[strlen(path) + 1];
- strcpy(this->path, path);
- return 0;
+ return plugin_type == PLUGIN_TYPE_FFMPEG ? 1 : 0;
+}
+
+void PluginServer::set_path(const char *path)
+{
+ delete [] this->path;
+ this->path = cstrdup(path);
}
char* PluginServer::get_path()
void PluginServer::set_title(const char *string)
{
if(title) delete [] title;
- title = new char[strlen(string) + 1];
- strcpy(title, string);
+ title = cstrdup(string);
}
void PluginServer::generate_display_title(char *string)
strcpy(string, ltitle);
}
-void PluginServer::delete_this()
+void *PluginObj::load(const char *plugin_dir, const char *path)
+{
+ char dlpath[BCTEXTLEN], *dp = dlpath;
+ const char *cp = path;
+ if( *cp != '/' ) {
+ const char *bp = plugin_dir;
+ while( *bp ) *dp++ = *bp++;
+ *dp++ = '/';
+ }
+ while( *cp ) *dp++ = *cp++;
+ *dp = 0;
+ return dlobj = load(dlpath);
+}
+
+int PluginServer::load_obj()
{
- void *dlp = load_obj();
- delete this;
- unload_obj(dlp);
+ void *obj = plugin_obj->obj();
+ if( !obj ) obj =plugin_obj->load(preferences->plugin_dir, path);
+ return obj ? 1 : 0;
+}
+
+const char *PluginServer::load_error()
+{
+ return plugin_obj->load_error();
+}
+
+void *PluginServer::get_sym(const char *sym)
+{
+ if( !plugin_obj->obj() ) return 0;
+ return plugin_obj->load_sym(sym);
}
// Open plugin for signal processing
this->preferences = preferences;
this->plugin = plugin;
this->edl = edl;
- if( !load_obj() ) {
- // add base path if not absolute path
- char dl_path[BCTEXTLEN], *dp = dl_path;
- char *cp = path;
- if( *cp != '/' ) {
- char *bp = preferences->plugin_dir;
- while( *bp ) *dp++ = *bp++;
- *dp++ = '/';
- }
- while( *cp ) *dp++ = *cp++;
- *dp = 0;
- if( !load_obj(dl_path) ) {
-// If the load failed it may still be an executable tool for a specific
-// file format, in which case we just store the path.
- set_title(path);
- char string[BCTEXTLEN];
- strcpy(string, load_error());
- if(!strstr(string, "executable"))
- eprintf("PluginServer::open_plugin: load_obj failure = %s\n", string);
- return PLUGINSERVER_NOT_RECOGNIZED;
- }
+ if( plugin_type != PLUGIN_TYPE_FFMPEG && plugin_type != PLUGIN_TYPE_EXECUTABLE && !load_obj() ) {
+// If the load failed, can't use error to detect executable
+// because locale and language selection change the load_error()
+// if( !strstr(string, "executable") ) { set_title(path); plugin_type = PLUGIN_TYPE_EXECUTABLE; }
+ eprintf("PluginServer::open_plugin: load_obj %s = %s\n", path, load_error());
+ return PLUGINSERVER_NOT_RECOGNIZED;
}
- if( !new_plugin && !lad_descriptor ) {
+ if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_BUILTIN ) {
new_plugin =
- (PluginClient* (*)(PluginServer*)) load_sym("new_plugin");
- if( !new_plugin ) {
- lad_descriptor_function =
- (LADSPA_Descriptor_Function) load_sym("ladspa_descriptor");
- if(!lad_descriptor_function) {
- fprintf(stderr, "PluginServer::open_plugin "
- " %d: new_plugin undefined in %s\n", __LINE__, path);
- unload_obj();
- return PLUGINSERVER_NOT_RECOGNIZED;
- }
- if( lad_index < 0 ) {
- unload_obj();
- return PLUGINSERVER_IS_LAD;
- }
+ (PluginClient* (*)(PluginServer*)) get_sym("new_plugin");
+ if( new_plugin )
+ plugin_type = PLUGIN_TYPE_BUILTIN;
+ }
+ if( plugin_type == PLUGIN_TYPE_UNKNOWN || plugin_type == PLUGIN_TYPE_LADSPA ) {
+ lad_descriptor_function =
+ (LADSPA_Descriptor_Function) get_sym("ladspa_descriptor");
+ if( lad_descriptor_function ) {
+ if( lad_index < 0 ) return PLUGINSERVER_IS_LAD;
lad_descriptor = lad_descriptor_function(lad_index);
- if(!lad_descriptor) {
- unload_obj();
+ if( !lad_descriptor )
return PLUGINSERVER_NOT_RECOGNIZED;
- }
- is_lad = 1;
+ plugin_type = PLUGIN_TYPE_LADSPA;
}
}
-
- client = is_lad ?
- (PluginClient *) new PluginAClientLAD(this) :
- new_plugin(this);
-
+ if( plugin_type == PLUGIN_TYPE_UNKNOWN ) {
+ fprintf(stderr, "PluginServer::open_plugin "
+ " %d: plugin undefined in %s\n", __LINE__, path);
+ return PLUGINSERVER_NOT_RECOGNIZED;
+ }
+ switch( plugin_type ) {
+ case PLUGIN_TYPE_EXECUTABLE:
+ return PLUGINSERVER_OK;
+ case PLUGIN_TYPE_BUILTIN:
+ client = new_plugin(this);
+ break;
+ case PLUGIN_TYPE_LADSPA:
+ client = new PluginAClientLAD(this);
+ break;
+ case PLUGIN_TYPE_FFMPEG:
+ client = new_ffmpeg_plugin();
+ break;
+ default:
+ client = 0;
+ break;
+ }
+ if( !client )
+ return PLUGINSERVER_NOT_RECOGNIZED;
+
// Run initialization functions
realtime = client->is_realtime();
// Don't load defaults when probing the directory.
client->render_stop();
}
-void PluginServer::write_table(FILE *fp, int idx)
+void PluginServer::write_table(FILE *fp, const char *path, int idx, int64_t mtime)
{
if(!fp) return;
- fprintf(fp, "\"%s\" \"%s\" %d %d %d %d %d %d %d %d %d %d %d %d\n",
- path, title, idx, audio, video, theme, realtime, fileio,
- uses_gui, multichannel, synthesis, transition, is_lad, lad_index);
+ fprintf(fp, "%d \"%s\" \"%s\" " _LD " %d %d %d %d %d %d %d %d %d %d %d\n",
+ plugin_type, path, title, mtime, idx, audio, video, theme, realtime,
+ fileio, uses_gui, multichannel, synthesis, transition, lad_index);
}
-char *PluginServer::table_quoted_field(char *&sp)
+int PluginServer::scan_table(char *text, int &type, char *path, char *title, int64_t &mtime)
{
- char *cp = sp;
- while( *cp && (*cp == ' ' || *cp == '\t') ) ++cp;
- if( *cp++ != '"' ) return 0;
- char *bp = cp;
- while( *cp && *cp != '"' ) ++cp;
- if( *cp != '"' ) return 0;
- *cp++ = 0; sp = cp;
- return bp;
+ int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" " _LD "", &type, path, title, &mtime);
+ return n < 4 ? 1 : 0;
}
int PluginServer::read_table(char *text)
{
- int n = sscanf(text, "%d %d %d %d %d %d %d %d %d %d %d %d",
- &dir_idx, &audio, &video, &theme, &realtime, &fileio, &uses_gui,
- &multichannel, &synthesis, &transition, &is_lad, &lad_index);
-
- return n == 12 ? 0 : 1;
+ char path[BCTEXTLEN], title[BCTEXTLEN];
+ int64_t mtime;
+ int n = sscanf(text, "%d \"%[^\"]\" \"%[^\"]\" " _LD " %d %d %d %d %d %d %d %d %d %d %d",
+ &plugin_type, path, title, &mtime, &dir_idx, &audio, &video, &theme, &realtime,
+ &fileio, &uses_gui, &multichannel, &synthesis, &transition, &lad_index);
+ if( n != 15 ) return 1;
+ set_title(title);
+ return 0;
}
int PluginServer::init_realtime(int realtime_sched,
vclient->input[i] = frame[i];
vclient->output[i] = frame[i];
}
- vclient->source_start = (int64_t)(plugin ?
- plugin->startproject *
- frame_rate /
- vclient->project_frame_rate :
- 0);
+
+ if(plugin)
+ {
+ vclient->source_start = (int64_t)plugin->startproject *
+ frame_rate /
+ vclient->project_frame_rate;
+ }
vclient->direction = direction;
+//PRINT_TRACE
+//printf("plugin=%p source_start=%ld\n", plugin, vclient->source_start);
+
vclient->begin_process_buffer();
if(multichannel)
{
client->source_start = start;
client->total_len = end - start;
client->total_in_buffers = channels;
+
+//PRINT_TRACE
+//printf(" source_start=%ld total_len=%ld\n", client->source_start, client->total_len);
+
return client->plugin_get_parameters();
}
// If we're a VirtualNode, read_data in the virtual plugin node handles
// backward propogation and produces the data.
// If we're a Module, render in the module produces the data.
+//PRINT_TRACE
int result = -1;
if(!multichannel) channel = 0;
}
-char *PluginServer::get_plugin_png_path(char *png_path)
+int PluginServer::get_theme_png_path(char *png_path, const char *theme_dir)
{
- char *bp = strrchr(path, '/'), *cp = png_path;
+ char *bp = strrchr(path, '/');
if( !bp ) bp = path; else ++bp;
char *sp = strrchr(bp,'.');
if( !sp || ( strcmp(sp, ".plugin") && strcmp(sp,".so") ) ) return 0;
- cp += sprintf(cp,"%s/picons/", mwindow->preferences->plugin_dir);
- while( bp < sp ) *cp++ = *bp++;
+ char *cp = png_path, *dp = bp;
+ cp += sprintf(cp,"%s/%s/", mwindow->preferences->plugin_dir, theme_dir);
+ while( dp < sp ) *cp++ = *dp++;
strcpy(cp, ".png");
- return png_path;
+ struct stat st;
+ if( stat(png_path, &st) ) return 0;
+ if( !S_ISREG(st.st_mode) ) return 0;
+ if( st.st_size == 0 ) return 0;
+ return st.st_size;
+}
+
+int PluginServer::get_theme_png_path(char *png_path, Theme *theme)
+{
+ char *bp = strrchr(theme->path, '/');
+ if( !bp ) bp = theme->path; else ++bp;
+ char *sp = strrchr(bp,'.');
+ if( !sp || ( strcmp(sp, ".plugin") && strcmp(sp,".so") ) ) return 0;
+ char theme_dir[BCTEXTLEN], *cp = theme_dir;
+ while( bp < sp ) *cp++ = *bp++;
+ *cp = 0;
+ return get_theme_png_path(png_path, theme_dir);
+}
+
+int PluginServer::get_plugin_png_path(char *png_path)
+{
+ int len = get_theme_png_path(png_path, mwindow->theme);
+ if( !len )
+ len = get_theme_png_path(png_path, "picon");
+ return len;
}
VFrame *PluginServer::get_plugin_images()
{
char png_path[BCTEXTLEN];
- if( !get_plugin_png_path(png_path) ) return 0;
- struct stat st;
- if( stat(png_path, &st) ) return 0;
- if( !S_ISREG(st.st_mode) ) return 0;
- if( st.st_size == 0 ) return 0;
- unsigned len = st.st_size;
+ int len = get_plugin_png_path(png_path);
+ if( !len ) return 0;
int ret = 0, w = 0, h = 0;
- uint8_t *bfr = 0;
+ unsigned char *bfr = 0;
int fd = ::open(png_path, O_RDONLY);
if( fd < 0 ) ret = 1;
if( !ret ) {
- bfr = (uint8_t*) ::mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ bfr = (unsigned char *) ::mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0);
if( bfr == MAP_FAILED ) ret = 1;
}
VFrame *vframe = 0;
if( !ret ) {
- vframe = new VFrame(bfr, st.st_size);
+ double scale = BC_WindowBase::get_resources()->icon_scale;
+ vframe = new VFramePng(bfr, len, scale, scale);
if( (w=vframe->get_w()) <= 0 || (h=vframe->get_h()) <= 0 ||
vframe->get_data() == 0 ) ret = 1;
}