--- babelplugin.c.stock 2008-11-20 11:54:51.000000000 +0100 +++ babelplugin.c 2008-11-20 11:54:31.000000000 +0100 @@ -21,8 +21,16 @@ * * Convert files using Open Babel 1.100.2 * http://openbabel.sourceforge.net/babel.shtml + * + * Convert files using Open Babel 2.2.0 + * http://openbabel.org/ */ +// Starting with OpenBabel 2.2.0, you can use automatic detection: +#define USE_OPENBABEL_AUTODETECT +// Otherwise, we can rely on fixed versions of Babel or OpenBabel +//#define USE_BABEL_1_6 +//#define USE_OPENBABEL_1_100_2 #include #include @@ -303,6 +311,9 @@ static const char *openbabel11filetypena 0 }; +/* File types and plugin names registered for OpenBabel >= 2.2.0 */ +static char **openbabelfiletypenames, **openbabelfiletypes; + static const char *babel16type_from_name(const char *name) { const char **ptr = babel16filetypenames; @@ -328,6 +339,19 @@ static const char *openbabel11type_from_ return NULL; } +static const char *openbabeltype_from_name(const char *name) { + const char **ptr = openbabelfiletypenames; + int i=0; + printf ("openbabeltype_from_name: %s\n", name); + while (*ptr) { + if (!strcmp(*ptr, name)) + return openbabelfiletypes[i]; + ptr++; + i++; + } + return NULL; +} + /* * Figure out the file type, call babel, and return a handle if successful. @@ -352,26 +376,35 @@ static void *open_babel_read(const char const char *filetype; babelbin = getenv("VMDBABELBIN"); - if (!babelbin) { - fprintf(stderr, "Babel plugin needs VMDBABELBIN environment variable\n" - "to point to location of Babel executable\n"); + if (!babelbin) + babelbin = "babel"; + +#if defined(USE_OPENBABEL_AUTODETECT) + filetype = openbabeltype_from_name(filetypename); + if (!filetype) { + fprintf(stderr, "No OpenBabel file type for '%s'\n", filetypename); return NULL; } +#endif -#if 0 +#if defined(USE_OPENBABEL_1_100_2) /* Try Open Babel file type names first... */ filetype = openbabel11type_from_name(filetypename); if (!filetype) { fprintf(stderr, "No Open Babel 1.100.2 file type for '%s'\n", filetypename); + return NULL; } #endif +#if defined(USE_BABEL_1_6) /* Try Babel 1.6 file type names if Open Babel didn't match */ filetype = babel16type_from_name(filetypename); if (!filetype) { fprintf(stderr, "No Babel 1.6 file type for '%s'\n", filetypename); return NULL; } +#endif + s = (char *)malloc(strlen(babelbin) + strlen(" -i -opdb ") + strlen(filename) + @@ -610,6 +643,78 @@ VMDPLUGIN_API int VMDPLUGIN_init() { #if defined(_MSC_VER) return VMDPLUGIN_SUCCESS; #else + +#if defined(USE_OPENBABEL_AUTODETECT) + /* Ask OpenBabel >= 2.2.0 to tell us what formats it can read. */ + + const char *babelbin = getenv("VMDBABELBIN"); + if (!babelbin) + babelbin = "babel"; + + char *tmpfile = strdup(BABEL_TMPDIR "/formats.XXXXXX"); + tmpfile = mktemp (tmpfile); + char *s = malloc(strlen(babelbin) + strlen(" -L formats read > ") + + strlen(tmpfile) + 3); + sprintf(s, "\"%s\" -L formats read > %s", babelbin, tmpfile); + system(s); + free(s); + + /* First read the number of formats we have. */ + FILE *f = fopen(tmpfile, "r"); + char buf[1024]; + nplugins = 0; + while (fgets (buf, sizeof(buf), f)) + nplugins++; + fclose(f); + + /* Now we get information for each plugin. */ + int i, j; + plugins = (molfile_plugin_t*)calloc(nplugins, sizeof(molfile_plugin_t)); + openbabelfiletypes = calloc(nplugins, sizeof(char*)); + openbabelfiletypenames = calloc(nplugins, sizeof(char*)); + f = fopen(tmpfile, "r"); + for (i=0; i