1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
#include "m_pd.h"
#include "s_stuff.h"
#include "g_canvas.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/* this object requires Pd 0.40.3 or later */
/* WARNING: KLUDGE! */
/*
* this struct is not publically defined (its in g_canvas.c) so I need to
* include this here. Its from Pd 0.47-0. */
struct _canvasenvironment
{
t_symbol *ce_dir; /* directory patch lives in */
int ce_argc; /* number of "$" arguments */
t_atom *ce_argv; /* array of "$" arguments */
int ce_dollarzero; /* value of "$0" */
t_namelist *ce_path; /* search path */
};
static char *version =
#ifdef VERSION
VERSION
#else
"unknown"
#endif
;
int sys_trytoopenone(const char *, const char *, const char*, char *, char **, unsigned int, int);
/* This loader opens a directory with a -meta.pd file as a library. In the
* long run, the idea is that one folder will have all of objects files, all
* of the related *-help.pd files, a file with meta data for the help system,
* etc. Then to install the lib, it would just be dropped into extra, or
* anywhere in the global classpath.
*
* Ultimately, the meta file will be read for meta data, specifically for
* the auto-generated Help system, but for other things too. Right now,
* its just used as a marker that a directory is meant to be a library.
* Plus its much easier to implement it this way, I can use
* open_via_path() instead of writing a new function. The grand plan is
* to have one directory hold the objects, help files, manuals,
* etc. making it a self-contained library. <hans@at.or.at>
*/
/*
* TODO
* - get 'declare' messages from the meta-file, and send them to the current canvas
*/
static void libdir_get_fullname(char*dest, size_t size, const char*classname) {
snprintf(dest, size-1, "%s/%s-meta", classname, classname);
dest[size-1]=0;
}
#if PD_MAJOR_VERSION>0 || PD_MINOR_VERSION>47
/* gone from the headers, but still present for binary compat */
extern t_namelist *sys_searchpath;
#endif
static int libdir_add_to_globalpath(const char*path) {
int major, minor, bugfix;
sys_getversion(&major, &minor, &bugfix);
if((major==0 && minor < 48)) {
sys_searchpath = namelist_append(sys_searchpath, path, 0);
} else {
const char *inptr = path;
char encoded[MAXPDSTRING];
char *outptr = encoded;
t_atom ap[2];
*outptr++='+';
while(inptr && ((outptr+2) < (encoded+MAXPDSTRING))) {
*outptr++ = *inptr++;
if ('+'==inptr[-1])
*outptr++='+';
}
*outptr=0;
SETSYMBOL(ap+0, gensym(encoded));
SETFLOAT(ap+1, 0.f);
pd_typedmess(gensym("pd")->s_thing, gensym("add-to-path"), 2, ap);
}
return 1;
}
static int libdir_add_to_path(const char*dirbuf, t_canvas*canvas) {
if(sys_isabsolutepath(dirbuf)) { // only include actual full paths
if (canvas) {
t_canvasenvironment *canvasenvironment = canvas_getenv(canvas);
canvasenvironment->ce_path = namelist_append(canvasenvironment->ce_path,
dirbuf, 0);
} else {
return libdir_add_to_globalpath(dirbuf);
}
return 1;
}
return 0;
}
static int libdir_loader_legacy(t_canvas *canvas, char *classname)
{
int fd = -1;
char fullclassname[FILENAME_MAX], dirbuf[FILENAME_MAX];
char *nameptr;
/* look for meta file (classname)/(classname)-meta.pd */
libdir_get_fullname(fullclassname, FILENAME_MAX, classname);
/* if this is being called from a canvas, then add the library path to the
* canvas-local path */
if(canvas)
/* setting the canvas to NULL causes it to ignore any canvas-local path */
fd = canvas_open(NULL, fullclassname, ".pd",
dirbuf, &nameptr, FILENAME_MAX, 0);
else
fd = open_via_path(".", fullclassname, ".pd",
dirbuf, &nameptr, FILENAME_MAX, 0);
if(fd < 0)
{
return (0);
}
sys_close(fd);
#if 0
if(!canvas) {
char helppathname[FILENAME_MAX];
strncpy(helppathname, sys_libdir->s_name, FILENAME_MAX-30);
helppathname[FILENAME_MAX-30] = 0;
strcat(helppathname, "/doc/5.reference/");
strcat(helppathname, classname);
sys_helppath = namelist_append(sys_helppath, helppathname, 0);
}
#endif
if(libdir_add_to_path(dirbuf, canvas))
logpost(NULL, 3, "libdir_loader: added '%s' to the %s objectclass path",
classname, canvas?"canvas-local":"global");
/* post("libdir_loader loaded fullclassname: '%s'\n", fullclassname); */
logpost(NULL, 14, "Loaded libdir '%s' from '%s'", classname, dirbuf);
return (1);
}
static int libdir_loader_pathwise(t_canvas *canvas, const char *classname, const char*path)
{
int fd = -1;
char fullclassname[FILENAME_MAX], dirbuf[FILENAME_MAX];
char *nameptr;
if(!path) {
/* we already tried all paths, so skip this */
return 0;
}
/* look for meta file (classname)/(classname)-meta.pd */
libdir_get_fullname(fullclassname, FILENAME_MAX, classname);
if ((fd = sys_trytoopenone(path, fullclassname, ".pd",
dirbuf, &nameptr, FILENAME_MAX, 0)) < 0) {
return 0;
}
sys_close(fd);
if(libdir_add_to_path(dirbuf, canvas))
logpost(NULL, 3, "libdir_loader: added '%s' to the %s objectclass path",
classname, canvas?"canvas-local":"global");
/* post("libdir_loader loaded fullclassname: '%s'\n", fullclassname); */
logpost(NULL, 14, "Loaded libdir '%s' from '%s'", classname, dirbuf);
return (1);
}
static t_class *libdir_class;
static void*libdir_new(void)
{
t_pd *x = pd_new(libdir_class);
return (x);
}
void libdir_setup(void)
{
int major, minor, bugfix;
sys_getversion(&major, &minor, &bugfix);
if (major>0 || minor >=47) {
sys_register_loader((void*)libdir_loader_pathwise);
} else {
sys_register_loader((void*)libdir_loader_legacy);
}
logpost(NULL, 3, "libdir loader %s",version);
logpost(NULL, 3, "\tcompiled on "__DATE__" at "__TIME__ " ");
logpost(NULL, 3, "\tcompiled against Pd version %d.%d.%d.%s",
PD_MAJOR_VERSION, PD_MINOR_VERSION, PD_BUGFIX_VERSION, PD_TEST_VERSION);
libdir_class = class_new(gensym("libdir"), libdir_new, 0, sizeof(t_object), CLASS_NOINLET, 0);
}
void setup(void)
{
libdir_setup();
}
|