From e92e9d79f95ad67e83074ef318278c3486601eac Mon Sep 17 00:00:00 2001 From: DH4 Date: Fri, 23 Jun 2017 17:38:05 -0500 Subject: QT5 Conversion + Directory Structure --- src/core.py | 477 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 src/core.py (limited to 'src/core.py') diff --git a/src/core.py b/src/core.py new file mode 100644 index 0000000..bb5d351 --- /dev/null +++ b/src/core.py @@ -0,0 +1,477 @@ +import sys +import io +import os +from PyQt5 import QtCore, QtGui, uic +from os.path import expanduser +import subprocess as sp +import numpy +from PIL import Image +from shutil import rmtree +import time +from collections import OrderedDict +import json +from importlib import import_module +from PyQt5.QtCore import QStandardPaths +import string + + +class Core(): + + def __init__(self): + self.FFMPEG_BIN = self.findFfmpeg() + self.dataDir = QStandardPaths.writableLocation( + QStandardPaths.AppConfigLocation + ) + self.presetDir = os.path.join(self.dataDir, 'presets') + if getattr(sys, 'frozen', False): + # frozen + self.wd = os.path.dirname(sys.executable) + else: + # unfrozen + self.wd = os.path.dirname(os.path.realpath(__file__)) + + self.loadEncoderOptions() + self.videoFormats = Core.appendUppercase([ + '*.mp4', + '*.mov', + '*.mkv', + '*.avi', + '*.webm', + '*.flv', + ]) + self.audioFormats = Core.appendUppercase([ + '*.mp3', + '*.wav', + '*.ogg', + '*.fla', + '*.flac', + '*.aac', + ]) + self.imageFormats = Core.appendUppercase([ + '*.png', + '*.jpg', + '*.tif', + '*.tiff', + '*.gif', + '*.bmp', + '*.ico', + '*.xbm', + '*.xpm', + ]) + + self.findComponents() + self.selectedComponents = [] + # copies of named presets to detect modification + self.savedPresets = {} + + def findComponents(self): + def findComponents(): + srcPath = os.path.join(self.wd, 'components') + if os.path.exists(srcPath): + for f in sorted(os.listdir(srcPath)): + name, ext = os.path.splitext(f) + if name.startswith("__"): + continue + elif ext == '.py': + yield name + self.modules = [ + import_module('components.%s' % name) + for name in findComponents() + ] + self.moduleIndexes = [i for i in range(len(self.modules))] + self.compNames = [mod.Component.__doc__ for mod in self.modules] + + def componentListChanged(self): + for i, component in enumerate(self.selectedComponents): + component.compPos = i + + def insertComponent(self, compPos, moduleIndex, loader): + '''Creates a new component''' + if compPos < 0 or compPos > len(self.selectedComponents): + compPos = len(self.selectedComponents) + if len(self.selectedComponents) > 50: + return None + + component = self.modules[moduleIndex].Component( + moduleIndex, compPos, self) + self.selectedComponents.insert( + compPos, + component) + self.componentListChanged() + + # init component's widget for loading/saving presets + self.selectedComponents[compPos].widget(loader) + self.updateComponent(compPos) + + if hasattr(loader, 'insertComponent'): + loader.insertComponent(compPos) + return compPos + + def moveComponent(self, startI, endI): + comp = self.selectedComponents.pop(startI) + self.selectedComponents.insert(endI, comp) + + self.componentListChanged() + return endI + + def removeComponent(self, i): + self.selectedComponents.pop(i) + self.componentListChanged() + + def clearComponents(self): + self.selectedComponents = list() + self.componentListChanged() + + def updateComponent(self, i): + # print('updating %s' % self.selectedComponents[i]) + self.selectedComponents[i].update() + + def moduleIndexFor(self, compName): + index = self.compNames.index(compName) + return self.moduleIndexes[index] + + def clearPreset(self, compIndex): + self.selectedComponents[compIndex].currentPreset = None + + def openPreset(self, filepath, compIndex, presetName): + '''Applies a preset to a specific component''' + saveValueStore = self.getPreset(filepath) + if not saveValueStore: + return False + try: + self.selectedComponents[compIndex].loadPreset( + saveValueStore, + presetName + ) + except KeyError as e: + print('preset missing value: %s' % e) + + 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): + return False + with open(filepath, 'r') as f: + for line in f: + saveValueStore = Core.presetFromString(line.strip()) + break + 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. + ''' + if not os.path.exists(filepath): + loader.showMessage(msg='Project file not found') + return + + errcode, data = self.parseAvFile(filepath) + if errcode == 0: + try: + for i, tup in enumerate(data['Components']): + name, vers, preset = tup + clearThis = False + + # add loaded named presets to savedPresets dict + if 'preset' in preset and preset['preset'] != None: + nam = preset['preset'] + filepath2 = os.path.join( + self.presetDir, name, str(vers), nam) + origSaveValueStore = self.getPreset(filepath2) + if origSaveValueStore: + self.savedPresets[nam] = dict(origSaveValueStore) + else: + # saved preset was renamed or deleted + clearThis = True + + # create the actual component object & get its index + i = self.insertComponent( + -1, + self.moduleIndexFor(name), + loader) + if i == None: + loader.showMessage(msg="Too many components!") + break + + try: + if 'preset' in preset and preset['preset'] != None: + self.selectedComponents[i].loadPreset( + preset + ) + else: + self.selectedComponents[i].loadPreset( + preset, + preset['preset'] + ) + except KeyError as e: + print('%s missing value %s' % + (self.selectedComponents[i], e)) + + if clearThis: + self.clearPreset(i) + if hasattr(loader, 'updateComponentTitle'): + loader.updateComponentTitle(i) + except: + errcode = 1 + data = sys.exc_info() + + + if errcode == 1: + typ, value, _ = 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) + loader.showMessage( + msg="Project file '%s' is corrupted." % filepath, + showCancel=False, + icon=QtGui.QMessageBox.Warning, + detail=msg) + + def parseAvFile(self, filepath): + '''Parses an avp (project) or avl (preset package) file. + 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 file line is a section header''' + validSections = ('Components') + line = line.strip() + newSection = '' + + if line.startswith('[') and line.endswith(']') \ + and line[1:-1] in validSections: + newSection = line[1:-1] + + return line, newSection + + section = '' + i = 0 + for line in f: + line, newSection = parseLine(line) + if newSection: + section = str(newSection) + data[section] = [] + continue + if line and section == 'Components': + if i == 0: + lastCompName = str(line) + i += 1 + elif i == 1: + lastCompVers = str(line) + i += 1 + elif i == 2: + lastCompPreset = Core.presetFromString(line) + data[section].append( + (lastCompName, + lastCompVers, + lastCompPreset) + ) + i = 0 + return 0, data + except: + return 1, sys.exc_info() + + def importPreset(self, filepath): + errcode, data = self.parseAvFile(filepath) + returnList = [] + if errcode == 0: + name, vers, preset = data['Components'][0] + presetName = preset['preset'] \ + if preset['preset'] else os.path.basename(filepath)[:-4] + newPath = os.path.join( + self.presetDir, + name, + vers, + presetName + ) + if os.path.exists(newPath): + return False, newPath + preset['preset'] = presetName + self.createPresetFile( + name, vers, presetName, preset + ) + return True, presetName + elif errcode == 1: + # TODO: an error message + return False, '' + + def exportPreset(self, exportPath, compName, vers, origName): + internalPath = os.path.join(self.presetDir, compName, str(vers), origName) + if not os.path.exists(internalPath): + return + if os.path.exists(exportPath): + os.remove(exportPath) + with open(internalPath, 'r') as f: + internalData = [line for line in f] + try: + saveValueStore = Core.presetFromString(internalData[0].strip()) + self.createPresetFile( + compName, vers, + origName, saveValueStore, + exportPath + ) + return True + except: + return False + + 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 args''' + if not filepath: + dirname = os.path.join(self.presetDir, compName, str(vers)) + if not os.path.exists(dirname): + os.makedirs(dirname) + filepath = os.path.join(dirname, presetName) + internal = True + else: + if not filepath.endswith('.avl'): + filepath += '.avl' + internal = False + + with open(filepath, 'w') as f: + if not internal: + f.write('[Components]\n') + f.write('%s\n' % compName) + f.write('%s\n' % str(vers)) + f.write(Core.presetToString(saveValueStore)) + + def createProjectFile(self, filepath): + '''Create a project file (.avp) using the current program state''' + try: + if not filepath.endswith(".avp"): + filepath += '.avp' + if os.path.exists(filepath): + 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)) + return True + except: + return False + + def loadEncoderOptions(self): + file_path = os.path.join(self.wd, 'encoder-options.json') + with open(file_path) as json_file: + self.encoder_options = json.load(json_file) + + def findFfmpeg(self): + if sys.platform == "win32": + return "ffmpeg.exe" + else: + try: + with open(os.devnull, "w") as f: + sp.check_call(['ffmpeg', '-version'], stdout=f, stderr=f) + return "ffmpeg" + except: + return "avconv" + + def readAudioFile(self, filename, parent): + command = [self.FFMPEG_BIN, '-i', filename] + + try: + fileInfo = sp.check_output(command, stderr=sp.STDOUT, shell=False) + except sp.CalledProcessError as ex: + fileInfo = ex.output + pass + + info = fileInfo.decode("utf-8").split('\n') + for line in info: + if 'Duration' in line: + d = line.split(',')[0] + d = d.split(' ')[3] + d = d.split(':') + duration = float(d[0])*3600 + float(d[1])*60 + float(d[2]) + + command = [ + self.FFMPEG_BIN, + '-i', filename, + '-f', 's16le', + '-acodec', 'pcm_s16le', + '-ar', '44100', # ouput will have 44100 Hz + '-ac', '1', # mono (set to '2' for stereo) + '-'] + in_pipe = sp.Popen( + command, stdout=sp.PIPE, stderr=sp.DEVNULL, bufsize=10**8) + + completeAudioArray = numpy.empty(0, dtype="int16") + + progress = 0 + lastPercent = None + while True: + if self.canceled: + break + # read 2 seconds of audio + progress = progress + 4 + raw_audio = in_pipe.stdout.read(88200*4) + if len(raw_audio) == 0: + break + audio_array = numpy.fromstring(raw_audio, dtype="int16") + completeAudioArray = numpy.append(completeAudioArray, audio_array) + + percent = int(100*(progress/duration)) + if percent >= 100: + percent = 100 + + if lastPercent != percent: + string = 'Loading audio file: '+str(percent)+'%' + parent.progressBarSetText.emit(string) + parent.progressBarUpdate.emit(percent) + + lastPercent = percent + + in_pipe.kill() + in_pipe.wait() + + # add 0s the end + completeAudioArrayCopy = numpy.zeros( + len(completeAudioArray) + 44100, dtype="int16") + completeAudioArrayCopy[:len(completeAudioArray)] = completeAudioArray + completeAudioArray = completeAudioArrayCopy + + return completeAudioArray + + def cancel(self): + self.canceled = True + + def reset(self): + self.canceled = False + + @staticmethod + def badName(name): + '''Returns whether a name contains non-alphanumeric chars''' + return any([letter in string.punctuation for letter in name]) + + @staticmethod + def presetToString(dictionary): + '''Alphabetizes a dict into OrderedDict & returns string repr''' + return repr(OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))) + + @staticmethod + def presetFromString(string): + '''Turns a string repr of OrderedDict into a regular dict''' + return dict(eval(string)) + + @staticmethod + def appendUppercase(lst): + for form, i in zip(lst, range(len(lst))): + lst.append(form.upper()) + return lst -- cgit v1.2.3 From 680214f5180a12f2250d8e266df9375ce99b9f80 Mon Sep 17 00:00:00 2001 From: tassaron Date: Fri, 23 Jun 2017 23:00:24 -0400 Subject: qt5 fixes also pep8 compliance --- src/command.py | 15 +++---- src/components/__base__.py | 14 +++---- src/components/color.py | 15 ++++--- src/components/image.py | 2 +- src/components/video.py | 14 ++++--- src/core.py | 28 +++++++------ src/main.py | 6 +-- src/mainwindow.py | 100 ++++++++++++++++++++++++++------------------- src/presetmanager.py | 55 +++++++++++++------------ src/video_thread.py | 11 ++--- 10 files changed, 143 insertions(+), 117 deletions(-) (limited to 'src/core.py') diff --git a/src/command.py b/src/command.py index 1a1e810..2f71f31 100644 --- a/src/command.py +++ b/src/command.py @@ -22,9 +22,9 @@ class Command(QtCore.QObject): self.parser = argparse.ArgumentParser( description='Create a visualization for an audio file', 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') + '-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') self.parser.add_argument( '-i', '--input', metavar='SOUND', help='input audio file') @@ -113,10 +113,11 @@ class Command(QtCore.QObject): if name.capitalize() in compName: return compName - compFileNames = [ \ - os.path.splitext(os.path.basename( - mod.__file__))[0] \ - for mod in self.core.modules \ + 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: diff --git a/src/components/__base__.py b/src/components/__base__.py index a4677b1..a24af40 100644 --- a/src/components/__base__.py +++ b/src/components/__base__.py @@ -39,7 +39,7 @@ class Component(QtCore.QObject): then update self.page widgets using the preset dict. ''' self.currentPreset = presetName \ - if presetName != None else presetDict['preset'] + if presetName is not None else presetDict['preset'] def preFrameRender(self, **kwargs): '''Triggered only before a video is exported (video_thread.py) @@ -66,8 +66,8 @@ class Component(QtCore.QObject): print('Couldn\'t locate preset "%s"' % preset) quit(1) else: - print('Opening "%s" preset on layer %s' % \ - (preset, self.compPos)) + print('Opening "%s" preset on layer %s' % ( + preset, self.compPos)) self.core.openPreset(path, self.compPos, preset) else: print( @@ -88,8 +88,8 @@ class Component(QtCore.QObject): 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) + dialog = QtWidgets.QColorDialog() + dialog.setOption(QtWidgets.QColorDialog.ShowAlphaChannel, True) color = dialog.getColor() if color.isValid(): RGBstring = '%s,%s,%s' % ( @@ -142,10 +142,10 @@ class Component(QtCore.QObject): return image ''' + class BadComponentInit(Exception): def __init__(self, arg, name): - string = \ -'''################################ + string = '''################################ Mandatory argument "%s" not specified in %s instance initialization ###################################''' diff --git a/src/components/color.py b/src/components/color.py index 8f9a1d1..2e3902a 100644 --- a/src/components/color.py +++ b/src/components/color.py @@ -53,7 +53,7 @@ class Component(__base__.Component): page.spinBox_height.valueChanged.connect(self.update) page.checkBox_trans.stateChanged.connect(self.update) - self.fillLabels = [ \ + self.fillLabels = [ 'Solid', 'Linear Gradient', 'Radial Gradient', @@ -126,8 +126,8 @@ class Component(__base__.Component): r, g, b = self.color1 shapeSize = (self.sizeWidth, self.sizeHeight) # in default state, skip all this logic and return a plain fill - if self.fillType==0 and shapeSize == (width, height) \ - and self.x == 0 and self.y == 0: + if self.fillType == 0 and shapeSize == (width, height) \ + and self.x == 0 and self.y == 0: return Image.new("RGBA", (width, height), (r, g, b, 255)) frame = self.blankFrame(width, height) @@ -143,9 +143,11 @@ class Component(__base__.Component): image = ImageQt(frame) painter = QtGui.QPainter(image) if self.stretch: - w = width; h = height + w = width + h = height else: - w = self.sizeWidth; h = self.sizeWidth + w = self.sizeWidth + h = self.sizeWidth if self.fillType == 1: # Linear Gradient brush = QtGui.QLinearGradient( @@ -170,7 +172,8 @@ class Component(__base__.Component): else: brush.setColorAt(1.0, QColor(*self.color2)) painter.setBrush(brush) - painter.drawRect(self.x, self.y, + painter.drawRect( + self.x, self.y, self.sizeWidth, self.sizeHeight) painter.end() imBytes = image.bits().asstring(image.numBytes()) diff --git a/src/components/image.py b/src/components/image.py index 8ca88d3..3517af6 100644 --- a/src/components/image.py +++ b/src/components/image.py @@ -85,7 +85,7 @@ class Component(__base__.Component): def pickImage(self): imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) - filename = QtGui.QFileDialog.getOpenFileName( + filename, _ = QtWidgets.QFileDialog.getOpenFileName( self.page, "Choose Image", imgDir, "Image Files (%s)" % " ".join(self.imageFormats)) if filename: diff --git a/src/components/video.py b/src/components/video.py index 58ce7a3..0090426 100644 --- a/src/components/video.py +++ b/src/components/video.py @@ -41,8 +41,8 @@ class Video: '-i', self.videoPath, '-f', 'image2pipe', '-pix_fmt', 'rgba', - '-filter:v', 'scale=%s:%s' % - scale(self.scale, self.width, self.height, str), + '-filter:v', 'scale=%s:%s' % scale( + self.scale, self.width, self.height, str), '-vcodec', 'rawvideo', '-', ] @@ -180,7 +180,7 @@ class Component(__base__.Component): def pickVideo(self): imgDir = self.settings.value("backgroundDir", os.path.expanduser("~")) - filename = QtGui.QFileDialog.getOpenFileName( + filename, _ = QtWidgets.QFileDialog.getOpenFileName( self.page, "Choose Video", imgDir, "Video Files (%s)" % " ".join(self.videoFormats) ) @@ -199,8 +199,8 @@ class Component(__base__.Component): '-i', self.videoPath, '-f', 'image2pipe', '-pix_fmt', 'rgba', - '-filter:v', 'scale=%s:%s' % - scale(self.scale, width, height, str), + '-filter:v', 'scale=%s:%s' % scale( + self.scale, width, height, str), '-vcodec', 'rawvideo', '-', '-ss', '90', '-vframes', '1', @@ -238,6 +238,7 @@ class Component(__base__.Component): def commandHelp(self): print('Load a video:\n path=/filepath/to/video.mp4') + def scale(scale, width, height, returntype=None): width = (float(width) / 100.0) * float(scale) height = (float(height) / 100.0) * float(scale) @@ -248,6 +249,7 @@ def scale(scale, width, height, returntype=None): else: return (width, height) + def finalizeFrame(self, imageData, width, height): if self.distort: try: @@ -265,7 +267,7 @@ def finalizeFrame(self, imageData, width, height): imageData) if self.scale != 100 \ - or self.xPosition != 0 or self.yPosition != 0: + or self.xPosition != 0 or self.yPosition != 0: frame = self.blankFrame(width, height) frame.paste(image, box=(self.xPosition, self.yPosition)) else: diff --git a/src/core.py b/src/core.py index bb5d351..670a3c5 100644 --- a/src/core.py +++ b/src/core.py @@ -179,7 +179,7 @@ class Core(): clearThis = False # add loaded named presets to savedPresets dict - if 'preset' in preset and preset['preset'] != None: + if 'preset' in preset and preset['preset'] is not None: nam = preset['preset'] filepath2 = os.path.join( self.presetDir, name, str(vers), nam) @@ -195,12 +195,12 @@ class Core(): -1, self.moduleIndexFor(name), loader) - if i == None: + if i is None: loader.showMessage(msg="Too many components!") break try: - if 'preset' in preset and preset['preset'] != None: + if 'preset' in preset and preset['preset'] is not None: self.selectedComponents[i].loadPreset( preset ) @@ -210,8 +210,8 @@ class Core(): preset['preset'] ) except KeyError as e: - print('%s missing value %s' % - (self.selectedComponents[i], e)) + print('%s missing value %s' % ( + self.selectedComponents[i], e)) if clearThis: self.clearPreset(i) @@ -221,7 +221,6 @@ class Core(): errcode = 1 data = sys.exc_info() - if errcode == 1: typ, value, _ = data if typ.__name__ == KeyError: @@ -274,11 +273,11 @@ class Core(): i += 1 elif i == 2: lastCompPreset = Core.presetFromString(line) - data[section].append( - (lastCompName, + data[section].append(( + lastCompName, lastCompVers, - lastCompPreset) - ) + lastCompPreset + )) i = 0 return 0, data except: @@ -309,7 +308,9 @@ class Core(): return False, '' def exportPreset(self, exportPath, compName, vers, origName): - internalPath = os.path.join(self.presetDir, compName, str(vers), origName) + internalPath = os.path.join( + self.presetDir, compName, str(vers), origName + ) if not os.path.exists(internalPath): return if os.path.exists(exportPath): @@ -328,7 +329,7 @@ class Core(): return False def createPresetFile( - self, compName, vers, presetName, saveValueStore, filepath=''): + 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 args''' if not filepath: @@ -463,7 +464,8 @@ class Core(): @staticmethod def presetToString(dictionary): '''Alphabetizes a dict into OrderedDict & returns string repr''' - return repr(OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))) + return repr( + OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))) @staticmethod def presetFromString(string): diff --git a/src/main.py b/src/main.py index 4bf26db..58fdb46 100644 --- a/src/main.py +++ b/src/main.py @@ -30,7 +30,6 @@ def LoadDefaultSettings(self): } for parm, value in default.items(): - #print(parm, self.settings.value(parm)) if self.settings.value(parm) is None: self.settings.setValue(parm, value) @@ -51,7 +50,7 @@ if __name__ == "__main__": app = QtWidgets.QApplication(sys.argv) app.setApplicationName("audio-visualizer") - app.setOrganizationName("audio-visualizer") + # app.setOrganizationName("audio-visualizer") if mode == 'cmd': from command import * @@ -76,7 +75,8 @@ if __name__ == "__main__": dpi = desc.physicalDpiX() topMargin = 0 if (dpi == 96) else int(10 * (dpi / 96)) - window.resize(window.width() * (dpi / 96), window.height() * (dpi / 96)) + window.resize( + window.width() * (dpi / 96), window.height() * (dpi / 96)) # window.verticalLayout_2.setContentsMargins(0, topMargin, 0, 0) main = MainWindow(window, proj) diff --git a/src/mainwindow.py b/src/mainwindow.py index a52a0f4..7a9e397 100644 --- a/src/mainwindow.py +++ b/src/mainwindow.py @@ -116,7 +116,6 @@ class MainWindow(QtWidgets.QMainWindow): codec = window.comboBox_videoCodec.itemText(i) if codec == self.settings.value('outputVideoCodec'): window.comboBox_videoCodec.setCurrentIndex(i) - #print(codec) for i in range(window.comboBox_audioCodec.count()): codec = window.comboBox_audioCodec.itemText(i) @@ -146,10 +145,11 @@ class MainWindow(QtWidgets.QMainWindow): # Make component buttons self.compMenu = QMenu() + self.compActions = [] for i, comp in enumerate(self.core.modules): action = self.compMenu.addAction(comp.Component.__doc__) 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) @@ -160,9 +160,10 @@ class MainWindow(QtWidgets.QMainWindow): self.window.pushButton_removeComponent.clicked.connect( lambda _: self.removeComponent()) - componentList.setContextMenuPolicy( - QtCore.Qt.CustomContextMenu) - componentList.customContextMenuRequested.connect(self.componentContextMenu) + componentList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + componentList.customContextMenuRequested.connect( + self.componentContextMenu + ) currentRes = str(self.settings.value('outputWidth'))+'x' + \ str(self.settings.value('outputHeight')) @@ -245,19 +246,30 @@ class MainWindow(QtWidgets.QMainWindow): QtWidgets.QShortcut("Ctrl+O", self.window, self.openOpenProjectDialog) QtWidgets.QShortcut("Ctrl+N", self.window, self.createNewProject) - QtWidgets.QShortcut("Ctrl+T", self.window, activated=lambda: - self.window.pushButton_addComponent.click()) - QtWidgets.QShortcut("Ctrl+Space", self.window, activated=lambda: - self.window.listWidget_componentList.setFocus()) - QtWidgets.QShortcut("Ctrl+Shift+S", self.window, - self.presetManager.openSavePresetDialog) - QtWidgets.QShortcut("Ctrl+Shift+C", self.window, - self.presetManager.clearPreset) - - QtWidgets.QShortcut("Ctrl+Up", self.window, - activated=lambda: self.moveComponent(-1)) - QtWidgets.QShortcut("Ctrl+Down", self.window, - activated=lambda: self.moveComponent(1)) + QtWidgets.QShortcut( + "Ctrl+T", self.window, + activated=lambda: self.window.pushButton_addComponent.click() + ) + QtWidgets.QShortcut( + "Ctrl+Space", self.window, + activated=lambda: self.window.listWidget_componentList.setFocus() + ) + QtWidgets.QShortcut( + "Ctrl+Shift+S", self.window, + self.presetManager.openSavePresetDialog + ) + QtWidgets.QShortcut( + "Ctrl+Shift+C", self.window, self.presetManager.clearPreset + ) + + QtWidgets.QShortcut( + "Ctrl+Up", self.window, + activated=lambda: self.moveComponent(-1) + ) + QtWidgets.QShortcut( + "Ctrl+Down", self.window, + activated=lambda: self.moveComponent(1) + ) QtWidgets.QShortcut("Ctrl+Home", self.window, self.moveComponentTop) QtWidgets.QShortcut("Ctrl+End", self.window, self.moveComponentBottom) QtWidgets.QShortcut("Ctrl+r", self.window, self.removeComponent) @@ -280,7 +292,7 @@ class MainWindow(QtWidgets.QMainWindow): def updateComponentTitle(self, pos, presetStore=False): if type(presetStore) == dict: name = presetStore['preset'] - if name == None or name not in self.core.savedPresets: + if name is None or name not in self.core.savedPresets: modified = False else: modified = (presetStore != self.core.savedPresets[name]) @@ -362,21 +374,22 @@ class MainWindow(QtWidgets.QMainWindow): def openInputFileDialog(self): inputDir = self.settings.value("inputDir", os.path.expanduser("~")) - fileName = QtGui.QFileDialog.getOpenFileName( + fileName, _ = QtWidgets.QFileDialog.getOpenFileName( self.window, "Open Audio File", inputDir, "Audio Files (%s)" % " ".join(self.core.audioFormats)) - if not fileName == "": + if fileName: self.settings.setValue("inputDir", os.path.dirname(fileName)) self.window.lineEdit_audioFile.setText(fileName) def openOutputFileDialog(self): outputDir = self.settings.value("outputDir", os.path.expanduser("~")) - fileName = QtGui.QFileDialog.getSaveFileName( + fileName, _ = QtWidgets.QFileDialog.getSaveFileName( self.window, "Set Output Video File", outputDir, - "Video Files (%s);; All Files (*)" % " ".join(self.core.videoFormats)) + "Video Files (%s);; All Files (*)" % " ".join( + self.core.videoFormats)) if not fileName == "": self.settings.setValue("outputDir", os.path.dirname(fileName)) @@ -547,13 +560,13 @@ class MainWindow(QtWidgets.QMainWindow): '''Drop event for the component listwidget''' componentList = self.window.listWidget_componentList - modelIndexes = [ \ - componentList.model().index(i) \ - for i in range(componentList.count()) \ + modelIndexes = [ + componentList.model().index(i) + for i in range(componentList.count()) ] - rects = [ \ - componentList.visualRect(modelIndex) \ - for modelIndex in modelIndexes \ + rects = [ + componentList.visualRect(modelIndex) + for modelIndex in modelIndexes ] rowPos = [rect.contains(event.pos()) for rect in rects] @@ -602,9 +615,10 @@ class MainWindow(QtWidgets.QMainWindow): if self.autosaveExists(identical=False): ch = self.showMessage( msg="You have unsaved changes in project '%s'. " - "Save before %s?" % \ - (os.path.basename(self.currentProject)[:-4], - phrase), + "Save before %s?" % ( + os.path.basename(self.currentProject)[:-4], + phrase + ), showCancel=True) if ch: success = self.saveProjectChanges() @@ -613,7 +627,7 @@ class MainWindow(QtWidgets.QMainWindow): os.remove(self.autosavePath) def openSaveProjectDialog(self): - filename = QtGui.QFileDialog.getSaveFileName( + filename, _ = QtWidgets.QFileDialog.getSaveFileName( self.window, "Create Project File", self.settings.value("projectDir"), "Project Files (*.avp)") @@ -628,7 +642,7 @@ class MainWindow(QtWidgets.QMainWindow): self.core.createProjectFile(filename) def openOpenProjectDialog(self): - filename = QtGui.QFileDialog.getOpenFileName( + filename, _ = QtWidgets.QFileDialog.getOpenFileName( self.window, "Open Project File", self.settings.value("projectDir"), "Project Files (*.avp)") @@ -657,17 +671,19 @@ class MainWindow(QtWidgets.QMainWindow): def showMessage(self, **kwargs): parent = kwargs['parent'] if 'parent' in kwargs else self.window - msg = QtGui.QMessageBox(parent) + msg = QtWidgets.QMessageBox(parent) msg.setModal(True) msg.setText(kwargs['msg']) msg.setIcon( - kwargs['icon'] if 'icon' in kwargs else QtGui.QMessageBox.Information) + kwargs['icon'] + if 'icon' in kwargs else QtWidgets.QMessageBox.Information + ) msg.setDetailedText(kwargs['detail'] if 'detail' in kwargs else None) if 'showCancel'in kwargs and kwargs['showCancel']: msg.setStandardButtons( - QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) + QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) else: - msg.setStandardButtons(QtGui.QMessageBox.Ok) + msg.setStandardButtons(QtWidgets.QMessageBox.Ok) ch = msg.exec_() if ch == 1024: return True @@ -687,7 +703,7 @@ class MainWindow(QtWidgets.QMainWindow): return self.presetManager.findPresets() - self.menu = QtGui.QMenu() + self.menu = QMenu() menuItem = self.menu.addAction("Save Preset") menuItem.triggered.connect( self.presetManager.openSavePresetDialog @@ -695,8 +711,10 @@ class MainWindow(QtWidgets.QMainWindow): # submenu for opening presets try: - presets = self.presetManager.presets[str(self.core.selectedComponents[index])] - self.submenu = QtGui.QMenu("Open Preset") + presets = self.presetManager.presets[ + str(self.core.selectedComponents[index]) + ] + self.submenu = QMenu("Open Preset") self.menu.addMenu(self.submenu) for version, presetName in presets: diff --git a/src/presetmanager.py b/src/presetmanager.py index ec3f5cd..97f6e0e 100644 --- a/src/presetmanager.py +++ b/src/presetmanager.py @@ -1,4 +1,4 @@ -from PyQt5 import QtGui, QtCore, QtWidgets +from PyQt5 import QtCore, QtWidgets import string import os @@ -21,13 +21,15 @@ class PresetManager(QtWidgets.QDialog): # window self.lastFilter = '*' - self.presetRows = [] # list of (comp, vers, name) tuples + self.presetRows = [] # list of (comp, vers, name) tuples self.window = window self.window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) # connect button signals - self.window.pushButton_delete.clicked.connect(self.openDeletePresetDialog) - self.window.pushButton_rename.clicked.connect(self.openRenamePresetDialog) + self.window.pushButton_delete.clicked.connect( + self.openDeletePresetDialog) + self.window.pushButton_rename.clicked.connect( + self.openRenamePresetDialog) self.window.pushButton_import.clicked.connect(self.openImportDialog) self.window.pushButton_export.clicked.connect(self.openExportDialog) self.window.pushButton_close.clicked.connect(self.window.close) @@ -36,7 +38,8 @@ class PresetManager(QtWidgets.QDialog): self.drawFilterList() self.window.comboBox_filter.currentIndexChanged.connect( lambda: self.drawPresetList( - self.window.comboBox_filter.currentText(), self.window.lineEdit_search.text() + self.window.comboBox_filter.currentText(), + self.window.lineEdit_search.text() ) ) @@ -47,7 +50,8 @@ class PresetManager(QtWidgets.QDialog): self.window.lineEdit_search.setCompleter(completer) self.window.lineEdit_search.textChanged.connect( lambda: self.drawPresetList( - self.window.comboBox_filter.currentText(), self.window.lineEdit_search.text() + self.window.comboBox_filter.currentText(), + self.window.lineEdit_search.text() ) ) self.drawPresetList('*') @@ -72,16 +76,14 @@ class PresetManager(QtWidgets.QDialog): parseList.append((compName, int(compVers), preset)) except ValueError: continue - self.presets =\ - { - compName : \ - [ - (vers, preset) \ - for name, vers, preset in parseList \ - if name == compName \ - ] \ - for compName, _, __ in parseList \ - } + self.presets = { + compName: [ + (vers, preset) + for name, vers, preset in parseList + if name == compName + ] + for compName, _, __ in parseList + } def drawPresetList(self, compFilter=None, presetFilter=''): self.window.listWidget_presets.clear() @@ -96,7 +98,8 @@ class PresetManager(QtWidgets.QDialog): continue for vers, preset in presets: if not presetFilter or presetFilter in preset: - self.window.listWidget_presets.addItem('%s: %s' % (component, preset)) + self.window.listWidget_presets.addItem( + '%s: %s' % (component, preset)) self.presetRows.append((component, vers, preset)) if preset not in presetNames: presetNames.append(preset) @@ -124,11 +127,11 @@ class PresetManager(QtWidgets.QDialog): while True: index = componentList.currentRow() currentPreset = selectedComponents[index].currentPreset - newName, OK = QtGui.QInputDialog.getText( + newName, OK = QtWidgets.QInputDialog.getText( self.parent.window, 'Audio Visualizer', 'New Preset Name:', - QtGui.QLineEdit.Normal, + QtWidgets.QLineEdit.Normal, currentPreset ) if OK: @@ -149,7 +152,7 @@ class PresetManager(QtWidgets.QDialog): break def createNewPreset( - self, compName, vers, filename, saveValueStore, **kwargs): + self, compName, vers, filename, saveValueStore, **kwargs): path = os.path.join(self.presetDir, compName, str(vers), filename) if self.presetExists(path, **kwargs): return @@ -163,7 +166,7 @@ class PresetManager(QtWidgets.QDialog): msg="%s already exists! Overwrite it?" % os.path.basename(path), showCancel=True, - icon=QtGui.QMessageBox.Warning, + icon=QtWidgets.QMessageBox.Warning, parent=window) if not ch: # user clicked cancel @@ -196,7 +199,7 @@ class PresetManager(QtWidgets.QDialog): ch = self.parent.showMessage( msg='Really delete %s?' % name, showCancel=True, - icon=QtGui.QMessageBox.Warning, + icon=QtWidgets.QMessageBox.Warning, parent=self.window ) if not ch: @@ -223,11 +226,11 @@ class PresetManager(QtWidgets.QDialog): while True: index = presetList.currentRow() - newName, OK = QtGui.QInputDialog.getText( + newName, OK = QtWidgets.QInputDialog.getText( self.window, 'Preset Manager', 'Rename Preset:', - QtGui.QLineEdit.Normal, + QtWidgets.QLineEdit.Normal, self.presetRows[index][2] ) if OK: @@ -250,7 +253,7 @@ class PresetManager(QtWidgets.QDialog): break def openImportDialog(self): - filename = QtGui.QFileDialog.getOpenFileName( + filename, _ = QtWidgets.QFileDialog.getOpenFileName( self.window, "Import Preset File", self.settings.value("presetDir"), "Preset Files (*.avl)") @@ -275,7 +278,7 @@ class PresetManager(QtWidgets.QDialog): def openExportDialog(self): if not self.window.listWidget_presets.selectedItems(): return - filename = QtGui.QFileDialog.getSaveFileName( + filename, _ = QtWidgets.QFileDialog.getSaveFileName( self.window, "Export Preset", self.settings.value("presetDir"), "Preset Files (*.avl)") diff --git a/src/video_thread.py b/src/video_thread.py index 5ea6d21..b45381c 100644 --- a/src/video_thread.py +++ b/src/video_thread.py @@ -121,15 +121,12 @@ class Worker(QtCore.QObject): vencoders = options['video-codecs'][vcodec] aencoders = options['audio-codecs'][acodec] - #print(encoders) for encoder in vencoders: - #print(encoder) if encoder in encoders: vencoder = encoder break for encoder in aencoders: - #print(encoder) if encoder in encoders: aencoder = encoder break @@ -167,10 +164,10 @@ class Worker(QtCore.QObject): numpy.seterr(divide='ignore') # Call preFrameRender on all components - print('Loaded Components:', ", ".join( - ["%s) %s" % (num, str(component)) \ - for num, component in enumerate(reversed(self.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): -- cgit v1.2.3