From 0f770551cebca90c92b7a39b0e0135a445af51f9 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Sat, 22 Mar 2008 02:28:22 +0000 Subject: merging in pdj-0.8.4.tar.gz from http://www.le-son666.com/software/pdj/ svn path=/trunk/externals/loaders/pdj/; revision=9624 --- src/pdj-osx.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) (limited to 'src/pdj-osx.c') diff --git a/src/pdj-osx.c b/src/pdj-osx.c index bd2be18..7c5b281 100644 --- a/src/pdj-osx.c +++ b/src/pdj-osx.c @@ -2,12 +2,170 @@ #include #include #include +#include +#include +#include +#include #include "pdj.h" +/** + * === USING AWT WITH OS X + * + * Unlike Linux or Windows, you cannot just simply fire-up a AWT form on OS X. This is + * because the event GUI mecanism has these limitation : + * + * --> A CFRunLoopRun must be park in the main thread. + * --> Java must be run in a secondary thread. + * + * Since this prerequisite need a pure-data patch, we will write our own pd scheduler. + * This scheduler will simple fire-up another thread that will run the real pd + * scheduler (m_mainloop) and park the main thread with a CFRunLoopRun. + * + * To be able to use the pdj scheduler, you need to apply a patch to pd. (Yes there + * is a bug with the -schedlib option). The patch is available in the directory + * src/pd_patch/osx_extsched_fix.patch. This patch has been made on a miller's 41.2 + * pd version. + * + * Once the patch is applied and compiled, you must configure your pure-data environement + * to add the option : -schedlib [fullpath of the pdj external without the extension]. Use + * the menu Pd -> Preference -> Startup to do this. Don't forget to click on [Save All + * Settings]. + * + * Be carfull when you configure this switch since it can crash PD on startup. If you do + * have the problem; you will have to delete all pd-preference by deleting file: + * ~/Library/Preferences/org.puredata.pd.plist + * + * If the scheduler is loaded, you should have this pd message : + * 'pdj: using pdj scheduler for Java AWT.' + */ + +int rc_pd = 0xFF; +CFRunLoopRef cfrunloop; + + +/* setting the environment varible APP_NAME_ to the applications name */ +/* sets it for the application menu */ +void setAppName(const char * name) { + char a[32]; + pid_t id = getpid(); + sprintf(a,"APP_NAME_%ld",(long)id); + setenv(a, name, 1); +} + + +/** + * The main pd thread, will become a secondary thread to AWT. + */ +void *pdj_pdloop(void *notused) { + post("pdj: using pdj scheduler for Java AWT."); + rc_pd = 0; + + // this will tell the java init code to initialize AWT before anything + setenv("PDJ_USE_AWT", "true", 1); + + // we create the JVM now + init_jvm(); + + /* open audio and MIDI */ + sys_reopen_midi(); + sys_reopen_audio(); + + rc_pd = m_mainloop(); + + exit(rc_pd); +} + + +/* call back for dummy source used to make sure the CFRunLoop doesn't exit right away */ +/* This callback is called when the source has fired. */ +void sourceCallBack ( void *info ) { +} + + +/** + * This function is called when pdj is considered a scheduler on pd + */ +int pd_extern_sched(void *notused) { + CFRunLoopSourceContext sourceContext; + + /* Start the thread that runs the pure-data main thread and the VM. */ + pthread_t vmthread; + + setAppName("pdj"); + + /* create a new pthread copying the stack size of the primordial pthread */ + struct rlimit limit; + size_t stack_size = 0; + int rc = getrlimit(RLIMIT_STACK, &limit); + if (rc == 0) { + if (limit.rlim_cur != 0LL) { + stack_size = (size_t)limit.rlim_cur; + } + } + + pthread_attr_t thread_attr; + pthread_attr_init(&thread_attr); + pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + if (stack_size > 0) { + pthread_attr_setstacksize(&thread_attr, stack_size); + } + + /* Start the thread that we will start the pd main thread */ + pthread_create(&vmthread, &thread_attr, pdj_pdloop, NULL); + pthread_attr_destroy(&thread_attr); + + /* Create a a sourceContext to be used by our source that makes */ + /* sure the CFRunLoop doesn't exit right away */ + sourceContext.version = 0; + sourceContext.info = NULL; + sourceContext.retain = NULL; + sourceContext.release = NULL; + sourceContext.copyDescription = NULL; + sourceContext.equal = NULL; + sourceContext.hash = NULL; + sourceContext.schedule = NULL; + sourceContext.cancel = NULL; + sourceContext.perform = &sourceCallBack; + + /* Create the Source from the sourceContext */ + CFRunLoopSourceRef sourceRef = CFRunLoopSourceCreate(NULL, 0, &sourceContext); + + /* Use the constant kCFRunLoopCommonModes to add the source to the set of objects */ + /* monitored by all the common modes */ + CFRunLoopAddSource (CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes); + + /* Park this thread in the runloop for Java */ + CFRunLoopRun(); + + return rc_pd; +} + + int getuglylibpath(char *path) { char fullpath[MAXPDSTRING], *pfullpath; + int cnt = _dyld_image_count(); + char *imagename = NULL; FILE *fd; + int i; + + // we get the bundle header, that contains the dyld header too... + struct mach_header* header = (struct mach_header*) &_mh_bundle_header; + + for(i=1;i