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 import VFSImporter
 
 
 from direct.showbase.DirectObject import DirectObject
 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 pandac import PandaModules
 from direct.stdpy import file
 from direct.stdpy import file
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.task.TaskManagerGlobal import taskMgr
@@ -80,6 +80,7 @@ class AppRunner(DirectObject):
         # These will be set from the application flags when
         # These will be set from the application flags when
         # setP3DFilename() is called.
         # setP3DFilename() is called.
         self.allowPythonDev = False
         self.allowPythonDev = False
+        self.guiApp = False
         self.interactiveConsole = False
         self.interactiveConsole = False
         self.initialAppImport = False
         self.initialAppImport = False
 
 
@@ -518,29 +519,41 @@ class AppRunner(DirectObject):
         self.superMirrorUrl = superMirrorUrl
         self.superMirrorUrl = superMirrorUrl
 
 
     def addPackageInfo(self, name, platform, version, hostUrl):
     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)
         host = self.getHost(hostUrl)
 
 
         if not host.readContentsFile():
         if not host.readContentsFile():
             if not host.downloadContentsFile(self.http):
             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:
         if not platform:
             platform = None
             platform = None
         package = host.getPackage(name, version, platform = platform)
         package = host.getPackage(name, version, platform = platform)
         if not package:
         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.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,
     def setP3DFilename(self, p3dFilename, tokens, argv, instanceId,
                        interactiveConsole):
                        interactiveConsole):
@@ -608,6 +621,9 @@ class AppRunner(DirectObject):
             allowPythonDev = self.p3dConfig.Attribute('allow_python_dev')
             allowPythonDev = self.p3dConfig.Attribute('allow_python_dev')
             if allowPythonDev:
             if allowPythonDev:
                 self.allowPythonDev = int(allowPythonDev)
                 self.allowPythonDev = int(allowPythonDev)
+            guiApp = self.p3dConfig.Attribute('gui_app')
+            if guiApp:
+                self.guiApp = int(guiApp)
 
 
             xhost = self.p3dConfig.FirstChildElement('host')
             xhost = self.p3dConfig.FirstChildElement('host')
             while xhost:
             while xhost:
@@ -625,6 +641,9 @@ class AppRunner(DirectObject):
             # allow_python_dev is enabled.
             # allow_python_dev is enabled.
             ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
             ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
 
 
+        if self.guiApp:
+            initAppForGui()
+
         self.initPackedAppEnvironment()
         self.initPackedAppEnvironment()
 
 
         # Mount the Multifile under /mf, by convention.
         # Mount the Multifile under /mf, by convention.

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

@@ -77,6 +77,7 @@ class PackageInfo:
         self.hasDescFile = False
         self.hasDescFile = False
         self.patchVersion = None
         self.patchVersion = None
         self.displayName = None
         self.displayName = None
+        self.guiApp = False
         self.uncompressedArchive = None
         self.uncompressedArchive = None
         self.compressedArchive = None
         self.compressedArchive = None
         self.extracts = []
         self.extracts = []
@@ -243,6 +244,11 @@ class PackageInfo:
             # The name for display to an English-speaking user.
             # The name for display to an English-speaking user.
             self.displayName = xconfig.Attribute('display_name')
             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,
         # The uncompressed archive, which will be mounted directly,
         # and also used for patching.
         # and also used for patching.
         xuncompressedArchive = xpackage.FirstChildElement('uncompressed_archive')
         xuncompressedArchive = xpackage.FirstChildElement('uncompressed_archive')
@@ -800,7 +806,7 @@ class PackageInfo:
 
 
     def installPackage(self, appRunner):
     def installPackage(self, appRunner):
         """ Mounts the package and sets up system paths so it becomes
         """ 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
         assert self.hasPackage
         if self.installed:
         if self.installed:

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

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

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

@@ -20,11 +20,6 @@
 #include <assert.h>
 #include <assert.h>
 #include <string.h>  // strrchr
 #include <string.h>  // strrchr
 using namespace std;
 using namespace std;
-         
-#ifdef __APPLE__
-#include <Carbon/Carbon.h>
-extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
-#endif
 
 
 #if defined(_WIN32) && defined(NON_CONSOLE)
 #if defined(_WIN32) && defined(NON_CONSOLE)
 // On Windows, we may need to build p3dpythonw.exe, a 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, 
   if (!run_p3dpython(program_name, archive_file, input_handle, output_handle, 
                      NULL, interactive_console)) {
                      NULL, interactive_console)) {
     cerr << "Failure on startup.\n";
     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) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
     }
+    exit(1);
   }
   }
   Py_XDECREF(result);
   Py_XDECREF(result);
 }
 }
@@ -1214,10 +1215,12 @@ add_package_info(P3DCInstance *inst, TiXmlElement *xpackage) {
 
 
   if (result == NULL) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
     }
+    exit(1);
   }
   }
+
   Py_XDECREF(result);
   Py_XDECREF(result);
 }
 }
 
 
@@ -1281,9 +1284,10 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
 
 
   if (result == NULL) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
     }
+    exit(1);
   }
   }
   Py_XDECREF(result);
   Py_XDECREF(result);
 }
 }
@@ -1380,9 +1384,10 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
 
 
   if (result == NULL) {
   if (result == NULL) {
     PyErr_Print();
     PyErr_Print();
-    if (!_interactive_console) {
-      exit(1);
+    if (_interactive_console) {
+      run_interactive_console();
     }
     }
+    exit(1);
   }
   }
   Py_XDECREF(result);
   Py_XDECREF(result);
 }
 }

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

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

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

@@ -19,6 +19,11 @@
 #include "renderBuffer.h"
 #include "renderBuffer.h"
 #include "camera.h"
 #include "camera.h"
 #include "graphicsPipeSelection.h"
 #include "graphicsPipeSelection.h"
+         
+#ifdef __APPLE__
+#include <Carbon/Carbon.h>
+extern "C" { void CPSEnableForegroundOperation(ProcessSerialNumber* psn); }
+#endif
 
 
 #ifdef WIN32
 #ifdef WIN32
 #include <windows.h>  // For SystemParametersInfo()
 #include <windows.h>  // For SystemParametersInfo()
@@ -55,6 +60,23 @@ get_config_showbase() {
   return 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
 // klunky interface since we cant pass array from python->C++ to use verify_window_sizes directly
 static int num_fullscreen_testsizes = 0;
 static int num_fullscreen_testsizes = 0;
 #define MAX_FULLSCREEN_TESTS 10
 #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 void throw_new_frame();
 
 
 EXPCL_DIRECT DConfig &get_config_showbase();
 EXPCL_DIRECT DConfig &get_config_showbase();
-
+EXPCL_DIRECT void init_app_for_gui();
 
 
 // klunky interface since we cant pass array from python->C++
 // klunky interface since we cant pass array from python->C++
 EXPCL_DIRECT void add_fullscreen_testsize(int xsize, int ysize);
 EXPCL_DIRECT void add_fullscreen_testsize(int xsize, int ysize);