Problem using Juce in a Python module


#1

Hi,

I am quite new to Juce, and I am already blocked by an issue.

I'd like to make a python module that opens a Juce Window when the module is imported (by the 'import <module>" , which calls a C function :  PyMODINIT_FUNC PyInit_<module>(void) ).

As it must create a new thread I can not use of course the standard JuceApplication initialisation, with START_JUCE_APPLICATION and so.

It looks like it is not more possible to use ScopedJuceInitialiser_GUI + MessageManager::runDispatchLoop() elsewhere than in the main thread.

I made a lot of tries, without any success : no gui displaying, and abort trap.

So here are my questions : Do you think this is something possible ? and if yes, how ?

 


#2

Everything's possible! Sounds like you're on the right lines, but I've no idea how python modules work, hopefully someone else will be able to help out here..


#3

My question is not particulary related to Python, it could be another kind of embedding.

It is quite simple, the Juce GUI initialisation must be called in a standard C function, like this one (PyInit_MyModule) :

static std::thread* my_juce_thread;

void my_juce_gui_initialisation_and_loop(){
   initialiseJuce_GUI(); // is it enough ???
   {
     DocumentWindow main_window("MyWindow", Colours::white, true, true); 

     // don't know what to write here, in any case JuceApplication can not be used in a thread
     // a MessageManager loop ???
   }
   shutdownJuce_GUI();
}

PyObject* PyInit_MyModule(void){

   // code to declare the new python module, new_module_pyobject_ptr

   PyObject* new_module_pyobject_ptr = ...

   // entering a new thread :

   my_juce_thread = new std::thread(my_juce_gui_initialisation_and_loop);

   return new_module_pyobject_ptr;

}

The question here can be summarised to : what should I write in my initialisation and loop function (my_juce_gui_initialisation_and_loop) ?
 

 

 


#4

Yes, calling that initialiser function is enough. But do you really need to run the message thread via juce, or is there already some other service that's doing that?


#5

For MacOS it does not seem to be enough. It works better with:

#if JUCE_MAC 
  JUCE_AUTORELEASEPOOL { 
   [NSApplication sharedApplication]; 
  } 
#endif

The main window also needs a runModalState() loop or something similar, isn't it ?

It worked when I tried from the main thread, but not within a new thread : the window is displayed, but blank, without any content drawn, and is not responding to mouse events.

void my_juce_gui_initialisation_and_loop(){ 
   
   #if JUCE_MAC 
     JUCE_AUTORELEASEPOOL { [NSApplication sharedApplication]; } 
   #endif

   initialiseJuce_GUI(); 
   { 
      DocumentWindow main_window("MyWindow", Colours::white, true, true); 
      //...

      main_window.runModalLoop();

   } 
   shutdownJuce_GUI(); 
}

 

When all of these is embedded in a python module, I have to do all the threading stuff, otherwise the python interpreter will be blocked by the GUI loop.

 


#6

I read that in MacOS there is no way to make a GUI loop elswhere than in the application main thread.

So it looks like my idea to open a window inside a Python module (that launches a new thread) is just impossible.