Hi. I am embedding libpd into a video game. The video game targets Android and so will be shipped in a configuration where assets are bundled into a zip file (the APK) and decoded at runtime. Code does not access the filesystem directly.
Looking at the libpd C sample, and also the documentation, it appears the only way to get it to open a patch is `void *libpd_openfile(const char *name, const char *dir)`. This appears to take an on-disk path to the patch file directly and it appears sometimes it will open other files from disk too (I guess pd files can reference external sound files?). However, again, none of the files I will want it to open are on the disk so it will not find them.
Is there a way around this? For example is there a backdoor to give libpd a buffer in memory containing an already-loaded file? Or callbacks to replace libpd's open/read file functions?
If this is not possible, it looks like I might be able to alter libpd to add virtual filesystem abilities (for example, letting the library user provide a table of surrogate openFile, readFile, closeFile function pointers). It looks(?) like the filesystem access is pretty neatly contained in s_path.c and m_binbuf.c. If I do this, would there be interest in accepting the patch back upstream?
I'm not sure if you can make calls directly into Pd, but if so, you can do what Pd does to create a couple of invosoble canvases it leeds. Look in teh Pd source for garray_init() (g_array.c) to see how it's done.
Perhaps this would be a good thing for libpd to support directly at some point.
Also, I've been thinking for a long time about how patches could include their own abstractions for easier distribution... I haven't been able to figure out the best way to do this yet (fake a filesystem? Or include dependencies directly in the Pd file? dunno...)
cheers Miller
On Mon, May 04, 2020 at 04:46:05PM -0400, Andi McClure wrote:
Hi. I am embedding libpd into a video game. The video game targets Android and so will be shipped in a configuration where assets are bundled into a zip file (the APK) and decoded at runtime. Code does not access the filesystem directly.
Looking at the libpd C sample, and also the documentation, it appears the only way to get it to open a patch is `void *libpd_openfile(const char *name, const char *dir)`. This appears to take an on-disk path to the patch file directly and it appears sometimes it will open other files from disk too (I guess pd files can reference external sound files?). However, again, none of the files I will want it to open are on the disk so it will not find them.
Is there a way around this? For example is there a backdoor to give libpd a buffer in memory containing an already-loaded file? Or callbacks to replace libpd's open/read file functions?
If this is not possible, it looks like I might be able to alter libpd to add virtual filesystem abilities (for example, letting the library user provide a table of surrogate openFile, readFile, closeFile function pointers). It looks(?) like the filesystem access is pretty neatly contained in s_path.c and m_binbuf.c. If I do this, would there be interest in accepting the patch back upstream?
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
I think supporting non-filesystem patch loading would be a good basic feature for libpd. There are lots of deployment environments where directly accessing the filesystem either isn't possible or isn't the best way to lookup files.
It's hard for me to say what the best way for you to do that is because I am unfortunately only a little familiar with PureData itself (in the case of my project I am integrating pd files created by another person). But it seems to me that if file paths / file names are already part of the "user model" of PureData— IE, someone using the graphical programming environment would be used to using filenames for referencing external sound files or other pd files— then it is probably best to keep the filesystem as a concept and just virtualize access to that filesystem.
A way to do this I've seen in a couple libraries is by letting the user supply a struct of function pointers that wrap file operations like open, read etc. For example look at PhysFS_Archiver and PHYSFS_Io in PhysFS: https://icculus.org/physfs/docs/html/structPHYSFS__Archiver.html PhysFS is a popular virtual-filesystem library I know a number of games use, you use it to access a chroot-like "local" filesystem which in fact is a directory on disk or a zip file. Its _Archiver and _Io structs are the last-case resort if a user needs to load files out of something that isn't a directory or zip. It would be pretty easy to implement this approach by running through s_path.c, m_binbuf.c etc and replacing any file-related function calls with pd_open, pd_read etc wrappers and having those wrappers call the registered function pointers if a structure's been registered or call normal fs ops if they don't. (In your C++ frontend you could present the function pointer table as like a class with virtual methods maybe.)
Packing dependencies directly into a pd file on the other hand might be useful for some applications (I'm imagining trying to run puredata on an arduino or something? I assume people are already doing this…) but it seems to me this means you lose the advantages of the filesystem model. For example I could imagine my project having two .pd files that both reference the same .ogg, if I was using dependency-packed files we'd have to pack the .ogg twice.
As for my case, I think the garray_init idea suggested by you and Christof Ressi is enough for me right now! I will test with it.
On Mon, May 4, 2020 at 5:02 PM Miller Puckette msp@ucsd.edu wrote:
I'm not sure if you can make calls directly into Pd, but if so, you can do what Pd does to create a couple of invosoble canvases it leeds. Look in teh Pd source for garray_init() (g_array.c) to see how it's done.
Perhaps this would be a good thing for libpd to support directly at some point.
Also, I've been thinking for a long time about how patches could include their own abstractions for easier distribution... I haven't been able to figure out the best way to do this yet (fake a filesystem? Or include dependencies directly in the Pd file? dunno...)
cheers Miller
On Mon, May 04, 2020 at 04:46:05PM -0400, Andi McClure wrote:
Hi. I am embedding libpd into a video game. The video game targets Android and so will be shipped in a configuration where assets are bundled into a zip file (the APK) and decoded at runtime. Code does not access the filesystem directly.
Looking at the libpd C sample, and also the documentation, it appears the only way to get it to open a patch is `void *libpd_openfile(const char *name, const char *dir)`. This appears to take an on-disk path to the patch file directly and it appears sometimes it will open other files from disk too (I guess pd files can reference external sound files?). However, again, none of the files I will want it to open are on the disk so it will not find them.
Is there a way around this? For example is there a backdoor to give libpd a buffer in memory containing an already-loaded file? Or callbacks to replace libpd's open/read file functions?
If this is not possible, it looks like I might be able to alter libpd to add virtual filesystem abilities (for example, letting the library user provide a table of surrogate openFile, readFile, closeFile function pointers). It looks(?) like the filesystem access is pretty neatly contained in s_path.c and m_binbuf.c. If I do this, would there be interest in accepting the patch back upstream?
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
Hi, it's certainly possible to load Pd patches entirely from memory with a binbuf. In fact, Pd itself does this for its private hidden canvases. Checkout the patch "garray_arraytemplatefile" in g_array.c and garray_init() for how to read it.
Christof
On 04.05.2020 22:46, Andi McClure wrote:
Hi. I am embedding libpd into a video game. The video game targets Android and so will be shipped in a configuration where assets are bundled into a zip file (the APK) and decoded at runtime. Code does not access the filesystem directly.
Looking at the libpd C sample, and also the documentation, it appears the only way to get it to open a patch is `void *libpd_openfile(const char *name, const char *dir)`. This appears to take an on-disk path to the patch file directly and it appears sometimes it will open other files from disk too (I guess pd files can reference external sound files?). However, again, none of the files I will want it to open are on the disk so it will not find them.
Is there a way around this? For example is there a backdoor to give libpd a buffer in memory containing an already-loaded file? Or callbacks to replace libpd's open/read file functions?
If this is not possible, it looks like I might be able to alter libpd to add virtual filesystem abilities (for example, letting the library user provide a table of surrogate openFile, readFile, closeFile function pointers). It looks(?) like the filesystem access is pretty neatly contained in s_path.c and m_binbuf.c. If I do this, would there be interest in accepting the patch back upstream?
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev