Browse Source

better handling of some startup failures; don't make a osx gui app unless necessary

David Rose 16 years ago
parent
commit
2dbd154536

+ 31 - 12
direct/src/p3d/AppRunner.py

@@ -33,7 +33,7 @@ else:
     from direct.showbase import VFSImporter
 
 from direct.showbase.DirectObject import DirectObject
-from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString
+from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, initAppForGui
 from pandac import PandaModules
 from direct.stdpy import file
 from direct.task.TaskManagerGlobal import taskMgr
@@ -80,6 +80,7 @@ class AppRunner(DirectObject):
         # These will be set from the application flags when
         # setP3DFilename() is called.
         self.allowPythonDev = False
+        self.guiApp = False
         self.interactiveConsole = False
         self.initialAppImport = False
 
@@ -518,29 +519,41 @@ class AppRunner(DirectObject):
         self.superMirrorUrl = superMirrorUrl
 
     def addPackageInfo(self, name, platform, version, hostUrl):
-        """ Called by the browser to list all of the "required"
-        packages that were preloaded before starting the
-        application.  If for some reason the package isn't already
-        downloaded, this will download it on the spot. """
+        """ Called by the browser for each one of the "required"
+        packages that were preloaded before starting the application.
+        If for some reason the package isn't already downloaded, this
+        will download it on the spot.  Raises OSError on failure. """
 
         host = self.getHost(hostUrl)
 
         if not host.readContentsFile():
             if not host.downloadContentsFile(self.http):
-                print "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name)
-                return
+                message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name)
+                raise OSError, message
 
         if not platform:
             platform = None
         package = host.getPackage(name, version, platform = platform)
         if not package:
-            print "Couldn't find %s %s on %s" % (name, version, hostUrl)
-            return
+            message = "Couldn't find %s %s on %s" % (name, version, hostUrl)
+            raise OSError, message
 
         package.checkStatus()
-        package.downloadDescFile(self.http)
-        package.downloadPackage(self.http)
-        package.installPackage(self)
+        if not package.downloadDescFile(self.http):
+            message = "Couldn't get desc file for %s" % (name)
+            raise OSError, message
+        
+        if not package.downloadPackage(self.http):
+            message = "Couldn't download %s" % (name)
+            raise OSError, message
+        
+        if not package.installPackage(self):
+            message = "Couldn't install %s" % (name)
+            raise OSError, message
+
+        if package.guiApp:
+            self.guiApp = True
+            initAppForGui()
 
     def setP3DFilename(self, p3dFilename, tokens, argv, instanceId,
                        interactiveConsole):
@@ -608,6 +621,9 @@ class AppRunner(DirectObject):
             allowPythonDev = self.p3dConfig.Attribute('allow_python_dev')
             if allowPythonDev:
                 self.allowPythonDev = int(allowPythonDev)
+            guiApp = self.p3dConfig.Attribute('gui_app')
+            if guiApp:
+                self.guiApp = int(guiApp)
 
             xhost = self.p3dConfig.FirstChildElement('host')
             while xhost:
@@ -625,6 +641,9 @@ class AppRunner(DirectObject):
             # allow_python_dev is enabled.
             ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
 
+        if self.guiApp:
+            initAppForGui()
+
         self.initPackedAppEnvironment()
 
         # Mount the Multifile under /mf, by convention.

+ 7 - 1
direct/src/p3d/PackageInfo.py

@@ -77,6 +77,7 @@ class PackageInfo:
         self.hasDescFile = False
         self.patchVersion = None
         self.displayName = None
+        self.guiApp = False
         self.uncompressedArchive = None
         self.compressedArchive = None
         self.extracts = []
@@ -243,6 +244,11 @@ class PackageInfo:
             # The name for display to an English-speaking user.
             self.displayName = xconfig.Attribute('display_name')
 
+            # True if any apps that use this package must be GUI apps.
+            guiApp = xconfig.Attribute('gui_app')
+            if guiApp:
+                self.guiApp = int(guiApp)
+
         # The uncompressed archive, which will be mounted directly,
         # and also used for patching.
         xuncompressedArchive = xpackage.FirstChildElement('uncompressed_archive')
@@ -800,7 +806,7 @@ class PackageInfo:
 
     def installPackage(self, appRunner):
         """ Mounts the package and sets up system paths so it becomes
-        available for use. """
+        available for use.  Returns true on success, false on failure. """
 
         assert self.hasPackage
         if self.installed:

+ 2 - 0
direct/src/p3d/panda3d.pdef

@@ -214,6 +214,7 @@ class ode(package):
 
 class wx(package):
     config(display_name = "wxPython GUI Toolkit")
+    config(gui_app = True)
     require('panda3d')
 
     module('direct.showbase.WxGlobal', 'wx', 'wx.*')
@@ -221,6 +222,7 @@ class wx(package):
 
 class tk(package):
     config(display_name = "Tk GUI Toolkit")
+    config(gui_app = True)
     require('panda3d')
 
     module('Tkinter',

+ 0 - 15
direct/src/plugin/p3dPythonMain.cxx

@@ -20,11 +20,6 @@
 #include <assert.h>
 #include <string.h>  // strrchr
 using namespace std;
-         
-#ifdef __APPLE__
-#include <Carbon/Carbon.h>
-extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
-#endif
 
 #if defined(_WIN32) && defined(NON_CONSOLE)
 // On Windows, we may need to build p3dpythonw.exe, a non-console
@@ -155,16 +150,6 @@ main(int argc, char *argv[]) {
     }
   }
 
-#ifdef __APPLE__
-  // In case the application is going to run a wx app, allow it to
-  // have access to the desktop.
-  ProcessSerialNumber psn;
-  
-  GetCurrentProcess(&psn);
-  CPSEnableForegroundOperation(&psn);
-  SetFrontProcess(&psn);
-#endif
-
   if (!run_p3dpython(program_name, archive_file, input_handle, output_handle, 
                      NULL, interactive_console)) {
     cerr << "Failure on startup.\n";

+ 13 - 8
direct/src/plugin/p3dPythonRun.cxx

@@ -1180,9 +1180,10 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
 
   if (result == NULL) {
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
+    exit(1);
   }
   Py_XDECREF(result);
 }
@@ -1214,10 +1215,12 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) {
 
   if (result == NULL) {
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
+    exit(1);
   }
+
   Py_XDECREF(result);
 }
 
@@ -1281,9 +1284,10 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
 
   if (result == NULL) {
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
+    exit(1);
   }
   Py_XDECREF(result);
 }
@@ -1380,9 +1384,10 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
 
   if (result == NULL) {
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
+    exit(1);
   }
   Py_XDECREF(result);
 }

+ 2 - 0
direct/src/showbase/ShowBase.py

@@ -2429,6 +2429,7 @@ class ShowBase(DirectObject.DirectObject):
     def startWx(self, fWantWx = 1):
         self.wantWx = fWantWx
         if self.wantWx:
+            initAppForGui()
             from direct.showbase import WxGlobal
             taskMgr.remove('wxLoop')
             WxGlobal.spawnWxLoop()
@@ -2436,6 +2437,7 @@ class ShowBase(DirectObject.DirectObject):
     def startTk(self, fWantTk = 1):
         self.wantTk = fWantTk
         if self.wantTk:
+            initAppForGui()
             from direct.showbase import TkGlobal
             taskMgr.remove('tkLoop')
             TkGlobal.spawnTkLoop()

+ 22 - 0
direct/src/showbase/showBase.cxx

@@ -19,6 +19,11 @@
 #include "renderBuffer.h"
 #include "camera.h"
 #include "graphicsPipeSelection.h"
+         
+#ifdef __APPLE__
+#include <Carbon/Carbon.h>
+extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
+#endif
 
 #ifdef WIN32
 #include <windows.h>  // For SystemParametersInfo()
@@ -55,6 +60,23 @@ get_config_showbase() {
   return config_showbase;
 }
 
+// Initialize the application for making a Gui-based app, such as wx.
+// At the moment, this is a no-op except on Mac.
+void
+init_app_for_gui() {
+  static bool initted_for_gui = false;
+  if (!initted_for_gui) {
+    initted_for_gui = true;
+#ifdef IS_OSX
+    ProcessSerialNumber psn;
+    
+    GetCurrentProcess(&psn);
+    CPSEnableForegroundOperation(&psn);
+    SetFrontProcess(&psn);
+#endif  // IS_OSX
+  }
+}
+
 // klunky interface since we cant pass array from python->C++ to use verify_window_sizes directly
 static int num_fullscreen_testsizes = 0;
 #define MAX_FULLSCREEN_TESTS 10

+ 1 - 1
direct/src/showbase/showBase.h

@@ -40,7 +40,7 @@ EXPCL_DIRECT ConfigVariableSearchPath &get_particle_path();
 EXPCL_DIRECT void throw_new_frame();
 
 EXPCL_DIRECT DConfig &get_config_showbase();
-
+EXPCL_DIRECT void init_app_for_gui();
 
 // klunky interface since we cant pass array from python->C++
 EXPCL_DIRECT void add_fullscreen_testsize(int xsize, int ysize);