コード例 #1
0
ファイル: test.db.c プロジェクト: AlvaroBuitrago/max-test
void testdb_setup(t_testdb *d)
{
	if (!d->d_db) {
		short			path = packages_getpackagepath("testpackage");
		char			fullpath[MAX_PATH_CHARS];
		short			apppath = path_getapppath();
		char			appfullpath[MAX_PATH_CHARS];
		unsigned long	appfullpathlen;
		int				i;
		char			dbfilename[MAX_PATH_CHARS];
		t_db_result		*dbresult = NULL;
		
		path_topathname(apppath, "", appfullpath);
		appfullpathlen = strlen(appfullpath);
		for (i=0; i<appfullpathlen; i++) {
			if (appfullpath[i] == ':' || appfullpath[i] == '/')
				appfullpath[i] ='-';
		}
		strncpy_zero(dbfilename, appfullpath, MAX_PATH_CHARS);
		strncat_zero(dbfilename, "--maxtestresults.db3", MAX_PATH_CHARS);
		
		path_topathname(path, "", fullpath);
		strncat_zero(fullpath, "/", MAX_PATH_CHARS);
		strncat_zero(fullpath, dbfilename, MAX_PATH_CHARS);
		db_open(gensym("unittestdb"), fullpath, &d->d_db);
		
		// cache the fullpath so it can be requested from the outside world
		{
			short apath;
			char afilename[MAX_FILENAME_CHARS];
			path_frompathname(fullpath, &apath, afilename);
			path_toabsolutesystempath(apath, afilename, g_dbpath);
		}

		db_query(d->d_db, &dbresult, "SELECT name FROM sqlite_master WHERE type='table' AND name='tests'");
		if (!db_result_numrecords(dbresult)) {
			db_query_table_new(d->d_db, "tests");
			db_query_table_addcolumn(d->d_db, "tests", "test_name",		"VARCHAR(512)", 0);
			db_query_table_addcolumn(d->d_db, "tests", "test_start",	"DATETIME", 0);
			db_query_table_addcolumn(d->d_db, "tests", "test_finish",	"DATETIME", 0);

			db_query_table_new(d->d_db, "assertions");
			db_query_table_addcolumn(d->d_db, "assertions", "test_id_ext",		"INTEGER", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_name",	"VARCHAR(512)", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_value",	"VARCHAR(512)", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_data",	"VARCHAR(512)", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_start",	"DATETIME", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_finish",	"DATETIME", 0);
			db_query_table_addcolumn(d->d_db, "assertions", "assertion_tags",	"VARCHAR(512)", 0);

			db_query_table_new(d->d_db, "logs");
			db_query_table_addcolumn(d->d_db, "logs", "test_id_ext",	"INTEGER", 0);
			db_query_table_addcolumn(d->d_db, "logs", "text",			"VARCHAR(512)", 0);
			db_query_table_addcolumn(d->d_db, "logs", "timestamp",		"DATETIME", 0);
		}
		object_free(dbresult);
	}
}
コード例 #2
0
void model_preset_filechanged(TTPtr self, char *filename, short path)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	char 		fullpath[MAX_PATH_CHARS];		// path and name passed on to the xml parser
	char		posixpath[MAX_PATH_CHARS];
	TTValue		v;
	TTSymbol    current;
	t_atom		a;

	// get current preset
	EXTRA->presetManager->get("current", v);

	path_topathname(path, filename, fullpath);
	path_nameconform(fullpath, posixpath, PATH_STYLE_NATIVE, PATH_TYPE_BOOT);

	atom_setsym(&a, gensym(posixpath));
	defer_low(self, (method)model_preset_doread, gensym("read"), 1, &a);

    /* since JamomaMax#711 : we decide to mute the triggering of the current preset

    // try to recall last current preset
	current = v[0];
	atom_setsym(&a, gensym((char*)current.c_str()));
	defer_low((t_object*)x, (method)model_preset_dorecall, NULL, 1, &a);

    */
}
コード例 #3
0
ファイル: flbase.cpp プロジェクト: EQ4/IntegraLive
void flext_obj::GetCanvasDir(char *buf,size_t bufsz) const
{
#if FLEXT_SYS == FLEXT_SYS_PD
	const char *c = GetString(canvas_getdir(thisCanvas()));
    strncpy(buf,c,bufsz);
#elif FLEXT_SYS == FLEXT_SYS_MAX 
	short path = patcher_myvol(thisCanvas());
    // \TODO dangerous!! no check for path length (got to be long enough... like 1024 chars)
	path_topathname(path,NULL,buf);
#else 
#error Not implemented
#endif
}
コード例 #4
0
ファイル: cc.c プロジェクト: CNMAT/CNMAT-Externs
t_max_err cc_cfile_set(t_cc *x, t_object *attr, long argc, t_atom *argv){
	if(argc == 0){
		// should put up an open file editor window here
		return 1;
	}

	t_symbol *arg = atom_getsym(argv);
	if(arg == gensym("")){
		return 0;
	}
	char *f = arg->s_name;

	FILE *fp;
	if(*f == '/'){
		// full path.  read it if it exists, otherwise write a template
		strcpy(x->cfile_fullpath, f);
		if(fp = fopen(f, "r")){
			x->code_len = fread(x->code_buf, sizeof(char), BUFSIZE, fp);
		}else{
			if(fp = fopen(f, "w")){
				x->code_len = cc_write_template(x, x->code_buf);
				fwrite(x->code_buf, x->code_len, sizeof(char), fp);
				fclose(fp);
			}
		}
	}else{
		// not a full path.  try to find it in the search path and bail if not found
		short outvol;//, binflag;
		long outtype;
		//if(locatefile(f, &outvol, &binflag)){
		if(locatefile_extended(f, &outvol, &outtype, NULL, 0)){
			error("cc: couldn't locate %s", f);
			return 1;
		}else{
			char buf[MAX_PATH_CHARS];
			char *ptr = buf;
			path_topathname(outvol, f, buf);
			while(*ptr++ != ':'){}
			strcpy(x->cfile_fullpath, ptr);
		}
	}

	cc_get_basename(f, x->basename);
	sprintf(x->ofile_fullpath, "%s/%s.o", x->build_path, x->basename);
	sprintf(x->dfile_fullpath, "%s/%s.dylib", x->build_path, x->basename);
	sprintf(x->logfile_fullpath, "%s/%s.log", x->build_path, x->basename);

	x->have_valid_filename = 1;

	return 0;
}
コード例 #5
0
void model_preset_default(TTPtr self)
{
	WrappedModularInstancePtr	x = (WrappedModularInstancePtr)self;
	short		outvol;
	t_fourcc	outtype, filetype = 'TEXT';
	char 		fullpath[MAX_PATH_CHARS];		// path and name passed on to the xml parser
	char		posixpath[MAX_PATH_CHARS];
	t_atom		a;
	t_symbol*	textfile;

	if (x->patcherClass != kTTSymEmpty) {

        if (EXTRA->attr_presets != kTTSym_none) {

            textfile = gensym(EXTRA->attr_presets.c_str());
        }
		else if (x->patcherContext == kTTSym_model)
			jamoma_edit_filename(*ModelPresetFormat, x->patcherClass, &textfile);

		else if (x->patcherContext == kTTSym_view)
			jamoma_edit_filename(*ViewPresetFormat, x->patcherClass, &textfile);
		else
			return object_error((t_object*)x, "preset_default : can't get the context of the patcher");

		if (locatefile_extended((char*)textfile->s_name, &outvol, &outtype, &filetype, 1)) {
			//object_warn((t_object*)x, "preset_default : can't find %s file in the Max search path", textfile.data());
			return;
		}

		path_topathname(outvol, (char*)textfile->s_name, fullpath);
		path_nameconform(fullpath, posixpath, PATH_STYLE_NATIVE, PATH_TYPE_BOOT);

		atom_setsym(&a, gensym(posixpath));
		defer_low(self, (method)model_preset_doread, gensym("read"), 1, &a);

		// recall the default preset if exists
        atom_setsym(&a, gensym("default"));
		defer_low((t_object*)x, (method)model_preset_dorecall, NULL, 1, &a);

		// replace filewatcher
		if (EXTRA->filewatcher) {
			filewatcher_stop(EXTRA->filewatcher);
			object_free(EXTRA->filewatcher);
		}

		EXTRA->filewatcher = filewatcher_new((t_object*)x, outvol, (char*)textfile->s_name);
		filewatcher_start(EXTRA->filewatcher);
	}
	else
		object_error((t_object*)x, "preset_default : can't get the class of the patcher");
}
コード例 #6
0
ファイル: pybase.cpp プロジェクト: McAlyster/py
void pybase::AddCurrentPath(flext_base *o)
{
    char dir[1024];

    // add dir of current patch to path
    o->GetCanvasDir(dir,sizeof(dir));
    if(*dir) AddToPath(dir);

    // add current dir to path
#if FLEXT_SYS == FLEXT_SYS_PD
    AddToPath(GetString(canvas_getcurrentdir()));
#elif FLEXT_SYS == FLEXT_SYS_MAX
    short path = path_getdefault();
    path_topathname(path,NULL,dir);
    AddToPath(dir);
#endif
}
コード例 #7
0
void myCreateFolder(t_mkdir, t_symbol *newfoldername) 
// short CreateFolder(const FSRef parentFolder, const CFStringRef folderName) 
{
	OSErr myerr;
	long len;
	short path;
	char name[256];
	char inname[2048];
	char name[2048];
	char parentname[2048];
	FSSpec fs;
	CFStringRef str;
	CFURLRef url;
	HFSUniStr255 folderNameU;


	path_nameconform(inname, newfoldername->s_name, PATH_STYLE_NATIVE, PATH_TYPE_ABSOLUTE);	
	len = strlen(inname);
	strrchr();
	filename = strrchr(name, '/') + 1;

	if (!path_topathname(path, "", inname)) { // check if path alreay exists
	
		path_nameconform(outname, natname, PATH_STYLE_NATIVE, PATH_TYPE_ABSOLUTE);
		
		path_tospec(0, natname, &fs);
	
		str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
		
		folderNameU.length = (UInt16) CFStringGetLength(str);
		
		CFStringGetCharacters(folderName, CFRangeMake(0, folderNameU.length), folderNameU.unicode);

		// see if it already exists?
		myerr = FSMakeFSRefUnicode(&parentname, folderNameU.length,folderNameU.unicode,
							kTextEncodingUnicodeDefault, NULL);
		// should now verify that is, in fact, a folder.
	
		if (myerr != noErr) { // no, so try to create it.		
			myerr = FSCreateDirectoryUnicode(&parentFolder, folderNameU.length, folderNameU.unicode,
				kFSCatInfoNone, NULL, NULL, NULL, NULL);
		}
		return myerr;	
	}
}
コード例 #8
0
// Function the translates a Max path+filename combo into a correct absolutepath
// TODO: remove this function once we've completed the transition to Max5, as path_topathname() is fixed for Max5
void jcom_core_getfilepath(short in_path, char *in_filename, char *out_filepath)
{
	char	path[4096];
	
	path_topathname(in_path, in_filename, path);

#ifdef MAC_VERSION
	char *temppath;
	temppath = strchr(path, ':');
	*temppath = '\0';
	temppath += 1;

	// at this point temppath points to the path after the volume, and out_filepath points to the volume
	sprintf(out_filepath, "/Volumes/%s%s", path, temppath);
#else // WIN_VERSION
	strcpy(out_filepath, path);
#endif
}
コード例 #9
0
ファイル: cc.c プロジェクト: CNMAT/CNMAT-Externs
int cc_doload(t_cc *x, t_symbol *lib){
	while(x->ok_to_compile == 0){}
	x->compiling = 1;
	int ret = 0;

	t_symbol *dfile_sym = lib;
	if(!dfile_sym){
		if(x->dfile_fullpath){
			dfile_sym = gensym(x->dfile_fullpath);
		}else{
			goto out;
		}
	}

	char dfile[MAX_PATH_CHARS];
	strcpy(dfile, dfile_sym->s_name);
	//char *ptr = dfile->s_name;
	//if(*ptr != '/'){
	short outvol;
	long outtype;
	if(locatefile_extended(dfile, &outvol, &outtype, NULL, 0)){
		error("cc: couldn't locate %s", dfile);
		ret = 1;
		goto out;
	}else{
		char buf[MAX_PATH_CHARS];
		path_topathname(outvol, dfile, buf);
		char *ptr = buf;
		while(*ptr++ != ':'){}
		dfile_sym = gensym(ptr);
		strcpy(dfile, dfile_sym->s_name);
	}

	x->handle = dlopen(dfile, RTLD_NOW);
	if(!x->handle){
		error("cc: %s", dlerror());
		ret = 1;
		goto out;
	}

	// read the symbols from the dylib
	hashtab_clear(x->ht);
	char *err;
	char st[MAX_PATH_CHARS];
	sprintf(st, "%s/.%s", x->build_path, x->basename);

	char compbuf[1024];
	sprintf(compbuf, "nm %s | awk '$2 ~ /T/ {print $3}' > %s", dfile, st);
	if(system(compbuf)){
		error("cc: couldn't parse symbol table");
		ret = 1;
		goto out;
	}

	FILE *fp = fopen(st, "r");
	if(!fp){
		error("cc: couldn't read symbol table");
		ret = 1;
		goto out;
	}

	char buf[LINE_MAX];
	int i = 0;
	while(fgets(buf, LINE_MAX, fp)){
		buf[strlen(buf) - 1] = '\0'; // get rid of the newline char
		//ccmethod f = (ccmethod)dlsym(x->handle, buf + 1);
		long f = (long)dlsym(x->handle, buf + 1);
		if((err = dlerror()) == NULL){
			x->function_names[i] = gensym(buf + 1); // skip over the leading underscore
			hashtab_store(x->ht, x->function_names[i], (t_object *)f);
#if defined(CC_JBOX)
			if(!strcmp(buf + 1, "my_paint")){
				x->user_paint = (ccpaint_method)f;
			}
#endif
			post("%s", buf + 1);
		}
	}
	fclose(fp);
	remove(st);

	void (*f)(t_object *, char *);
	hashtab_lookup(x->ht, gensym("my_new"), (t_object **)&f);
	if(f){
		f((t_object *)x, x->user_obj);
	}
 out:
	x->compiling = 0;
#if defined(CC_JBOX)
	jbox_redraw((t_jbox *)x);
#endif
	return ret;
}
コード例 #10
0
ファイル: JamomaForMax.cpp プロジェクト: EQ4/JamomaMax
void jamoma_init(void)
{
    short		outvol = 0;
    t_fourcc	outtype, filetype = 'TEXT';
    char        name[MAX_PATH_CHARS], fullname[MAX_PATH_CHARS];
    
	if (!initialized) {
        
		t_object	*max = SymbolGen("max")->s_thing;
        TTString    JamomaConfigurationFilePath;
		t_atom		a[4];
		TTValue		v, out;
        TTErr       err;

		if (maxversion() < 1798)
        {
			error("Jamoma  %s  |  build %s can't run under Max version ealier than 7.0.6", JAMOMA_MAX_VERSION, JAMOMA_MAX_REV);
            return;
        }
        
		// Initialize the Modular library
        TTModularInit();
        
#ifdef TTSCORE_IMPORT
        // Initialize the Score framework
        TTScoreInit();
#endif
        
        // Prepare a symbol for Max application
        kTTSym_Max = TTSymbol("Max");
        
        // Create an application manager
        MaxApplicationManager = TTObject("ApplicationManager");
        
        // Create a local application called "Max" and get it back
        err = MaxApplicationManager.send("ApplicationInstantiateLocal", kTTSym_Max, out);
        
        if (err) {
            TTLogError("Error : can't create Jamoma application \n");
            return;
        }
        else
            MaxApplication = out[0];

        // check if the JamomaConfiguration.xml file exists
        strncpy_zero(name, "JamomaConfiguration.xml", MAX_PATH_CHARS);
        if (locatefile_extended(name, &outvol, &outtype, &filetype, 1))
            return error("Jamoma not loaded : can't find %s", name);
        
        path_topathname(outvol, name, fullname);


        // MaxApplication have to read JamomaConfiguration.xml
        TTObject anXmlHandler(kTTSym_XmlHandler);
        anXmlHandler.set(kTTSym_object, MaxApplication);
        std::string path = fullname;
        #if ( __APPLE__ )
        // remove drive name prefix
        size_t pos = path.find(":/");
        path = path.substr(pos+1);
       	v = TTSymbol(path);
        #else
        v = TTSymbol(fullname);
		#endif
        anXmlHandler.send(kTTSym_Read, v, out);

		// Initialize common symbols
		common_symbols_init();
		jamomaSymbolsInit();
		
		// Initialize common regex
		ttRegexForJmod = new TTRegex("(jmod.)");
		ttRegexForJcom = new TTRegex("(j\\.)");
		ttRegexForModel = new TTRegex("(.model)");
		ttRegexForModule = new TTRegex("(.module)");
		ttRegexForView = new TTRegex("(.view)");
		ttRegexForMaxpat = new TTRegex("(.maxpat)");
		ttRegexForMaxhelp = new TTRegex("(.maxhelp)");
		ttRegexForBracket = new TTRegex("\\[(\\d|\\d\\d|\\d\\d\\d)\\]");	// parse until 999
		
		ModelPatcherFormat = new TTString("%s.model.maxpat");
		ModelPresetFormat = new TTString("%s.model.presets.txt");
		ViewPresetFormat = new TTString("%s.view.presets.txt");
		HelpPatcherFormat = new TTString("%s.model");
		RefpageFormat = new TTString("%s.model");
		DocumentationFormat = new TTString("%s.model.html");
		
		// Create Required Global Instances
		hash_modules = (t_hashtab*)hashtab_new(0);
		// TODO: Use quittask_install() to set up a destructor for this to free it before Max exits

		// Add Jamoma Key Commands
		
		// J -- Jamoma: a new object box with "j." in it
		atom_setsym(a+0, SymbolGen("k"));
		atom_setsym(a+1, SymbolGen("patcher"));
		atom_setsym(a+2, SymbolGen("inserttextobj"));
		atom_setsym(a+3, SymbolGen("j."));
		object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL);
				
//		// M -- Module: a new object box with ".model" in it
//		atom_setsym(a+0, SymbolGen("M"));
//		atom_setsym(a+1, SymbolGen("patcher"));
//		atom_setsym(a+2, SymbolGen("inserttextobj"));
//		atom_setsym(a+3, SymbolGen(".model"));
//		object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL);
//        
		
//		// B -- BPatcher: a new module in a bpatcher
//		object_method_parse(max, SymbolGen("definecommand"), (char*)"B patcher inserttextobj \"bpatcher @name .module @args myModule\"", NULL);		

//		// D -- Demo: a new module in a bpatcher, but with the args reverse which is handy for super-fast demos when you don't care about the OSC name
//		object_method_parse(max, SymbolGen("definecommand"), (char*)"D patcher inserttextobj \"bpatcher @name .module\"", NULL);		

//		// X -- Continuous Mapper module
//		object_method_parse(max, SymbolGen("definecommand"), (char*)"X patcher insertobj bpatcher @name mapper.module.maxpat @args mapper", NULL);
				
		// now the jamoma object
		{
			t_symbol *jamomaSymbol = SymbolGen("jamoma");
		
			jamoma_object_initclass();
			jamomaSymbol->s_thing = jamoma_object_new();
		}
		
		post("Jamoma  %s  |  build %s", JAMOMA_MAX_VERSION, JAMOMA_MAX_REV );

		initialized = true;
	}
}
コード例 #11
0
void max_jit_openni_XMLConfig_read(t_max_jit_openni *x, t_symbol *s, short argc, t_atom *argv)
{
	long i;
	t_atom OutAtoms[2];	
	short filePathID;
	long fileType = 'TEXT', outType;
	char filename[MAX_FILENAME_CHARS];
	char fullyQualifiedPathname[MAX_PATH_CHARS];
	XnStatus nRetVal = XN_STATUS_OK;
	
#ifdef _DEBUG
	t_object *mypatcher;
	t_symbol *mypatcherpath;

	if (object_obex_lookup(x, gensym("#P"), &mypatcher) != MAX_ERR_NONE)
		LOG_ERROR("error getting patcher for jit.openni");
	mypatcherpath = object_attr_getsym(mypatcher, gensym("filepath"));
	
	if ((mypatcherpath) && (mypatcherpath != gensym(""))) 	// if I use _sym_nothing rather than gensym("") then I get linker error LNK2001: unresolved external symbol __common_symbols
	{
		LOG_COMMENT2("The patcher path is %s", mypatcherpath->s_name);
	}
	else
	{
		LOG_COMMENT("error getting filepath symbol for max.jit.openni");
		return;
	}
#endif

	if (argc == 0) // if no argument supplied, ask for file
	{
		if (open_dialog(filename, &filePathID, &outType, &fileType, 1))
		{
			// non-zero: user cancelled or error
			LOG_DEBUG("error getting XML config file from dialog box for max.jit.openni");
			atom_setsym(OutAtoms, gensym("<none>"));
			atom_setlong(OutAtoms + 1, 0);
			max_jit_obex_dumpout(x, gensym("read"), 2, OutAtoms);
			return;
		}
	}
	else if ((argc != 1) || (atom_gettype(argv) != A_SYM))
	{
		LOG_DEBUG("read must have only one symbol argument");
		atom_setsym(OutAtoms, gensym("<none>"));
		atom_setlong(OutAtoms + 1, 0);
		max_jit_obex_dumpout(x, gensym("read"), 2, OutAtoms);
		return;
	}
	else // we have exactly one symbol argument
	{
		strncpy_zero(filename, atom_getsym(argv)->s_name, MAX_FILENAME_CHARS);
		if (locatefile_extended(filename, &filePathID, &outType, &fileType, 1))
		{
			LOG_DEBUG2("Could not find file", atom_getsym(argv)->s_name);
			atom_setsym(OutAtoms, atom_getsym(argv));
			atom_setlong(OutAtoms + 1, 0);
			max_jit_obex_dumpout(x, gensym("read"), 2, OutAtoms);
			return;
		}
	}

	//Load file
	atom_setsym(OutAtoms, gensym(filename));
	if (path_topathname(filePathID, filename, fullyQualifiedPathname) == 0)
	{
		LOG_DEBUG2("asking Jitter object to load file %s", fullyQualifiedPathname);
		jit_object_method(max_jit_obex_jitob_get(x), gensym("init_from_xml"), gensym(fullyQualifiedPathname), &nRetVal);
		if (nRetVal)
		{
			atom_setlong(OutAtoms + 1, 0);
		}
		else
		{
			atom_setlong(OutAtoms + 1, 1);
		}
		max_jit_obex_dumpout(x, gensym("read"), 2, OutAtoms);
	}
	else
	{
		atom_setlong(OutAtoms + 1, 0);
		max_jit_obex_dumpout(x, gensym("read"), 2, OutAtoms);
	}

}
コード例 #12
0
ファイル: pybase.cpp プロジェクト: McAlyster/py
static bool getmodulesub(const char *mod,char *dir,int len,const char *ext)
{
#if FLEXT_SYS == FLEXT_SYS_PD
    char *name;
    int fd = open_via_path("",mod,ext,dir,&name,len,0);
    if(fd >= 0) {
        fileclose(fd);
        FLEXT_ASSERT(name && *name);
    }
    else {
        // look for mod/__init__.py
        std::string tmp(mod); 
        int l = tmp.size();
        tmp += "/__init__";
        fd = open_via_path("",tmp.c_str(),ext,dir,&name,len,0);
        if(fd >= 0) {
            fileclose(fd);
            FLEXT_ASSERT(name && *name);

            // we must remove the module name from dir
            char *t = dir+strlen(dir)-l;
            FLEXT_ASSERT(!strcmp(mod,t) && t[-1] == '/');
            t[-1] = 0;
        }
        else
            name = NULL;
    }

    // if dir is current working directory... name points to dir
    if(dir == name) strcpy(dir,".");
    return name != NULL;
#elif FLEXT_SYS == FLEXT_SYS_MAX
    short path;
    long type;
    char smod[1024];
    strcpy(smod,mod);
    strcat(smod,ext);
    bool ok = !locatefile_extended(smod,&path,&type,&type,0);
    if(ok)
        // convert pathname to unix style
        path_topathname(path,NULL,smod);
    else {
        // do path/file.ext combinations work at all under Max?
        strcpy(smod,mod);

        short path;
        type = 'fold';
        ok = !locatefile_extended(smod,&path,&type,&type,1);
        if(ok) {
            // convert pathname to unix style (including trailing slash)
            path_topathname(path,NULL,smod);
            char *end = smod+strlen(smod);
            strcpy(end,mod);
            strcat(end,"/__init__");
            strcat(end,ext);

            // check if file is really existing: try to open it
            FILE *f = fopen(smod,"r");
            if(f) {
                *end = 0;  // clear module part ... we only need base path
                fclose(f);
            }
            else
                ok = false;
        }
    }
    
    if(ok) {
        // convert path into slash style needed for Python
#if 0
        // Max API function uses Volume:/Path notation
        path_nameconform(smod,dir,PATH_STYLE_SLASH,PATH_TYPE_ABSOLUTE);
#else
#if FLEXT_OS == FLEXT_OS_WIN
        char *colon = NULL;
#else
        char *colon = strchr(smod,':');
#endif
        if(colon) {
            *colon = 0;
            strcpy(dir,"/Volumes/");
            strcat(dir,smod);
            strcat(dir,colon+1);
        }
        else
            strcpy(dir,smod);
#endif
        return true;
    }
    else
        // not found
        return false;
#else
#pragma message("Not implemented");
    return false;
#endif
}