disable some hotkeys while encoding, more friendly error messages

This commit is contained in:
tassaron 2017-06-25 10:36:32 -04:00
parent 45b55d8e2f
commit a2838a0c38
5 changed files with 107 additions and 59 deletions

View File

@ -86,12 +86,14 @@ class Video:
continue continue
except AttributeError as e: except AttributeError as e:
self.parent.showMessage( self.parent.showMessage(
msg='%s couldn\'t be loaded.' % os.path.basename( msg='%s couldn\'t be loaded. '
'This is a fatal error.' % os.path.basename(
self.videoPath self.videoPath
), ),
detail=str(e) detail=str(e)
) )
self.parent.stopVideo() self.parent.stopVideo()
break
self.currentFrame = pipe.stdout.read(self.chunkSize) self.currentFrame = pipe.stdout.read(self.chunkSize)
if len(self.currentFrame) != 0: if len(self.currentFrame) != 0:
@ -258,20 +260,24 @@ def scale(scale, width, height, returntype=None):
def finalizeFrame(self, imageData, width, height): def finalizeFrame(self, imageData, width, height):
if self.distort: try:
try: if self.distort:
image = Image.frombytes( image = Image.frombytes(
'RGBA', 'RGBA',
(width, height), (width, height),
imageData) imageData)
except ValueError: else:
print('#### ignored invalid data caused by distortion ####') image = Image.frombytes(
image = self.blankFrame(width, height) 'RGBA',
else: scale(self.scale, width, height, int),
image = Image.frombytes( imageData)
'RGBA',
scale(self.scale, width, height, int), except ValueError:
imageData) print(
'### BAD VIDEO SELECTED ###\n'
'Video will not export with these settings'
)
return self.blankFrame(width, height)
if self.scale != 100 \ if self.scale != 100 \
or self.xPosition != 0 or self.yPosition != 0: or self.xPosition != 0 or self.yPosition != 0:

View File

@ -7,6 +7,15 @@ import preview_thread
import video_thread import video_thread
def disableWhenEncoding(func):
def decorator(*args):
if args[0].encoding:
return
else:
return func(*args)
return decorator
def LoadDefaultSettings(self): def LoadDefaultSettings(self):
self.resolutions = [ self.resolutions = [
'1920x1080', '1920x1080',

View File

@ -12,7 +12,7 @@ import core
import preview_thread import preview_thread
import video_thread import video_thread
from presetmanager import PresetManager from presetmanager import PresetManager
from main import LoadDefaultSettings from main import LoadDefaultSettings, disableWhenEncoding
class PreviewWindow(QtWidgets.QLabel): class PreviewWindow(QtWidgets.QLabel):
@ -54,6 +54,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.pages = [] # widgets of component settings self.pages = [] # widgets of component settings
self.lastAutosave = time.time() self.lastAutosave = time.time()
self.encoding = False
# Create data directory, load/create settings # Create data directory, load/create settings
self.dataDir = self.core.dataDir self.dataDir = self.core.dataDir
@ -149,16 +150,18 @@ class MainWindow(QtWidgets.QMainWindow):
for i, comp in enumerate(self.core.modules): for i, comp in enumerate(self.core.modules):
action = self.compMenu.addAction(comp.Component.__doc__) action = self.compMenu.addAction(comp.Component.__doc__)
action.triggered.connect( action.triggered.connect(
lambda _, item=i: self.core.insertComponent(0, item, self)) lambda _, item=i: self.core.insertComponent(0, item, self)
)
self.window.pushButton_addComponent.setMenu(self.compMenu) self.window.pushButton_addComponent.setMenu(self.compMenu)
componentList.dropEvent = self.dragComponent componentList.dropEvent = self.dragComponent
componentList.itemSelectionChanged.connect( componentList.itemSelectionChanged.connect(
self.changeComponentWidget) self.changeComponentWidget
)
self.window.pushButton_removeComponent.clicked.connect( self.window.pushButton_removeComponent.clicked.connect(
lambda _: self.removeComponent()) lambda: self.removeComponent()
)
componentList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) componentList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
componentList.customContextMenuRequested.connect( componentList.customContextMenuRequested.connect(
@ -173,7 +176,8 @@ class MainWindow(QtWidgets.QMainWindow):
currentRes = i currentRes = i
window.comboBox_resolution.setCurrentIndex(currentRes) window.comboBox_resolution.setCurrentIndex(currentRes)
window.comboBox_resolution.currentIndexChanged.connect( window.comboBox_resolution.currentIndexChanged.connect(
self.updateResolution) self.updateResolution
)
self.window.pushButton_listMoveUp.clicked.connect( self.window.pushButton_listMoveUp.clicked.connect(
lambda: self.moveComponent(-1) lambda: self.moveComponent(-1)
@ -185,14 +189,17 @@ class MainWindow(QtWidgets.QMainWindow):
# Configure the Projects Menu # Configure the Projects Menu
self.projectMenu = QMenu() self.projectMenu = QMenu()
self.window.menuButton_newProject = self.projectMenu.addAction( self.window.menuButton_newProject = self.projectMenu.addAction(
"New Project") "New Project"
)
self.window.menuButton_newProject.triggered.connect( self.window.menuButton_newProject.triggered.connect(
self.createNewProject) lambda: self.createNewProject()
)
self.window.menuButton_openProject = self.projectMenu.addAction( self.window.menuButton_openProject = self.projectMenu.addAction(
"Open Project") "Open Project"
)
self.window.menuButton_openProject.triggered.connect( self.window.menuButton_openProject.triggered.connect(
self.openOpenProjectDialog) lambda: self.openOpenProjectDialog()
)
action = self.projectMenu.addAction("Save Project") action = self.projectMenu.addAction("Save Project")
action.triggered.connect(self.saveCurrentProject) action.triggered.connect(self.saveCurrentProject)
@ -207,6 +214,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.openPresetManager self.openPresetManager
) )
self.updateWindowTitle()
window.show() window.show()
if project and project != self.autosavePath: if project and project != self.autosavePath:
@ -282,12 +290,15 @@ class MainWindow(QtWidgets.QMainWindow):
def updateWindowTitle(self): def updateWindowTitle(self):
appName = 'Audio Visualizer' appName = 'Audio Visualizer'
if self.currentProject: try:
appName += ' - %s' % \ if self.currentProject:
os.path.splitext( appName += ' - %s' % \
os.path.basename(self.currentProject))[0] os.path.splitext(
if self.autosaveExists(identical=False): os.path.basename(self.currentProject))[0]
appName += '*' if self.autosaveExists(identical=False):
appName += '*'
except AttributeError:
pass
self.window.setWindowTitle(appName) self.window.setWindowTitle(appName)
@QtCore.pyqtSlot(int, dict) @QtCore.pyqtSlot(int, dict)
@ -347,7 +358,7 @@ class MainWindow(QtWidgets.QMainWindow):
if not self.currentProject: if not self.currentProject:
if os.path.exists(self.autosavePath): if os.path.exists(self.autosavePath):
os.remove(self.autosavePath) os.remove(self.autosavePath)
elif force or time.time() - self.lastAutosave >= 2.0: elif force or time.time() - self.lastAutosave >= 0.1:
self.core.createProjectFile(self.autosavePath) self.core.createProjectFile(self.autosavePath)
self.lastAutosave = time.time() self.lastAutosave = time.time()
@ -393,7 +404,7 @@ class MainWindow(QtWidgets.QMainWindow):
"Video Files (%s);; All Files (*)" % " ".join( "Video Files (%s);; All Files (*)" % " ".join(
self.core.videoFormats)) self.core.videoFormats))
if not fileName == "": if fileName:
self.settings.setValue("outputDir", os.path.dirname(fileName)) self.settings.setValue("outputDir", os.path.dirname(fileName))
self.window.lineEdit_outputFile.setText(fileName) self.window.lineEdit_outputFile.setText(fileName)
@ -404,33 +415,50 @@ class MainWindow(QtWidgets.QMainWindow):
def createAudioVisualisation(self): def createAudioVisualisation(self):
# create output video if mandatory settings are filled in # create output video if mandatory settings are filled in
if self.window.lineEdit_audioFile.text() and \ audioFile = self.window.lineEdit_audioFile.text()
self.window.lineEdit_outputFile.text(): outputPath = self.window.lineEdit_outputFile.text()
self.canceled = False
self.progressBarUpdated(-1) if audioFile and outputPath and self.core.selectedComponents:
self.videoThread = QtCore.QThread(self)
self.videoWorker = video_thread.Worker(self)
self.videoWorker.moveToThread(self.videoThread)
self.videoWorker.videoCreated.connect(self.videoCreated)
self.videoWorker.progressBarUpdate.connect(self.progressBarUpdated)
self.videoWorker.progressBarSetText.connect(
self.progressBarSetText)
self.videoWorker.imageCreated.connect(self.showPreviewImage)
self.videoWorker.encoding.connect(self.changeEncodingStatus)
self.videoThread.start()
outputPath = self.window.lineEdit_outputFile.text()
if not os.path.dirname(outputPath): if not os.path.dirname(outputPath):
outputPath = os.path.join( outputPath = os.path.join(
os.path.expanduser("~"), outputPath) os.path.expanduser("~"), outputPath)
self.videoTask.emit( if outputPath and os.path.isdir(outputPath):
self.window.lineEdit_audioFile.text(), self.showMessage(
outputPath, msg='Chosen filename matches a directory, which '
self.core.selectedComponents) 'cannot be overwritten. Please choose a different '
'filename or move the directory.'
)
return
else: else:
self.showMessage( if not audioFile or not outputPath:
msg="You must select an audio file and output filename.") self.showMessage(
msg="You must select an audio file and output filename."
)
elif not self.core.selectedComponents:
self.showMessage(
msg="Not enough components."
)
return
self.canceled = False
self.progressBarUpdated(-1)
self.videoThread = QtCore.QThread(self)
self.videoWorker = video_thread.Worker(self)
self.videoWorker.moveToThread(self.videoThread)
self.videoWorker.videoCreated.connect(self.videoCreated)
self.videoWorker.progressBarUpdate.connect(self.progressBarUpdated)
self.videoWorker.progressBarSetText.connect(
self.progressBarSetText)
self.videoWorker.imageCreated.connect(self.showPreviewImage)
self.videoWorker.encoding.connect(self.changeEncodingStatus)
self.videoThread.start()
self.videoTask.emit(
audioFile,
outputPath,
self.core.selectedComponents)
def changeEncodingStatus(self, status): def changeEncodingStatus(self, status):
self.encoding = status
if status: if status:
self.window.pushButton_createVideo.setEnabled(False) self.window.pushButton_createVideo.setEnabled(False)
self.window.pushButton_Cancel.setEnabled(True) self.window.pushButton_Cancel.setEnabled(True)
@ -598,6 +626,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.window.stackedWidget.removeWidget(widget) self.window.stackedWidget.removeWidget(widget)
self.pages = [] self.pages = []
@disableWhenEncoding
def createNewProject(self): def createNewProject(self):
self.openSaveChangesDialog('starting a new project') self.openSaveChangesDialog('starting a new project')
@ -644,6 +673,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.core.createProjectFile(filename) self.core.createProjectFile(filename)
self.updateWindowTitle() self.updateWindowTitle()
@disableWhenEncoding
def openOpenProjectDialog(self): def openOpenProjectDialog(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName( filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self.window, "Open Project File", self.window, "Open Project File",
@ -669,6 +699,7 @@ class MainWindow(QtWidgets.QMainWindow):
if self.window.listWidget_componentList.count() == 0: if self.window.listWidget_componentList.count() == 0:
self.drawPreview() self.drawPreview()
self.autosave(True) self.autosave(True)
self.updateWindowTitle()
def showMessage(self, **kwargs): def showMessage(self, **kwargs):
parent = kwargs['parent'] if 'parent' in kwargs else self.window parent = kwargs['parent'] if 'parent' in kwargs else self.window

View File

@ -50,16 +50,15 @@ class Worker(QtCore.QObject):
components = nextPreviewInformation["components"] components = nextPreviewInformation["components"]
for component in reversed(components): for component in reversed(components):
try: try:
newFrame = component.previewRender(self)
frame = Image.alpha_composite( frame = Image.alpha_composite(
frame, newFrame) frame, component.previewRender(self)
except ValueError: )
except ValueError as e:
self.parent.showMessage( self.parent.showMessage(
msg="Bad frame returned by %s's previewRender method. " msg="Bad frame returned by %s's previewRender method. "
"This is a fatal error." % "This is a fatal error." %
str(component), str(component),
detail="bad frame: w%s, h%s" % ( detail=str(e)
newFrame.width, newFrame.height)
) )
quit(1) quit(1)

View File

@ -2,7 +2,6 @@ from PyQt5 import QtCore, QtGui, uic
from PyQt5.QtCore import pyqtSignal, pyqtSlot from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from PIL.ImageQt import ImageQt from PIL.ImageQt import ImageQt
import core
import numpy import numpy
import subprocess as sp import subprocess as sp
import sys import sys
@ -13,6 +12,8 @@ import time
from copy import copy from copy import copy
import signal import signal
import core
class Worker(QtCore.QObject): class Worker(QtCore.QObject):
@ -87,8 +88,10 @@ class Worker(QtCore.QObject):
self.encoding.emit(True) self.encoding.emit(True)
self.components = components self.components = components
self.outputFile = outputFile self.outputFile = outputFile
self.bgI = 0 # tracked video frame
self.reset() self.reset()
self.bgI = 0 # tracked video frame
self.width = int(self.core.settings.value('outputWidth')) self.width = int(self.core.settings.value('outputWidth'))
self.height = int(self.core.settings.value('outputHeight')) self.height = int(self.core.settings.value('outputHeight'))
progressBarValue = 0 progressBarValue = 0
@ -171,7 +174,7 @@ class Worker(QtCore.QObject):
self.staticComponents = {} self.staticComponents = {}
numComps = len(self.components) numComps = len(self.components)
for compNo, comp in enumerate(self.components): for compNo, comp in enumerate(self.components):
pStr = "Analyzing audio..." pStr = "Starting components..."
self.progressBarSetText.emit(pStr) self.progressBarSetText.emit(pStr)
properties = None properties = None
properties = comp.preFrameRender( properties = comp.preFrameRender(