aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.py54
-rw-r--r--src/components/image.py4
-rw-r--r--src/components/video.py11
-rw-r--r--src/core.py76
-rw-r--r--src/mainwindow.py37
-rw-r--r--src/presetmanager.py4
-rw-r--r--src/preview_thread.py3
7 files changed, 145 insertions, 44 deletions
diff --git a/src/command.py b/src/command.py
index 2f71f31..3eea1b6 100644
--- a/src/command.py
+++ b/src/command.py
@@ -1,5 +1,4 @@
-from PyQt4 import QtCore
-from PyQt4.QtCore import QSettings
+from PyQt5 import QtCore
import argparse
import os
import sys
@@ -24,13 +23,20 @@ class Command(QtCore.QObject):
epilog='EXAMPLE COMMAND: main.py myvideotemplate.avp '
'-i ~/Music/song.mp3 -o ~/video.mp4 '
'-c 0 image path=~/Pictures/thisWeeksPicture.jpg '
- '-c 1 video "preset=My Logo" -c 2 vis layout=classic')
+ '-c 1 video "preset=My Logo" -c 2 vis layout=classic'
+ )
self.parser.add_argument(
'-i', '--input', metavar='SOUND',
- help='input audio file')
+ help='input audio file'
+ )
self.parser.add_argument(
'-o', '--output', metavar='OUTPUT',
- help='output video file')
+ help='output video file'
+ )
+ self.parser.add_argument(
+ '-e', '--export', action='store_true',
+ help='use input and output files from project file'
+ )
# optional arguments
self.parser.add_argument(
@@ -43,12 +49,19 @@ class Command(QtCore.QObject):
nargs='*', action='append')
self.args = self.parser.parse_args()
- self.settings = QSettings(
- os.path.join(self.dataDir, 'settings.ini'), QSettings.IniFormat)
+ self.settings = self.core.settings
LoadDefaultSettings(self)
if self.args.projpath:
- self.core.openProject(self, self.args.projpath)
+ projPath = self.args.projpath
+ if not os.path.dirname(projPath):
+ projPath = os.path.join(
+ self.settings.value("projectDir"),
+ projPath
+ )
+ if not projPath.endswith('.avp'):
+ projPath += '.avp'
+ self.core.openProject(self, projPath)
self.core.selectedComponents = list(
reversed(self.core.selectedComponents))
self.core.componentListChanged()
@@ -72,13 +85,28 @@ class Command(QtCore.QObject):
for arg in args:
self.core.selectedComponents[i].command(arg)
- if self.args.input and self.args.output:
- self.createAudioVisualisation()
+ if self.args.export and self.args.projpath:
+ errcode, data = self.core.parseAvFile(projPath)
+ for key, value in data['WindowFields']:
+ if 'outputFile' in key:
+ output = value
+ if not os.path.dirname(value):
+ output = os.path.join(
+ os.path.expanduser('~'),
+ output
+ )
+ if 'audioFile' in key:
+ input = value
+ self.createAudioVisualisation(input, output)
+
+ elif self.args.input and self.args.output:
+ self.createAudioVisualisation(self.args.input, self.args.output)
+
elif 'help' not in sys.argv:
self.parser.print_help()
quit(1)
- def createAudioVisualisation(self):
+ def createAudioVisualisation(self, input, output):
self.videoThread = QtCore.QThread(self)
self.videoWorker = video_thread.Worker(self)
self.videoWorker.moveToThread(self.videoThread)
@@ -86,8 +114,8 @@ class Command(QtCore.QObject):
self.videoThread.start()
self.videoTask.emit(
- self.args.input,
- self.args.output,
+ input,
+ output,
list(reversed(self.core.selectedComponents))
)
diff --git a/src/components/image.py b/src/components/image.py
index 143ae59..4bb33b1 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -83,12 +83,12 @@ class Component(__base__.Component):
}
def pickImage(self):
- imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
+ imgDir = self.settings.value("componentDir", os.path.expanduser("~"))
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self.page, "Choose Image", imgDir,
"Image Files (%s)" % " ".join(self.imageFormats))
if filename:
- self.settings.setValue("backgroundDir", os.path.dirname(filename))
+ self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename)
self.update()
diff --git a/src/components/video.py b/src/components/video.py
index 44f88a5..02bb44b 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -88,9 +88,10 @@ class Video:
self.parent.showMessage(
msg='%s couldn\'t be loaded. '
'This is a fatal error.' % os.path.basename(
- self.videoPath
- ),
- detail=str(e)
+ self.videoPath
+ ),
+ detail=str(e),
+ icon='Warning'
)
self.parent.stopVideo()
break
@@ -188,13 +189,13 @@ class Component(__base__.Component):
}
def pickVideo(self):
- imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
+ imgDir = self.settings.value("componentDir", os.path.expanduser("~"))
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self.page, "Choose Video",
imgDir, "Video Files (%s)" % " ".join(self.videoFormats)
)
if filename:
- self.settings.setValue("backgroundDir", os.path.dirname(filename))
+ self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_video.setText(filename)
self.update()
diff --git a/src/core.py b/src/core.py
index fdba1c4..2994a24 100644
--- a/src/core.py
+++ b/src/core.py
@@ -30,6 +30,10 @@ class Core():
# unfrozen
self.wd = os.path.dirname(os.path.realpath(__file__))
self.componentsPath = os.path.join(self.wd, 'components')
+ self.settings = QtCore.QSettings(
+ os.path.join(self.dataDir, 'settings.ini'),
+ QtCore.QSettings.IniFormat
+ )
self.loadEncoderOptions()
self.videoFormats = Core.appendUppercase([
@@ -169,13 +173,23 @@ class Core():
its own showMessage(**kwargs) method for displaying errors.
'''
if not os.path.exists(filepath):
- loader.showMessage(msg='Project file not found')
+ loader.showMessage(msg='Project file not found.')
return
errcode, data = self.parseAvFile(filepath)
if errcode == 0:
try:
- for i, tup in enumerate(data['Components']):
+ if hasattr(loader, 'window'):
+ for widget, value in data['WindowFields']:
+ widget = eval('loader.window.%s' % widget)
+ widget.blockSignals(True)
+ widget.setText(value)
+ widget.blockSignals(False)
+
+ for key, value in data['Settings']:
+ self.settings.setValue(key, value)
+
+ for tup in data['Components']:
name, vers, preset = tup
clearThis = False
modified = False
@@ -213,7 +227,7 @@ class Core():
preset['preset']
)
except KeyError as e:
- print('%s missing value %s' % (
+ print('%s missing value: %s' % (
self.selectedComponents[i], e)
)
@@ -221,23 +235,26 @@ class Core():
self.clearPreset(i)
if hasattr(loader, 'updateComponentTitle'):
loader.updateComponentTitle(i, modified)
+
except:
errcode = 1
data = sys.exc_info()
if errcode == 1:
- typ, value, _ = data
- if typ.__name__ == KeyError:
+ typ, value, tb = data
+ if typ.__name__ == 'KeyError':
# probably just an old version, still loadable
print('file missing value: %s' % value)
return
if hasattr(loader, 'createNewProject'):
loader.createNewProject()
- msg = '%s: %s' % (typ.__name__, value)
+ import traceback
+ msg = '%s: %s\n\nTraceback:\n' % (typ.__name__, value)
+ msg += "\n".join(traceback.format_tb(tb))
loader.showMessage(
msg="Project file '%s' is corrupted." % filepath,
showCancel=False,
- icon=QtGui.QMessageBox.Warning,
+ icon='Warning',
detail=msg)
def parseAvFile(self, filepath):
@@ -245,12 +262,16 @@ class Core():
Returns dictionary with section names as the keys, each one
contains a list of tuples: (compName, version, compPresetDict)
'''
- data = {}
+ validSections = (
+ 'Components',
+ 'Settings',
+ 'WindowFields'
+ )
+ data = {sect: [] for sect in validSections}
try:
with open(filepath, 'r') as f:
def parseLine(line):
'''Decides if a file line is a section header'''
- validSections = ('Components')
line = line.strip()
newSection = ''
@@ -266,7 +287,6 @@ class Core():
line, newSection = parseLine(line)
if newSection:
section = str(newSection)
- data[section] = []
continue
if line and section == 'Components':
if i == 0:
@@ -283,6 +303,10 @@ class Core():
lastCompPreset
))
i = 0
+ elif line and section:
+ key, value = line.split('=', 1)
+ data[section].append((key, value.strip()))
+
return 0, data
except:
return 1, sys.exc_info()
@@ -354,8 +378,22 @@ class Core():
f.write('%s\n' % str(vers))
f.write(Core.presetToString(saveValueStore))
- def createProjectFile(self, filepath):
+ def createProjectFile(self, filepath, window=None):
'''Create a project file (.avp) using the current program state'''
+ forbiddenSettingsKeys = [
+ 'currentProject',
+ 'outputAudioBitrate',
+ 'outputAudioCodec',
+ 'outputContainer',
+ 'outputFormat',
+ 'outputFrameRate',
+ 'outputHeight',
+ 'outputPreset',
+ 'outputVideoBitrate',
+ 'outputVideoCodec',
+ 'outputVideoFormat',
+ 'outputWidth',
+ ]
try:
if not filepath.endswith(".avp"):
filepath += '.avp'
@@ -363,12 +401,28 @@ class Core():
os.remove(filepath)
with open(filepath, 'w') as f:
print('creating %s' % filepath)
+
f.write('[Components]\n')
for comp in self.selectedComponents:
saveValueStore = comp.savePreset()
f.write('%s\n' % str(comp))
f.write('%s\n' % str(comp.version()))
f.write('%s\n' % Core.presetToString(saveValueStore))
+
+ f.write('\n[Settings]\n')
+ for key in self.settings.allKeys():
+ if key not in forbiddenSettingsKeys:
+ f.write('%s=%s\n' % (key, self.settings.value(key)))
+
+ if window:
+ f.write('\n[WindowFields]\n')
+ f.write(
+ 'lineEdit_audioFile=%s\n'
+ 'lineEdit_outputFile=%s\n' % (
+ window.lineEdit_audioFile.text(),
+ window.lineEdit_outputFile.text()
+ )
+ )
return True
except:
return False
diff --git a/src/mainwindow.py b/src/mainwindow.py
index 76c2b62..203992b 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -1,6 +1,5 @@
from queue import Queue
from PyQt5 import QtCore, QtGui, uic, QtWidgets
-from PyQt5.QtCore import QSettings, Qt
from PyQt5.QtWidgets import QMenu, QShortcut
import sys
import os
@@ -27,7 +26,9 @@ class PreviewWindow(QtWidgets.QLabel):
painter = QtGui.QPainter(self)
point = QtCore.QPoint(0, 0)
scaledPix = self.pixmap.scaled(
- size, Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation)
+ size,
+ QtCore.Qt.KeepAspectRatio,
+ transformMode=QtCore.Qt.SmoothTransformation)
# start painting the label from left upper corner
point.setX((size.width() - scaledPix.width())/2)
@@ -59,8 +60,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Create data directory, load/create settings
self.dataDir = self.core.dataDir
self.autosavePath = os.path.join(self.dataDir, 'autosave.avp')
- self.settings = QSettings(
- os.path.join(self.dataDir, 'settings.ini'), QSettings.IniFormat)
+ self.settings = self.core.settings
LoadDefaultSettings(self)
self.presetManager = PresetManager(
uic.loadUi(
@@ -94,6 +94,13 @@ class MainWindow(QtWidgets.QMainWindow):
window.toolButton_selectOutputFile.clicked.connect(
self.openOutputFileDialog)
+ def changedField():
+ self.autosave()
+ self.updateWindowTitle()
+
+ window.lineEdit_audioFile.textChanged.connect(changedField)
+ window.lineEdit_outputFile.textChanged.connect(changedField)
+
window.progressBar_createVideo.setValue(0)
window.pushButton_createVideo.clicked.connect(
@@ -222,7 +229,9 @@ class MainWindow(QtWidgets.QMainWindow):
project += '.avp'
# open a project from the commandline
if not os.path.dirname(project):
- project = os.path.join(os.path.expanduser('~'), project)
+ project = os.path.join(
+ self.settings.value("projectDir"), project
+ )
self.currentProject = project
self.settings.setValue("currentProject", project)
if os.path.exists(self.autosavePath):
@@ -359,7 +368,7 @@ class MainWindow(QtWidgets.QMainWindow):
if os.path.exists(self.autosavePath):
os.remove(self.autosavePath)
elif force or time.time() - self.lastAutosave >= 0.1:
- self.core.createProjectFile(self.autosavePath)
+ self.core.createProjectFile(self.autosavePath, self.window)
self.lastAutosave = time.time()
def autosaveExists(self, identical=True):
@@ -426,7 +435,8 @@ class MainWindow(QtWidgets.QMainWindow):
self.showMessage(
msg='Chosen filename matches a directory, which '
'cannot be overwritten. Please choose a different '
- 'filename or move the directory.'
+ 'filename or move the directory.',
+ icon='Warning',
)
return
else:
@@ -625,6 +635,13 @@ class MainWindow(QtWidgets.QMainWindow):
for widget in self.pages:
self.window.stackedWidget.removeWidget(widget)
self.pages = []
+ for field in (
+ self.window.lineEdit_audioFile,
+ self.window.lineEdit_outputFile
+ ):
+ field.blockSignals(True)
+ field.setText('')
+ field.blockSignals(False)
@disableWhenEncoding
def createNewProject(self):
@@ -637,7 +654,7 @@ class MainWindow(QtWidgets.QMainWindow):
def saveCurrentProject(self):
if self.currentProject:
- self.core.createProjectFile(self.currentProject)
+ self.core.createProjectFile(self.currentProject, self.window)
self.updateWindowTitle()
else:
self.openSaveProjectDialog()
@@ -670,7 +687,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.settings.setValue("projectDir", os.path.dirname(filename))
self.settings.setValue("currentProject", filename)
self.currentProject = filename
- self.core.createProjectFile(filename)
+ self.core.createProjectFile(filename, self.window)
self.updateWindowTitle()
@disableWhenEncoding
@@ -707,7 +724,7 @@ class MainWindow(QtWidgets.QMainWindow):
msg.setModal(True)
msg.setText(kwargs['msg'])
msg.setIcon(
- kwargs['icon']
+ eval('QtWidgets.QMessageBox.%s' % kwargs['icon'])
if 'icon' in kwargs else QtWidgets.QMessageBox.Information
)
msg.setDetailedText(kwargs['detail'] if 'detail' in kwargs else None)
diff --git a/src/presetmanager.py b/src/presetmanager.py
index 069bf62..3ab49ef 100644
--- a/src/presetmanager.py
+++ b/src/presetmanager.py
@@ -176,7 +176,7 @@ class PresetManager(QtWidgets.QDialog):
msg="%s already exists! Overwrite it?" %
os.path.basename(path),
showCancel=True,
- icon=QtWidgets.QMessageBox.Warning,
+ icon='Warning',
parent=window)
if not ch:
# user clicked cancel
@@ -209,7 +209,7 @@ class PresetManager(QtWidgets.QDialog):
ch = self.parent.showMessage(
msg='Really delete %s?' % name,
showCancel=True,
- icon=QtWidgets.QMessageBox.Warning,
+ icon='Warning',
parent=self.window
)
if not ch:
diff --git a/src/preview_thread.py b/src/preview_thread.py
index 769656b..e58f04e 100644
--- a/src/preview_thread.py
+++ b/src/preview_thread.py
@@ -58,7 +58,8 @@ class Worker(QtCore.QObject):
msg="Bad frame returned by %s's previewRender method. "
"This is a fatal error." %
str(component),
- detail=str(e)
+ detail=str(e),
+ icon='Warning'
)
quit(1)