fix plugin probe when LANG != en
[goodguy/history.git] / cinelerra-5.0 / cinelerra / pluginserver.C
index a57da8658c25da747ab6601738fa793df1fe183f..25573cf4b95986e61e61ae4ec3af2af501f73567 100644 (file)
 #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"
@@ -40,6 +42,7 @@
 #include "plugin.h"
 #include "pluginaclient.h"
 #include "pluginaclientlad.h"
+#include "pluginfclient.h"
 #include "pluginclient.h"
 #include "plugincommands.h"
 #include "pluginserver.h"
@@ -48,6 +51,7 @@
 #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*>;
 
@@ -117,7 +126,6 @@ PluginServer::PluginServer(PluginServer &that)
        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;
@@ -126,11 +134,13 @@ PluginServer::PluginServer(PluginServer &that)
 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
@@ -141,11 +151,11 @@ int PluginServer::reset_parameters()
        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;
@@ -161,14 +171,12 @@ int PluginServer::reset_parameters()
        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()
 {
@@ -217,15 +225,18 @@ int PluginServer::get_lad_index()
 
 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()
@@ -242,8 +253,7 @@ int PluginServer::get_synthesis()
 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)
@@ -260,11 +270,36 @@ 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
@@ -278,57 +313,54 @@ int PluginServer::open_plugin(int master,
        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.
@@ -390,33 +422,30 @@ void PluginServer::render_stop()
                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,
@@ -501,14 +530,19 @@ void PluginServer::process_buffer(VFrame **frame,
                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)
        {
@@ -631,6 +665,10 @@ int PluginServer::get_parameters(int64_t start, int64_t end, int channels)
        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();
 }
 
@@ -773,6 +811,7 @@ int PluginServer::read_frame(VFrame *buffer,
 // 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;
@@ -1168,38 +1207,60 @@ Theme* PluginServer::get_theme()
 }
 
 
-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;
        }