99import sys
1010import os , os .path
1111import json
12- import subprocess
1312import time
1413import platform
1514
@@ -167,7 +166,7 @@ def setSaveFileName(self, obj):
167166
168167class Xqemu (object ):
169168 def __init__ (self ):
170- self ._p = None
169+ self ._p = QtCore . QProcess ()
171170 self ._qmp = None
172171
173172 @staticmethod
@@ -282,10 +281,11 @@ def launchCmdToString(cmd):
282281
283282 def start (self , settings ):
284283 cmd = self .generateLaunchCmd (settings )
284+ cmd_string = self .launchCmdToString (cmd )
285285
286- print ('Running: %s' % self . launchCmdToString ( cmd ) )
286+ print ('Running: %s' % cmd_string )
287287
288- self ._p = subprocess . Popen ( cmd )
288+ self ._p . start ( cmd_string )
289289 i = 0
290290 while True :
291291 print ('Trying to connect %d' % i )
@@ -294,6 +294,10 @@ def start(self, settings):
294294 self ._qmp = QEMUMonitorProtocol (('localhost' , 4444 ))
295295 self ._qmp .connect ()
296296 except Exception as e :
297+ # If XQEMU quits, we abort the loop
298+ if self ._p .waitForFinished (1 ):
299+ return
300+
297301 if i > 4 :
298302 raise
299303 else :
@@ -302,9 +306,8 @@ def start(self, settings):
302306 break
303307
304308 def stop (self ):
305- if self ._p :
309+ if self .isRunning :
306310 self ._p .terminate ()
307- self ._p = None
308311
309312 def run_cmd (self , cmd ):
310313 if type (cmd ) is str :
@@ -341,7 +344,7 @@ def isPaused(self):
341344
342345 @property
343346 def isRunning (self ):
344- return self ._p is not None # FIXME: Check subproc state
347+ return self ._p is not None and self . _p . state () == QtCore . QProcess . Running
345348
346349class MainWindow (QMainWindow , mainwindow_class ):
347350 def __init__ (self , * args ):
@@ -361,19 +364,46 @@ def __init__(self, *args):
361364 self .restartButton .clicked .connect (self .onRestartButtonClicked )
362365 self .actionExit .triggered .connect (self .onExitClicked )
363366 self .actionSettings .triggered .connect (self .onSettingsClicked )
367+ self .inst ._p .readyReadStandardOutput .connect (self .onReadyReadStandardOutput )
368+ self .inst ._p .readyReadStandardError .connect (self .onReadyReadStandardError )
369+ self .inst ._p .stateChanged .connect (self .onXqemuStateChanged )
370+
371+ def onReadyReadStandardOutput (self ):
372+ text = self .inst ._p .readAllStandardOutput ().data ().decode ()
373+ self .log .moveCursor (QtGui .QTextCursor .End )
374+ self .log .insertPlainText (text )
375+ self .log .moveCursor (QtGui .QTextCursor .End )
376+
377+ def onReadyReadStandardError (self ):
378+ text = self .inst ._p .readAllStandardError ().data ().decode ()
379+ self .log .moveCursor (QtGui .QTextCursor .End )
380+ self .log .insertPlainText (text )
381+ self .log .moveCursor (QtGui .QTextCursor .End )
382+
383+ def onXqemuStateChanged (self ):
384+ if self .inst .isRunning :
385+ self .runButton .setText ('Stop' )
386+ else :
387+ self .runButton .setText ('Start' )
388+ if self .inst ._p .exitCode () != 0 :
389+ QMessageBox .critical (self , 'XQEMU quit prematurely!' , 'XQEMU quit prematurely.\n \n '
390+ 'This may be a known issue with this specific game, a problem in XQEMU, or an error in your settings.\n '
391+ 'Please check your settings for correctness and see the log area for details.\n '
392+ 'If you need help resolving this problem, make sure to include this log in your error report, '
393+ 'along with as many details about how and what you were doing when the error happened.' )
394+ self .pauseButton .setText ('Pause' )
364395
365396 def onRunButtonClicked (self ):
366397 if not self .inst .isRunning :
367398 # No active instance
368399 try :
400+ self .log .clear ()
369401 self .inst .start (self .settings )
370- self .runButton .setText ('Stop' )
371402 except Exception as e :
372403 QMessageBox .critical (self , 'Error!' , str (e ))
373404 else :
374405 # Instance exists
375406 self .inst .stop ()
376- self .runButton .setText ('Start' )
377407
378408 def onPauseButtonClicked (self ):
379409 if not self .inst .isRunning : return
0 commit comments