error can be locked within properties()
and simplified the componenterrors again
This commit is contained in:
parent
661526b073
commit
15d70474d4
|
@ -19,7 +19,7 @@ class ComponentMetaclass(type(QtCore.QObject)):
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
raise ComponentInitError(self, 'initialization process')
|
raise ComponentError(self, 'initialization process')
|
||||||
except ComponentError:
|
except ComponentError:
|
||||||
return
|
return
|
||||||
return initializationWrapper
|
return initializationWrapper
|
||||||
|
@ -63,7 +63,13 @@ class ComponentMetaclass(type(QtCore.QObject)):
|
||||||
if self._lockedProperties is not None:
|
if self._lockedProperties is not None:
|
||||||
return self._lockedProperties
|
return self._lockedProperties
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
return func(self)
|
return func(self)
|
||||||
|
except Exception:
|
||||||
|
try:
|
||||||
|
raise ComponentError(self, 'properties')
|
||||||
|
except ComponentError:
|
||||||
|
return []
|
||||||
return propertiesWrapper
|
return propertiesWrapper
|
||||||
|
|
||||||
def errorWrapper(func):
|
def errorWrapper(func):
|
||||||
|
@ -396,18 +402,18 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class ComponentException(RuntimeError):
|
class ComponentError(RuntimeError):
|
||||||
'''A base class for component errors'''
|
'''Gives the MainWindow a traceback to display, and cancels the export.'''
|
||||||
|
|
||||||
_prevErrors = []
|
prevErrors = []
|
||||||
|
|
||||||
def __init__(self, caller, name, immediate):
|
def __init__(self, caller, name):
|
||||||
print('ComponentError by %s: %s' % (caller.name, name))
|
print('ComponentError by %s: %s' % (caller.name, name))
|
||||||
super().__init__()
|
super().__init__()
|
||||||
if len(ComponentException._prevErrors) > 1:
|
if len(ComponentError.prevErrors) > 1:
|
||||||
ComponentException._prevErrors.pop()
|
ComponentError.prevErrors.pop()
|
||||||
ComponentException._prevErrors.insert(0, name)
|
ComponentError.prevErrors.insert(0, name)
|
||||||
if name in ComponentException._prevErrors[1:]:
|
if name in ComponentError.prevErrors[1:]:
|
||||||
# Don't create multiple windows for repeated messages
|
# Don't create multiple windows for repeated messages
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -434,28 +440,4 @@ class ComponentException(RuntimeError):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if immediate:
|
|
||||||
caller._error.emit(string, detail)
|
caller._error.emit(string, detail)
|
||||||
else:
|
|
||||||
caller.lockProperties(['error'])
|
|
||||||
caller.lockError((string, detail))
|
|
||||||
|
|
||||||
|
|
||||||
class ComponentError(ComponentException):
|
|
||||||
'''
|
|
||||||
Use for general Python errors caused by a component at any time.
|
|
||||||
Raising this gives the MainWindow a traceback to display and
|
|
||||||
cancels any export in progress.
|
|
||||||
'''
|
|
||||||
def __init__(self, caller, name):
|
|
||||||
ComponentException.__init__(self, caller, name, True)
|
|
||||||
|
|
||||||
|
|
||||||
class ComponentInitError(ComponentError):
|
|
||||||
'''
|
|
||||||
Use for Python errors in preFrameRender, while the export is starting.
|
|
||||||
This will end the video thread in a clean way by locking the component
|
|
||||||
into an error state so the export definitely won't begin.
|
|
||||||
'''
|
|
||||||
def __init__(self, caller, name):
|
|
||||||
ComponentException.__init__(self, caller, name, False)
|
|
||||||
|
|
|
@ -154,33 +154,28 @@ class Component(Component):
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def properties(self):
|
def properties(self):
|
||||||
# TODO: Disallow selecting the same video you're exporting to
|
|
||||||
props = []
|
props = []
|
||||||
if not self.videoPath or self.badVideo \
|
|
||||||
or not os.path.exists(self.videoPath):
|
if not self.videoPath:
|
||||||
return ['error']
|
self.lockError("There is no video selected.")
|
||||||
|
elif self.badVideo:
|
||||||
|
self.lockError("Could not identify an audio stream in this video.")
|
||||||
|
elif not os.path.exists(self.videoPath):
|
||||||
|
self.lockError("The video selected does not exist!")
|
||||||
|
elif (os.path.realpath(self.videoPath) ==
|
||||||
|
os.path.realpath(
|
||||||
|
self.parent.window.lineEdit_outputFile.text())):
|
||||||
|
self.lockError("Input and output paths match.")
|
||||||
|
|
||||||
if self.useAudio:
|
if self.useAudio:
|
||||||
props.append('audio')
|
props.append('audio')
|
||||||
self.testAudioStream()
|
if not testAudioStream(self.videoPath) \
|
||||||
if self.badAudio:
|
and self.error() is None:
|
||||||
return ['error']
|
self.lockError(
|
||||||
|
"Could not identify an audio stream in this video.")
|
||||||
|
|
||||||
return props
|
return props
|
||||||
|
|
||||||
def error(self):
|
|
||||||
if self.badAudio:
|
|
||||||
return "Could not identify an audio stream in this video."
|
|
||||||
if not self.videoPath:
|
|
||||||
return "There is no video selected."
|
|
||||||
if not os.path.exists(self.videoPath):
|
|
||||||
return "The video selected does not exist!"
|
|
||||||
if self.badVideo:
|
|
||||||
return "The video selected is corrupt!"
|
|
||||||
|
|
||||||
def testAudioStream(self):
|
|
||||||
self.badAudio = testAudioStream(self.videoPath)
|
|
||||||
|
|
||||||
def audio(self):
|
def audio(self):
|
||||||
params = {}
|
params = {}
|
||||||
if self.volume != 1.0:
|
if self.volume != 1.0:
|
||||||
|
|
|
@ -573,16 +573,16 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str, str)
|
@QtCore.pyqtSlot(str, str)
|
||||||
def videoThreadError(self, msg, detail):
|
def videoThreadError(self, msg, detail):
|
||||||
self.showMessage(
|
|
||||||
msg=msg,
|
|
||||||
detail=detail,
|
|
||||||
icon='Warning',
|
|
||||||
)
|
|
||||||
try:
|
try:
|
||||||
self.stopVideo()
|
self.stopVideo()
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
if 'videoWorker' not in str(e):
|
if 'videoWorker' not in str(e):
|
||||||
raise
|
raise
|
||||||
|
self.showMessage(
|
||||||
|
msg=msg,
|
||||||
|
detail=detail,
|
||||||
|
icon='Warning',
|
||||||
|
)
|
||||||
|
|
||||||
def changeEncodingStatus(self, status):
|
def changeEncodingStatus(self, status):
|
||||||
self.encoding = status
|
self.encoding = status
|
||||||
|
|
Binary file not shown.
|
@ -224,9 +224,9 @@ def testAudioStream(filename):
|
||||||
try:
|
try:
|
||||||
checkOutput(audioTestCommand, stderr=subprocess.DEVNULL)
|
checkOutput(audioTestCommand, stderr=subprocess.DEVNULL)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def getAudioDuration(filename):
|
def getAudioDuration(filename):
|
||||||
|
|
|
@ -163,24 +163,27 @@ class Worker(QtCore.QObject):
|
||||||
except ComponentError:
|
except ComponentError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if 'error' in comp.properties():
|
compProps = comp.properties()
|
||||||
|
if 'error' in compProps or comp.error() is not None:
|
||||||
self.cancel()
|
self.cancel()
|
||||||
self.canceled = True
|
self.canceled = True
|
||||||
canceledByComponent = True
|
canceledByComponent = True
|
||||||
compError = comp.error() \
|
compError = comp.error() \
|
||||||
if type(comp.error()) is tuple else (comp.error(), '')
|
if type(comp.error()) is tuple else (comp.error(), '')
|
||||||
errMsg = (
|
errMsg = (
|
||||||
"Component #%s encountered an error!" % compNo
|
"Component #%s (%s) encountered an error!" % (
|
||||||
|
str(compNo), comp.name
|
||||||
|
)
|
||||||
if comp.error() is None else
|
if comp.error() is None else
|
||||||
'Export cancelled by component #%s (%s): %s' % (
|
'Export cancelled by component #%s (%s): %s' % (
|
||||||
str(compNo),
|
str(compNo),
|
||||||
str(comp),
|
comp.name,
|
||||||
compError[0]
|
compError[0]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
comp._error.emit(errMsg, compError[1])
|
comp._error.emit(errMsg, compError[1])
|
||||||
break
|
break
|
||||||
if 'static' in comp.properties():
|
if 'static' in compProps:
|
||||||
self.staticComponents[compNo] = \
|
self.staticComponents[compNo] = \
|
||||||
comp.frameRender(compNo, 0).copy()
|
comp.frameRender(compNo, 0).copy()
|
||||||
|
|
||||||
|
|
Reference in New Issue