aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortassaron2017-06-22 18:40:34 -0400
committertassaron2017-06-22 18:40:34 -0400
commit5c74d496a960042ed4a4279328dc81e23dfdc1d9 (patch)
treef11c4f6fe69ab202688b55100ec841bb24f8804f
parent82011de966f95afa88ec9e11e0ce86cbd04d5fc0 (diff)
preset-loading and basic args from commandline
also made some docstrings more informative
-rw-r--r--command.py30
-rw-r--r--components/__base__.py69
-rw-r--r--components/image.py17
-rw-r--r--components/original.py12
-rw-r--r--components/text.py10
-rw-r--r--components/video.py16
-rw-r--r--core.py22
-rw-r--r--main.py12
-rw-r--r--mainwindow.py1
-rw-r--r--video_thread.py29
10 files changed, 156 insertions, 62 deletions
diff --git a/command.py b/command.py
index d56c64b..97eddd2 100644
--- a/command.py
+++ b/command.py
@@ -36,7 +36,7 @@ class Command(QtCore.QObject):
help='open a project file (.avp)', nargs='?')
self.parser.add_argument(
'-c', '--comp', metavar=('LAYER', 'NAME', 'ARG'),
- help='create/edit component NAME at LAYER.'
+ help='create component NAME at LAYER.'
'"help" for information about possible args', nargs=3,
action='append')
@@ -80,12 +80,18 @@ class Command(QtCore.QObject):
if self.args.comp:
for comp in self.args.comp:
pos, name, arg = comp
+ try:
+ pos = int(pos)
+ except ValueError:
+ print(pos, 'is not a layer number.')
+ quit(1)
realName = self.parseCompName(name)
if not realName:
print(name, 'is not a valid component name.')
- quit()
+ quit(1)
modI = self.core.moduleIndexFor(realName)
- self.core.insertComponent(int(pos), modI, self)
+ i = self.core.insertComponent(pos, modI, self)
+ self.core.selectedComponents[i].command(arg)
self.createAudioVisualisation()
@@ -99,12 +105,12 @@ class Command(QtCore.QObject):
self.videoTask.emit(
self.args.input,
self.args.output,
- self.core.selectedComponents)
+ list(reversed(self.core.selectedComponents))
+ )
def videoCreated(self):
self.videoThread.quit()
self.videoThread.wait()
- self.cleanUp()
def showMessage(self, **kwargs):
print(kwargs['msg'])
@@ -114,22 +120,20 @@ class Command(QtCore.QObject):
def drawPreview(self, *args):
pass
- def cleanUp(self, *args):
- pass
-
def parseCompName(self, name):
'''Deduces a proper component name out of a commandline arg'''
- compFileNames = [ \
- os.path.splitext(os.path.basename(
- mod.__file__))[0] \
- for mod in self.core.modules \
- ]
if name.title() in self.core.compNames:
return name.title()
for compName in self.core.compNames:
if name.capitalize() in compName:
return compName
+
+ compFileNames = [ \
+ os.path.splitext(os.path.basename(
+ mod.__file__))[0] \
+ for mod in self.core.modules \
+ ]
for i, compFileName in enumerate(compFileNames):
if name.lower() in compFileName:
return self.core.compNames[i]
diff --git a/components/__base__.py b/components/__base__.py
index 88f22d4..e43a517 100644
--- a/components/__base__.py
+++ b/components/__base__.py
@@ -1,5 +1,6 @@
from PyQt4 import QtGui, QtCore
from PIL import Image
+import os
class Component(QtCore.QObject):
@@ -7,11 +8,12 @@ class Component(QtCore.QObject):
# modified = QtCore.pyqtSignal(int, bool)
- def __init__(self, moduleIndex, compPos):
+ def __init__(self, moduleIndex, compPos, core):
super().__init__()
self.currentPreset = None
self.moduleIndex = moduleIndex
self.compPos = compPos
+ self.core = core
def __str__(self):
return self.__doc__
@@ -32,24 +34,59 @@ class Component(QtCore.QObject):
# read your widget values, then call super().update()
def loadPreset(self, presetDict, presetName):
- '''Children should take (presetDict, presetName=None) as args'''
-
- # Use super().loadPreset(presetDict, presetName)
- # Then update your widgets using the preset dict
+ '''Subclasses take (presetDict, presetName=None) as args.
+ Must use super().loadPreset(presetDict, presetName) first,
+ then update self.page widgets using the preset dict.
+ '''
self.currentPreset = presetName \
if presetName != None else presetDict['preset']
- '''
- def savePreset(self):
- return {}
- '''
+
def preFrameRender(self, **kwargs):
+ '''Triggered only before a video is exported (video_thread.py)
+ self.worker = the video thread worker
+ self.completeAudioArray = a list of audio samples
+ self.sampleSize = number of audio samples per video frame
+ self.progressBarUpdate = signal to set progress bar number
+ self.progressBarSetText = signal to set progress bar text
+ Use the latter two signals to update the MainProgram if needed
+ for a long initialization procedure (i.e., for a visualizer)
+ '''
for var, value in kwargs.items():
exec('self.%s = value' % var)
+ def command(self, arg):
+ '''Configure a component using argument from the commandline.
+ Use super().command(arg) at the end of a subclass's method,
+ if no arguments are found in that method first
+ '''
+ if arg.startswith('preset='):
+ _, preset = arg.split('=', 1)
+ path = os.path.join(self.core.getPresetDir(self), preset)
+ if not os.path.exists(path):
+ print('Couldn\'t locate preset "%s"' % preset)
+ quit(1)
+ else:
+ print('Opening "%s" preset on layer %s' % \
+ (preset, self.compPos))
+ self.core.openPreset(path, self.compPos, preset)
+ else:
+ print(
+ 'To open a preset for this component:\n'
+ ' "preset=Preset Name"\n')
+ self.commandHelp()
+ quit(0)
+
+ def commandHelp(self):
+ '''Print help text for this Component's commandline arguments'''
+
def blankFrame(self, width, height):
return Image.new("RGBA", (width, height), (0, 0, 0, 0))
def pickColor(self):
+ '''Use color picker to get color input from the user,
+ and return this as an RGB string and QPushButton stylesheet.
+ In a subclass apply stylesheet to any color selection widgets
+ '''
dialog = QtGui.QColorDialog()
dialog.setOption(QtGui.QColorDialog.ShowAlphaChannel, True)
color = dialog.getColor()
@@ -63,7 +100,7 @@ class Component(QtCore.QObject):
return None, None
def RGBFromString(self, string):
- ''' turns an RGB string like "255, 255, 255" into a tuple '''
+ ''' Turns an RGB string like "255, 255, 255" into a tuple '''
try:
tup = tuple([int(i) for i in string.split(',')])
if len(tup) != 3:
@@ -83,14 +120,10 @@ class Component(QtCore.QObject):
self.parent = parent
page = uic.loadUi(os.path.join(
os.path.dirname(os.path.realpath(__file__)), 'example.ui'))
- # connect widgets signals
+ # --- connect widget signals here ---
self.page = page
return page
- def update(self):
- super().update()
- self.parent.drawPreview()
-
def previewRender(self, previewWorker):
width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight'))
@@ -102,12 +135,6 @@ class Component(QtCore.QObject):
height = int(self.worker.core.settings.value('outputHeight'))
image = Image.new("RGBA", (width, height), (0,0,0,0))
return image
-
- def cancel(self):
- self.canceled = True
-
- def reset(self):
- self.canceled = False
'''
class BadComponentInit(Exception):
diff --git a/components/image.py b/components/image.py
index b6aa29b..d0e1894 100644
--- a/components/image.py
+++ b/components/image.py
@@ -92,3 +92,20 @@ class Component(__base__.Component):
self.settings.setValue("backgroundDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename)
self.update()
+
+ def command(self, arg):
+ if not arg.startswith('preset='):
+ if os.path.exists(arg):
+ try:
+ Image.open(arg)
+ self.imagePath = arg
+ self.stretched = True
+ return True
+ except OSError as e:
+ print("Not a supported image format")
+ quit(1)
+ super().command(arg)
+
+ def commandHelp(self):
+ print('Give a complete filepath to an image to load that '
+ 'image with default settings.')
diff --git a/components/original.py b/components/original.py
index 5e2f9d4..328d64f 100644
--- a/components/original.py
+++ b/components/original.py
@@ -183,3 +183,15 @@ class Component(__base__.Component):
return im
+ def command(self, arg):
+ if not arg.startswith('preset='):
+ if arg == 'classic':
+ self.layout = 0; return
+ elif arg == 'split':
+ self.layout = 1; return
+ elif arg == 'bottom':
+ self.layout = 2; return
+ super().command(arg)
+
+ def commandHelp(self):
+ print('Give a layout name: classic, split, or bottom')
diff --git a/components/text.py b/components/text.py
index f8ef7b3..6c465b1 100644
--- a/components/text.py
+++ b/components/text.py
@@ -146,3 +146,13 @@ class Component(__base__.Component):
return
self.page.lineEdit_textColor.setText(RGBstring)
self.page.pushButton_textColor.setStyleSheet(btnStyle)
+
+ def commandHelp(self, arg):
+ print('Enter a string to use as centred white text. '
+ 'Use quotes around the string to escape spaces.')
+
+ def command(self, arg):
+ if not arg.startswith('preset='):
+ self.title = arg
+ return True
+ super().command(arg)
diff --git a/components/video.py b/components/video.py
index 3d43a18..dd385b4 100644
--- a/components/video.py
+++ b/components/video.py
@@ -221,6 +221,22 @@ class Component(__base__.Component):
width, height = scale(self.scale, width, height, int)
self.chunkSize = 4*width*height
+ def command(self, arg):
+ if not arg.startswith('preset='):
+ if os.path.exists(arg):
+ if os.path.splitext(arg)[1] in self.core.videoFormats:
+ self.videoPath = arg
+ self.scale = 100
+ return True
+ else:
+ print("Not a supported video format")
+ quit(1)
+ super().command(arg)
+
+ def commandHelp(self):
+ print('Give a complete filepath to a video to load that '
+ 'video with default settings.')
+
def scale(scale, width, height, returntype=None):
width = (float(width) / 100.0) * float(scale)
height = (float(height) / 100.0) * float(scale)
diff --git a/core.py b/core.py
index 2dde464..42eb44e 100644
--- a/core.py
+++ b/core.py
@@ -86,7 +86,7 @@ class Core():
return None
component = self.modules[moduleIndex].Component(
- moduleIndex, compPos)
+ moduleIndex, compPos, self)
self.selectedComponents.insert(
compPos,
component)
@@ -142,6 +142,10 @@ class Core():
self.savedPresets[presetName] = dict(saveValueStore)
return True
+ def getPresetDir(self, comp):
+ return os.path.join(
+ self.presetDir, str(comp), str(comp.version()))
+
def getPreset(self, filepath):
'''Returns the preset dict stored at this filepath'''
if not os.path.exists(filepath):
@@ -153,10 +157,11 @@ class Core():
return saveValueStore
def openProject(self, loader, filepath):
- '''loader is the object calling this method which must have
- its own showMessage(**kwargs) method for displaying errors'''
+ ''' loader is the object calling this method which must have
+ its own showMessage(**kwargs) method for displaying errors.
+ '''
errcode, data = self.parseAvFile(filepath)
- print(data)
+ #print(data)
if errcode == 0:
try:
for i, tup in enumerate(data['Components']):
@@ -224,12 +229,14 @@ class Core():
def parseAvFile(self, filepath):
'''Parses an avp (project) or avl (preset package) file.
- Returns data usable by another method.'''
+ Returns dictionary with section names as the keys, each one
+ contains a list of tuples: (compName, version, compPresetDict)
+ '''
data = {}
try:
with open(filepath, 'r') as f:
def parseLine(line):
- '''Decides if a given avp or avl line is a section header'''
+ '''Decides if a file line is a section header'''
validSections = ('Components')
line = line.strip()
newSection = ''
@@ -313,8 +320,7 @@ class Core():
def createPresetFile(
self, compName, vers, presetName, saveValueStore, filepath=''):
'''Create a preset file (.avl) at filepath using args.
- Or if filepath is empty, create an internal preset using
- the args for the filepath.'''
+ Or if filepath is empty, create an internal preset using args'''
if not filepath:
dirname = os.path.join(self.presetDir, compName, str(vers))
if not os.path.exists(dirname):
diff --git a/main.py b/main.py
index 140392c..e04d002 100644
--- a/main.py
+++ b/main.py
@@ -1,8 +1,6 @@
from PyQt4 import QtGui, uic
import sys
import os
-import atexit
-import signal
import core
import preview_thread
@@ -32,7 +30,7 @@ def LoadDefaultSettings(self):
}
for parm, value in default.items():
- print(parm, self.settings.value(parm))
+ #print(parm, self.settings.value(parm))
if self.settings.value(parm) is None:
self.settings.setValue(parm, value)
@@ -62,6 +60,8 @@ if __name__ == "__main__":
elif mode == 'gui':
from mainwindow import *
+ import atexit
+ import signal
window = uic.loadUi(os.path.join(
os.path.dirname(os.path.realpath(__file__)), "mainwindow.ui"))
@@ -73,10 +73,10 @@ if __name__ == "__main__":
window.resize(window.width() * (dpi / 96), window.height() * (dpi / 96))
# window.verticalLayout_2.setContentsMargins(0, topMargin, 0, 0)
+ signal.signal(signal.SIGINT, main.cleanUp)
+ atexit.register(main.cleanUp)
+
main = MainWindow(window, proj)
# applicable to both modes
- signal.signal(signal.SIGINT, main.cleanUp)
- atexit.register(main.cleanUp)
-
sys.exit(app.exec_())
diff --git a/mainwindow.py b/mainwindow.py
index 2a8762d..6023831 100644
--- a/mainwindow.py
+++ b/mainwindow.py
@@ -597,7 +597,6 @@ class MainWindow(QtCore.QObject):
self.openProject(filename)
def openProject(self, filepath, prompt=True):
- print('opening', filepath)
if not filepath or not os.path.exists(filepath) \
or not filepath.endswith('.avp'):
self.updateWindowTitle()
diff --git a/video_thread.py b/video_thread.py
index 2255259..e6c6531 100644
--- a/video_thread.py
+++ b/video_thread.py
@@ -29,7 +29,7 @@ class Worker(QtCore.QObject):
self.modules = parent.core.modules
self.parent = parent
parent.videoTask.connect(self.createVideo)
- self.sampleSize = 1470
+ self.sampleSize = 1470 # 44100 / 30 = 1470
self.canceled = False
self.error = False
self.stopped = False
@@ -99,7 +99,8 @@ class Worker(QtCore.QObject):
# test if user has libfdk_aac
encoders = sp.check_output(
- self.core.FFMPEG_BIN + " -encoders -hide_banner", shell=True)
+ self.core.FFMPEG_BIN + " -encoders -hide_banner",
+ shell=True)
encoders = encoders.decode("utf-8")
@@ -120,15 +121,15 @@ class Worker(QtCore.QObject):
vencoders = options['video-codecs'][vcodec]
aencoders = options['audio-codecs'][acodec]
- print(encoders)
+ #print(encoders)
for encoder in vencoders:
- print(encoder)
+ #print(encoder)
if encoder in encoders:
vencoder = encoder
break
for encoder in aencoders:
- print(encoder)
+ #print(encoder)
if encoder in encoders:
aencoder = encoder
break
@@ -161,16 +162,15 @@ class Worker(QtCore.QObject):
ffmpegCommand.append('-2')
ffmpegCommand.append(outputFile)
- self.out_pipe = sp.Popen(
- ffmpegCommand, stdin=sp.PIPE, stdout=sys.stdout, stderr=sys.stdout)
- # create video for output
+ # ### Now start creating video for output ###
numpy.seterr(divide='ignore')
- # initialize components
- print('loaded components:',
- ["%s%s" % (num, str(component)) for num,
- component in enumerate(self.components)])
+ # Call preFrameRender on all components
+ print('Loaded Components:', ", ".join(
+ ["%s) %s" % (num, str(component)) \
+ for num, component in enumerate(reversed(self.components))
+ ]))
self.staticComponents = {}
numComps = len(self.components)
for compNo, comp in enumerate(self.components):
@@ -190,14 +190,17 @@ class Worker(QtCore.QObject):
comp.frameRender(compNo, 0, 0))
self.progressBarUpdate.emit(100)
+ # Create ffmpeg pipe and queues for frames
+ self.out_pipe = sp.Popen(
+ ffmpegCommand, stdin=sp.PIPE, stdout=sys.stdout, stderr=sys.stdout)
self.compositeQueue = Queue()
self.compositeQueue.maxsize = 20
self.renderQueue = PriorityQueue()
self.renderQueue.maxsize = 20
self.previewQueue = PriorityQueue()
- self.renderThreads = []
# Threads to render frames and send them back here for piping out
+ self.renderThreads = []
for i in range(3):
self.renderThreads.append(
Thread(target=self.renderNode, name="Render Thread"))