From c1457b6dad4640b17679dd802e372bd46a13d2a5 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 29 Jul 2017 13:08:28 -0400
Subject: starting work on Waveform component
split Video class out of Video component for reuse in Waveform
---
src/components/waveform.py | 139 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
create mode 100644 src/components/waveform.py
(limited to 'src/components/waveform.py')
diff --git a/src/components/waveform.py b/src/components/waveform.py
new file mode 100644
index 0000000..487a3bb
--- /dev/null
+++ b/src/components/waveform.py
@@ -0,0 +1,139 @@
+from PIL import Image
+from PyQt5 import QtGui, QtCore, QtWidgets
+from PyQt5.QtGui import QColor
+import os
+import math
+import subprocess
+
+from component import Component, ComponentError
+from toolkit.frame import BlankFrame
+from toolkit import openPipe, checkOutput, rgbFromString
+from toolkit.ffmpeg import FfmpegVideo
+
+
+class Component(Component):
+ name = 'Waveform'
+ version = '1.0.0'
+
+ def widget(self, *args):
+ self.color = (255, 255, 255)
+ super().widget(*args)
+
+ self.page.lineEdit_color.setText('%s,%s,%s' % self.color)
+ btnStyle = "QPushButton { background-color : %s; outline: none; }" \
+ % QColor(*self.color1).name()
+ self.page.lineEdit_color.setStylesheet(btnStyle)
+ self.page.pushButton_color.clicked.connect(lambda: self.pickColor())
+
+ self.trackWidgets(
+ {
+ 'mode': self.page.comboBox_mode,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'scale': self.page.spinBox_scale,
+ }
+ )
+
+ def update(self):
+ self.color = rgbFromString(self.page.lineEdit_color.text())
+ btnStyle = "QPushButton { background-color : %s; outline: none; }" \
+ % QColor(*self.color).name()
+ self.page.pushButton_color.setStyleSheet(btnStyle)
+ super().update()
+
+ def previewRender(self):
+ self.updateChunksize()
+ frame = self.getPreviewFrame(self.width, self.height)
+ if not frame:
+ return BlankFrame(self.width, self.height)
+ else:
+ return frame
+
+ def preFrameRender(self, **kwargs):
+ super().preFrameRender(**kwargs)
+ self.updateChunksize()
+ self.video = FfmpegVideo(
+ inputPath=self.audioFile,
+ filter_=makeFfmpegFilter(),
+ width=self.width, height=self.height,
+ chunkSize=self.chunkSize,
+ frameRate=int(self.settings.value("outputFrameRate")),
+ parent=self.parent, component=self,
+ )
+
+ def frameRender(self, frameNo):
+ if FfmpegVideo.threadError is not None:
+ raise FfmpegVideo.threadError
+ return finalizeFrame(self.video.frame(frameNo))
+
+ def postFrameRender(self):
+ closePipe(self.video.pipe)
+
+ def getPreviewFrame(self, width, height):
+ inputFile = self.parent.window.lineEdit_audioFile.text()
+ if not inputFile or not os.path.exists(inputFile):
+ return
+
+ command = [
+ self.core.FFMPEG_BIN,
+ '-thread_queue_size', '512',
+ '-i', inputFile,
+ '-f', 'image2pipe',
+ '-pix_fmt', 'rgba',
+ ]
+ command.extend(self.makeFfmpegFilter())
+ command.extend([
+ '-vcodec', 'rawvideo', '-',
+ '-ss', '90',
+ '-frames:v', '1',
+ ])
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=subprocess.DEVNULL, bufsize=10**8
+ )
+ byteFrame = pipe.stdout.read(self.chunkSize)
+ closePipe(pipe)
+
+ frame = finalizeFrame(self, byteFrame, width, height)
+ return frame
+
+ def makeFfmpegFilter(self):
+ w, h = scale(self.scale, self.width, self.height, str)
+ return [
+ '-filter_complex',
+ '[0:a] showwaves=s=%sx%s:mode=%s,format=rgba [v]' % (
+ w, h, self.mode,
+ ),
+ '-map', '[v]',
+ '-map', '0:a',
+ ]
+
+ def updateChunksize(self):
+ if self.scale != 100:
+ width, height = scale(self.scale, self.width, self.height, int)
+ else:
+ width, height = self.width, self.height
+ self.chunkSize = 4 * width * height
+
+
+def scale(scale, width, height, returntype=None):
+ width = (float(width) / 100.0) * float(scale)
+ height = (float(height) / 100.0) * float(scale)
+ if returntype == str:
+ return (str(math.ceil(width)), str(math.ceil(height)))
+ elif returntype == int:
+ return (math.ceil(width), math.ceil(height))
+ else:
+ return (width, height)
+
+
+def finalizeFrame(self, imageData, width, height):
+ # frombytes goes here
+ if self.scale != 100 \
+ or self.x != 0 or self.y != 0:
+ frame = BlankFrame(width, height)
+ frame.paste(image, box=(self.x, self.y))
+ else:
+ frame = image
+ return frame
--
cgit v1.2.3
From 1297af61c9ce00b6dd76f8ec690baedf5bf887c7 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 29 Jul 2017 20:27:46 -0400
Subject: waveform component is working, preview is glitchy
---
src/components/original.py | 3 +
src/components/video.py | 10 ++--
src/components/waveform.py | 134 +++++++++++++++++++++++++++++++--------------
src/components/waveform.ui | 95 +++++++++++++++++++++++++++++++-
src/toolkit/common.py | 21 -------
src/toolkit/ffmpeg.py | 30 ++++++++--
src/toolkit/frame.py | 12 ++++
src/video_thread.py | 38 +++++++++----
8 files changed, 256 insertions(+), 87 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/components/original.py b/src/components/original.py
index 3d1a574..621af6f 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -18,6 +18,9 @@ class Component(Component):
def names(*args):
return ['Original Audio Visualization']
+ def properties(self):
+ return ['pcm']
+
def widget(self, *args):
self.visColor = (255, 255, 255)
self.scale = 20
diff --git a/src/components/video.py b/src/components/video.py
index d3460ff..6cd16e5 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -4,10 +4,10 @@ import os
import math
import subprocess
-from component import Component, ComponentError
-from toolkit.frame import BlankFrame
-from toolkit.ffmpeg import testAudioStream, FfmpegVideo
-from toolkit import openPipe, closePipe, checkOutput, scale
+from component import Component
+from toolkit.frame import BlankFrame, scale
+from toolkit.ffmpeg import openPipe, closePipe, testAudioStream, FfmpegVideo
+from toolkit import checkOutput
class Component(Component):
@@ -132,7 +132,7 @@ class Component(Component):
]
command.extend(self.makeFfmpegFilter())
command.extend([
- '-vcodec', 'rawvideo', '-',
+ '-codec:v', 'rawvideo', '-',
'-ss', '90',
'-frames:v', '1',
])
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 487a3bb..375b3fc 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -5,10 +5,10 @@ import os
import math
import subprocess
-from component import Component, ComponentError
-from toolkit.frame import BlankFrame
-from toolkit import openPipe, checkOutput, rgbFromString
-from toolkit.ffmpeg import FfmpegVideo
+from component import Component
+from toolkit.frame import BlankFrame, scale
+from toolkit import checkOutput, rgbFromString, pickColor
+from toolkit.ffmpeg import openPipe, closePipe, getAudioDuration, FfmpegVideo
class Component(Component):
@@ -21,17 +21,27 @@ class Component(Component):
self.page.lineEdit_color.setText('%s,%s,%s' % self.color)
btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color1).name()
- self.page.lineEdit_color.setStylesheet(btnStyle)
+ % QColor(*self.color).name()
+ self.page.pushButton_color.setStyleSheet(btnStyle)
self.page.pushButton_color.clicked.connect(lambda: self.pickColor())
+ self.page.spinBox_scale.valueChanged.connect(self.updateChunksize)
+
+ if hasattr(self.parent, 'window'):
+ self.parent.window.lineEdit_audioFile.textChanged.connect(
+ self.update
+ )
self.trackWidgets(
{
'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude,
'x': self.page.spinBox_x,
'y': self.page.spinBox_y,
'mirror': self.page.checkBox_mirror,
'scale': self.page.spinBox_scale,
+ 'opacity': self.page.spinBox_opacity,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
}
)
@@ -42,6 +52,26 @@ class Component(Component):
self.page.pushButton_color.setStyleSheet(btnStyle)
super().update()
+ def loadPreset(self, pr, *args):
+ super().loadPreset(pr, *args)
+
+ self.page.lineEdit_color.setText('%s,%s,%s' % pr['color'])
+ btnStyle = "QPushButton { background-color : %s; outline: none; }" \
+ % QColor(*pr['color']).name()
+ self.page.pushButton_color.setStyleSheet(btnStyle)
+
+ def savePreset(self):
+ saveValueStore = super().savePreset()
+ saveValueStore['color'] = self.color
+ return saveValueStore
+
+ def pickColor(self):
+ RGBstring, btnStyle = pickColor()
+ if not RGBstring:
+ return
+ self.page.lineEdit_color.setText(RGBstring)
+ self.page.pushButton_color.setStyleSheet(btnStyle)
+
def previewRender(self):
self.updateChunksize()
frame = self.getPreviewFrame(self.width, self.height)
@@ -53,10 +83,11 @@ class Component(Component):
def preFrameRender(self, **kwargs):
super().preFrameRender(**kwargs)
self.updateChunksize()
+ w, h = scale(self.scale, self.width, self.height, str)
self.video = FfmpegVideo(
inputPath=self.audioFile,
- filter_=makeFfmpegFilter(),
- width=self.width, height=self.height,
+ filter_=self.makeFfmpegFilter(),
+ width=w, height=h,
chunkSize=self.chunkSize,
frameRate=int(self.settings.value("outputFrameRate")),
parent=self.parent, component=self,
@@ -65,7 +96,7 @@ class Component(Component):
def frameRender(self, frameNo):
if FfmpegVideo.threadError is not None:
raise FfmpegVideo.threadError
- return finalizeFrame(self.video.frame(frameNo))
+ return self.finalizeFrame(self.video.frame(frameNo))
def postFrameRender(self):
closePipe(self.video.pipe)
@@ -74,18 +105,25 @@ class Component(Component):
inputFile = self.parent.window.lineEdit_audioFile.text()
if not inputFile or not os.path.exists(inputFile):
return
+ duration = getAudioDuration(inputFile)
+ if not duration:
+ return
+ startPt = duration / 3
command = [
self.core.FFMPEG_BIN,
'-thread_queue_size', '512',
+ '-r', self.settings.value("outputFrameRate"),
+ '-ss', "{0:.3f}".format(startPt),
'-i', inputFile,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
]
- command.extend(self.makeFfmpegFilter())
+ command.extend(self.makeFfmpegFilter(preview=True, startPt=startPt))
command.extend([
- '-vcodec', 'rawvideo', '-',
- '-ss', '90',
+ '-an',
+ '-s:v', '%sx%s' % scale(self.scale, self.width, self.height, str),
+ '-codec:v', 'rawvideo', '-',
'-frames:v', '1',
])
pipe = openPipe(
@@ -95,45 +133,57 @@ class Component(Component):
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
- frame = finalizeFrame(self, byteFrame, width, height)
+ frame = self.finalizeFrame(byteFrame)
return frame
- def makeFfmpegFilter(self):
+ def makeFfmpegFilter(self, preview=False, startPt=0):
w, h = scale(self.scale, self.width, self.height, str)
+ if self.amplitude == 0:
+ amplitude = 'lin'
+ elif self.amplitude == 1:
+ amplitude = 'log'
+ elif self.amplitude == 2:
+ amplitude = 'sqrt'
+ elif self.amplitude == 3:
+ amplitude = 'cbrt'
+ hexcolor = QColor(*self.color).name()
+ opacity = "{0:.1f}".format(self.opacity / 100)
+
return [
'-filter_complex',
- '[0:a] showwaves=s=%sx%s:mode=%s,format=rgba [v]' % (
- w, h, self.mode,
+ '[0:a] %s%s'
+ 'showwaves=r=30:s=%sx%s:mode=%s:colors=%s@%s:scale=%s%s%s [v1]; '
+ '[v1] scale=%s:%s%s [v]' % (
+ 'compand=gain=2,' if self.compress else '',
+ 'aformat=channel_layouts=mono,' if self.mono else '',
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ str(self.page.comboBox_mode.currentText()).lower(),
+ hexcolor, opacity, amplitude,
+ ', drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=4:color=%s@%s' % (
+ hexcolor, opacity
+ ) if self.mode < 2 else '',
+ ', hflip' if self.mirror else'',
+ w, h,
+ ', trim=duration=%s' % "{0:.3f}".format(startPt + 1) if preview else '',
),
'-map', '[v]',
- '-map', '0:a',
]
def updateChunksize(self):
- if self.scale != 100:
- width, height = scale(self.scale, self.width, self.height, int)
- else:
- width, height = self.width, self.height
+ width, height = scale(self.scale, self.width, self.height, int)
self.chunkSize = 4 * width * height
-
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
- if returntype == str:
- return (str(math.ceil(width)), str(math.ceil(height)))
- elif returntype == int:
- return (math.ceil(width), math.ceil(height))
- else:
- return (width, height)
-
-
-def finalizeFrame(self, imageData, width, height):
- # frombytes goes here
- if self.scale != 100 \
- or self.x != 0 or self.y != 0:
- frame = BlankFrame(width, height)
- frame.paste(image, box=(self.x, self.y))
- else:
- frame = image
- return frame
+ def finalizeFrame(self, imageData):
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ if self.scale != 100 \
+ or self.x != 0 or self.y != 0:
+ frame = BlankFrame(self.width, self.height)
+ frame.paste(image, box=(self.x, self.y))
+ else:
+ frame = image
+ return frame
diff --git a/src/components/waveform.ui b/src/components/waveform.ui
index 5d62150..0e40380 100644
--- a/src/components/waveform.ui
+++ b/src/components/waveform.ui
@@ -226,9 +226,31 @@
-
-
+
- Mirror
+ Opacity
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QAbstractSpinBox::UpDownArrows
+
+
+ %
+
+
+ 10
+
+
+ 400
+
+
+ 100
@@ -263,6 +285,75 @@
+ -
+
+
-
+
+
+ Compress
+
+
+
+ -
+
+
+ Mono
+
+
+
+ -
+
+
+ Mirror
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Amplitude
+
+
+
+ -
+
+
-
+
+ Linear
+
+
+ -
+
+ Logarithmic
+
+
+ -
+
+ Square root
+
+
+ -
+
+ Cubic root
+
+
+
+
+
+
-
diff --git a/src/toolkit/common.py b/src/toolkit/common.py
index 128ed08..5d424e0 100644
--- a/src/toolkit/common.py
+++ b/src/toolkit/common.py
@@ -6,22 +6,9 @@ import string
import os
import sys
import subprocess
-import signal
-import math
from collections import OrderedDict
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
- if returntype == str:
- return (str(math.ceil(width)), str(math.ceil(height)))
- elif returntype == int:
- return (math.ceil(width), math.ceil(height))
- else:
- return (width, height)
-
-
def badName(name):
'''Returns whether a name contains non-alphanumeric chars'''
return any([letter in string.punctuation for letter in name])
@@ -69,14 +56,6 @@ def checkOutput(commandList, **kwargs):
return subprocess.check_output(commandList, **kwargs)
-@pipeWrapper
-def openPipe(commandList, **kwargs):
- return subprocess.Popen(commandList, **kwargs)
-
-def closePipe(pipe):
- pipe.stdout.close()
- pipe.send_signal(signal.SIGINT)
-
def disableWhenEncoding(func):
def decorator(self, *args, **kwargs):
if self.encoding:
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index fea9d4e..e37282f 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -6,10 +6,12 @@ import sys
import os
import subprocess
import threading
+import signal
from queue import PriorityQueue
import core
-from toolkit.common import checkOutput, openPipe
+from toolkit.common import checkOutput, pipeWrapper
+from component import ComponentError
class FfmpegVideo:
@@ -60,7 +62,8 @@ class FfmpegVideo:
kwargs['filter_']
)
self.command.extend([
- '-vcodec', 'rawvideo', '-',
+ '-s:v', '%sx%s' % (self.width, self.height),
+ '-codec:v', 'rawvideo', '-',
])
self.frameBuffer = PriorityQueue()
@@ -85,9 +88,11 @@ class FfmpegVideo:
self.frameBuffer.task_done()
def fillBuffer(self):
+ import sys
+ print(self.command)
self.pipe = openPipe(
self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL, bufsize=10**8
+ stderr=sys.__stdout__, bufsize=10**8
)
while True:
if self.parent.canceled:
@@ -100,7 +105,7 @@ class FfmpegVideo:
self.frameBuffer.put((self.frameNo-1, self.lastFrame))
continue
except AttributeError:
- Video.threadError = ComponentError(self.component, 'video')
+ FfmpegVideo.threadError = ComponentError(self.component, 'video')
break
self.currentFrame = self.pipe.stdout.read(self.chunkSize)
@@ -109,6 +114,16 @@ class FfmpegVideo:
self.lastFrame = self.currentFrame
+@pipeWrapper
+def openPipe(commandList, **kwargs):
+ return subprocess.Popen(commandList, **kwargs)
+
+
+def closePipe(pipe):
+ pipe.stdout.close()
+ pipe.send_signal(signal.SIGINT)
+
+
def findFfmpeg():
if getattr(sys, 'frozen', False):
# The application is frozen
@@ -347,7 +362,12 @@ def getAudioDuration(filename):
except subprocess.CalledProcessError as ex:
fileInfo = ex.output
- info = fileInfo.decode("utf-8").split('\n')
+ try:
+ info = fileInfo.decode("utf-8").split('\n')
+ except UnicodeDecodeError as e:
+ print('Unicode error:', str(e))
+ return False
+
for line in info:
if 'Duration' in line:
d = line.split(',')[0]
diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py
index b66e037..f42d4c9 100644
--- a/src/toolkit/frame.py
+++ b/src/toolkit/frame.py
@@ -6,6 +6,7 @@ from PIL import Image
from PIL.ImageQt import ImageQt
import sys
import os
+import math
import core
@@ -41,6 +42,17 @@ class PaintColor(QtGui.QColor):
super().__init__(b, g, r, a)
+def scale(scale, width, height, returntype=None):
+ width = (float(width) / 100.0) * float(scale)
+ height = (float(height) / 100.0) * float(scale)
+ if returntype == str:
+ return (str(math.ceil(width)), str(math.ceil(height)))
+ elif returntype == int:
+ return (math.ceil(width), math.ceil(height))
+ else:
+ return (width, height)
+
+
def defaultSize(framefunc):
'''Makes width/height arguments optional'''
def decorator(*args):
diff --git a/src/video_thread.py b/src/video_thread.py
index f27ec21..5963def 100644
--- a/src/video_thread.py
+++ b/src/video_thread.py
@@ -19,9 +19,11 @@ import time
import signal
from component import ComponentError
-from toolkit import openPipe
-from toolkit.ffmpeg import readAudioFile, createFfmpegCommand
from toolkit.frame import Checkerboard
+from toolkit.ffmpeg import (
+ openPipe, readAudioFile,
+ getAudioDuration, createFfmpegCommand
+)
class Worker(QtCore.QObject):
@@ -132,15 +134,24 @@ class Worker(QtCore.QObject):
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
# READ AUDIO, INITIALIZE COMPONENTS, OPEN A PIPE TO FFMPEG
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
-
- self.progressBarSetText.emit("Loading audio file...")
- audioFileTraits = readAudioFile(
- self.inputFile, self
- )
- if audioFileTraits is None:
- self.cancelExport()
- return
- self.completeAudioArray, duration = audioFileTraits
+ if any([
+ True if 'pcm' in comp.properties() else False
+ for comp in self.components
+ ]):
+ self.progressBarSetText.emit("Loading audio file...")
+ audioFileTraits = readAudioFile(
+ self.inputFile, self
+ )
+ if audioFileTraits is None:
+ self.cancelExport()
+ return
+ self.completeAudioArray, duration = audioFileTraits
+ else:
+ duration = getAudioDuration(self.inputFile)
+ class FakeList:
+ def __len__(self):
+ return int((duration * 44100) + 44100) - 1470
+ self.completeAudioArray = FakeList()
self.progressBarUpdate.emit(0)
self.progressBarSetText.emit("Starting components...")
@@ -284,7 +295,10 @@ class Worker(QtCore.QObject):
numpy.seterr(all='print')
- self.out_pipe.stdin.close()
+ try:
+ self.out_pipe.stdin.close()
+ except BrokenPipeError:
+ print('Broken pipe to ffmpeg!')
if self.out_pipe.stderr is not None:
print(self.out_pipe.stderr.read())
self.out_pipe.stderr.close()
--
cgit v1.2.3
From db1ea1fc4edf19589e82171d48c417742c61c74b Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 29 Jul 2017 23:45:37 -0400
Subject: generic preview sound for waveform component
with secret preference to use the audio file again
---
src/component.py | 2 +-
src/components/waveform.py | 38 +++++++++++++++++++++++++-------------
src/core.py | 1 +
src/mainwindow.py | 2 ++
src/toolkit/ffmpeg.py | 14 ++++++++++----
5 files changed, 39 insertions(+), 18 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index fc8fbd3..6d49406 100644
--- a/src/component.py
+++ b/src/component.py
@@ -427,7 +427,7 @@ class ComponentError(RuntimeError):
ComponentError.prevErrors.insert(0, name)
curTime = time.time()
if name in ComponentError.prevErrors[1:] \
- and curTime - ComponentError.lastTime < 0.2:
+ and curTime - ComponentError.lastTime < 1.0:
# Don't create multiple windows for quickly repeated messages
return
ComponentError.lastTime = time.time()
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 375b3fc..b4b19e9 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -90,7 +90,7 @@ class Component(Component):
width=w, height=h,
chunkSize=self.chunkSize,
frameRate=int(self.settings.value("outputFrameRate")),
- parent=self.parent, component=self,
+ parent=self.parent, component=self, debug=True,
)
def frameRender(self, frameNo):
@@ -102,20 +102,25 @@ class Component(Component):
closePipe(self.video.pipe)
def getPreviewFrame(self, width, height):
- inputFile = self.parent.window.lineEdit_audioFile.text()
- if not inputFile or not os.path.exists(inputFile):
- return
- duration = getAudioDuration(inputFile)
- if not duration:
- return
- startPt = duration / 3
+ genericPreview = self.settings.value("pref_genericPreview")
+ startPt = 0
+ if not genericPreview:
+ inputFile = self.parent.window.lineEdit_audioFile.text()
+ if not inputFile or not os.path.exists(inputFile):
+ return
+ duration = getAudioDuration(inputFile)
+ if not duration:
+ return
+ startPt = duration / 3
command = [
self.core.FFMPEG_BIN,
'-thread_queue_size', '512',
'-r', self.settings.value("outputFrameRate"),
'-ss', "{0:.3f}".format(startPt),
- '-i', inputFile,
+ '-i',
+ os.path.join(self.core.wd, 'background.png')
+ if genericPreview else inputFile,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
]
@@ -148,13 +153,19 @@ class Component(Component):
amplitude = 'cbrt'
hexcolor = QColor(*self.color).name()
opacity = "{0:.1f}".format(self.opacity / 100)
+ genericPreview = self.settings.value("pref_genericPreview")
return [
'-filter_complex',
- '[0:a] %s%s'
+ '%s%s%s'
'showwaves=r=30:s=%sx%s:mode=%s:colors=%s@%s:scale=%s%s%s [v1]; '
- '[v1] scale=%s:%s%s [v]' % (
- 'compand=gain=2,' if self.compress else '',
+ '[v1] scale=%s:%s%s,setpts=2.0*PTS [v]' % (
+ 'aevalsrc=sin(1*2*PI*t)*sin(880*2*PI*t),'
+ if preview and genericPreview else '[0:a] ',
+ 'compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2'
+ ',' if self.compress and not preview else (
+ 'compand=gain=5,' if self.compress else ''
+ ),
'aformat=channel_layouts=mono,' if self.mono else '',
self.settings.value("outputWidth"),
self.settings.value("outputHeight"),
@@ -165,7 +176,8 @@ class Component(Component):
) if self.mode < 2 else '',
', hflip' if self.mirror else'',
w, h,
- ', trim=duration=%s' % "{0:.3f}".format(startPt + 1) if preview else '',
+ ', trim=duration=%s' % "{0:.3f}".format(startPt + 1)
+ if preview else '',
),
'-map', '[v]',
]
diff --git a/src/core.py b/src/core.py
index 1c29774..24bf097 100644
--- a/src/core.py
+++ b/src/core.py
@@ -506,6 +506,7 @@ class Core:
"outputContainer": "MP4",
"projectDir": os.path.join(cls.dataDir, 'projects'),
"pref_insertCompAtTop": True,
+ "pref_genericPreview": True,
}
for parm, value in defaultSettings.items():
diff --git a/src/mainwindow.py b/src/mainwindow.py
index 070131c..a97081e 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -791,6 +791,8 @@ class MainWindow(QtWidgets.QMainWindow):
field.blockSignals(True)
field.setText('')
field.blockSignals(False)
+ self.progressBarUpdated(0)
+ self.progressBarSetText('')
@disableWhenEncoding
def createNewProject(self, prompt=True):
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index e37282f..4ea2863 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -37,6 +37,7 @@ class FfmpegVideo:
self.frameNo = -1
self.currentFrame = 'None'
self.map_ = None
+ self.debug = False
if 'loopVideo' in kwargs and kwargs['loopVideo']:
self.loopValue = '-1'
@@ -47,6 +48,8 @@ class FfmpegVideo:
kwargs['filter_'].insert(0, '-filter_complex')
else:
kwargs['filter_'] = None
+ if 'debug' in kwargs:
+ self.debug = True
self.command = [
core.Core.FFMPEG_BIN,
@@ -62,7 +65,6 @@ class FfmpegVideo:
kwargs['filter_']
)
self.command.extend([
- '-s:v', '%sx%s' % (self.width, self.height),
'-codec:v', 'rawvideo', '-',
])
@@ -88,11 +90,15 @@ class FfmpegVideo:
self.frameBuffer.task_done()
def fillBuffer(self):
- import sys
- print(self.command)
+ if self.debug:
+ print(" ".join([word for word in self.command]))
+ err = sys.__stdout__
+ else:
+ err = subprocess.DEVNULL
+
self.pipe = openPipe(
self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=sys.__stdout__, bufsize=10**8
+ stderr=err, bufsize=10**8
)
while True:
if self.parent.canceled:
--
cgit v1.2.3
From b6b45d12702f18f041acf65b0d5e34714835ecb4 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sun, 30 Jul 2017 13:04:02 -0400
Subject: added Spectrum component with many options
tweaked Waveform, added some ffmpeg logging, made generic widget functions
---
src/component.py | 54 ++---
src/components/spectrum.py | 239 +++++++++++++++++++
src/components/spectrum.ui | 582 +++++++++++++++++++++++++++++++++++++++++++++
src/components/waveform.py | 48 ++--
src/components/waveform.ui | 21 +-
src/mainwindow.py | 2 +-
src/toolkit/common.py | 43 ++++
src/toolkit/ffmpeg.py | 41 ++--
8 files changed, 959 insertions(+), 71 deletions(-)
create mode 100644 src/components/spectrum.py
create mode 100644 src/components/spectrum.ui
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index 6d49406..1a5a5a4 100644
--- a/src/component.py
+++ b/src/component.py
@@ -4,9 +4,11 @@
'''
from PyQt5 import uic, QtCore, QtWidgets
import os
+import sys
import time
from toolkit.frame import BlankFrame
+from toolkit import getWidgetValue, setWidgetValue, connectWidget
class ComponentMetaclass(type(QtCore.QObject)):
@@ -273,14 +275,9 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
widgets['spinBox'].extend(
self.page.findChildren(QtWidgets.QDoubleSpinBox)
)
- for widget in widgets['lineEdit']:
- widget.textChanged.connect(self.update)
- for widget in widgets['checkBox']:
- widget.stateChanged.connect(self.update)
- for widget in widgets['spinBox']:
- widget.valueChanged.connect(self.update)
- for widget in widgets['comboBox']:
- widget.currentIndexChanged.connect(self.update)
+ for widgetList in widgets.values():
+ for widget in widgetList:
+ connectWidget(widget, self.update)
def update(self):
'''
@@ -289,15 +286,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
Call super() at the END if you need to subclass this.
'''
for attr, widget in self._trackedWidgets.items():
- if type(widget) == QtWidgets.QLineEdit:
- setattr(self, attr, widget.text())
- elif type(widget) == QtWidgets.QSpinBox \
- or type(widget) == QtWidgets.QDoubleSpinBox:
- setattr(self, attr, widget.value())
- elif type(widget) == QtWidgets.QCheckBox:
- setattr(self, attr, widget.isChecked())
- elif type(widget) == QtWidgets.QComboBox:
- setattr(self, attr, widget.currentIndex())
+ setattr(self, attr, getWidgetValue(widget))
if not self.core.openingProject:
self.parent.drawPreview()
saveValueStore = self.savePreset()
@@ -313,19 +302,10 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self.currentPreset = presetName \
if presetName is not None else presetDict['preset']
for attr, widget in self._trackedWidgets.items():
- val = presetDict[
- attr if attr not in self._presetNames
+ key = attr if attr not in self._presetNames \
else self._presetNames[attr]
- ]
- if type(widget) == QtWidgets.QLineEdit:
- widget.setText(val)
- elif type(widget) == QtWidgets.QSpinBox \
- or type(widget) == QtWidgets.QDoubleSpinBox:
- widget.setValue(val)
- elif type(widget) == QtWidgets.QCheckBox:
- widget.setChecked(val)
- elif type(widget) == QtWidgets.QComboBox:
- widget.setCurrentIndex(val)
+ val = presetDict[key]
+ setWidgetValue(widget, val)
def savePreset(self):
saveValueStore = {}
@@ -420,24 +400,30 @@ class ComponentError(RuntimeError):
prevErrors = []
lastTime = time.time()
- def __init__(self, caller, name):
- print('##### ComponentError by %s: %s' % (caller.name, name))
+ def __init__(self, caller, name, msg=None):
+ if msg is None and sys.exc_info()[0] is not None:
+ msg = str(sys.exc_info()[1])
+ else:
+ msg = 'Unknown error.'
+ print("##### ComponentError by %s's %s: %s" % (
+ caller.name, name, msg))
+
+ # Don't create multiple windows for quickly repeated messages
if len(ComponentError.prevErrors) > 1:
ComponentError.prevErrors.pop()
ComponentError.prevErrors.insert(0, name)
curTime = time.time()
if name in ComponentError.prevErrors[1:] \
and curTime - ComponentError.lastTime < 1.0:
- # Don't create multiple windows for quickly repeated messages
return
ComponentError.lastTime = time.time()
from toolkit import formatTraceback
- import sys
if sys.exc_info()[0] is not None:
string = (
- "%s component's %s encountered %s %s: %s" % (
+ "%s component (#%s): %s encountered %s %s: %s" % (
caller.__class__.name,
+ str(caller.compPos),
name,
'an' if any([
sys.exc_info()[0].__name__.startswith(vowel)
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
new file mode 100644
index 0000000..261d9cc
--- /dev/null
+++ b/src/components/spectrum.py
@@ -0,0 +1,239 @@
+from PIL import Image
+from PyQt5 import QtGui, QtCore, QtWidgets
+from PyQt5.QtGui import QColor
+import os
+import math
+import subprocess
+import time
+
+from component import Component
+from toolkit.frame import BlankFrame, scale
+from toolkit import checkOutput, rgbFromString, pickColor, connectWidget
+from toolkit.ffmpeg import (
+ openPipe, closePipe, getAudioDuration, FfmpegVideo, exampleSound
+)
+
+
+class Component(Component):
+ name = 'Spectrum'
+ version = '1.0.0'
+
+ def widget(self, *args):
+ self.color = (255, 255, 255)
+ self.previewFrame = None
+ super().widget(*args)
+ self.chunkSize = 4 * self.width * self.height
+ self.changedOptions = True
+
+ if hasattr(self.parent, 'window'):
+ # update preview when audio file changes (if genericPreview is off)
+ self.parent.window.lineEdit_audioFile.textChanged.connect(
+ self.update
+ )
+
+ self.trackWidgets(
+ {
+ 'filterType': self.page.comboBox_filterType,
+ 'window': self.page.comboBox_window,
+ 'amplitude': self.page.comboBox_amplitude,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'scale': self.page.spinBox_scale,
+ 'color': self.page.comboBox_color,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
+ }
+ )
+ for widget in self._trackedWidgets.values():
+ connectWidget(widget, lambda: self.changed())
+
+ def changed(self):
+ self.changedOptions = True
+
+ def update(self):
+ count = self.page.stackedWidget.count()
+ i = self.page.comboBox_filterType.currentIndex()
+ self.page.stackedWidget.setCurrentIndex(i if i < count else count - 1)
+ super().update()
+
+ def previewRender(self):
+ changedSize = self.updateChunksize()
+ if not changedSize \
+ and not self.changedOptions \
+ and self.previewFrame is not None:
+ return self.previewFrame
+
+ frame = self.getPreviewFrame()
+ self.changedOptions = False
+ if not frame:
+ self.previewFrame = None
+ return BlankFrame(self.width, self.height)
+ else:
+ self.previewFrame = frame
+ return frame
+
+ def preFrameRender(self, **kwargs):
+ super().preFrameRender(**kwargs)
+ self.updateChunksize()
+ w, h = scale(self.scale, self.width, self.height, str)
+ self.video = FfmpegVideo(
+ inputPath=self.audioFile,
+ filter_=self.makeFfmpegFilter(),
+ width=w, height=h,
+ chunkSize=self.chunkSize,
+ frameRate=int(self.settings.value("outputFrameRate")),
+ parent=self.parent, component=self,
+ )
+
+ def frameRender(self, frameNo):
+ if FfmpegVideo.threadError is not None:
+ raise FfmpegVideo.threadError
+ return self.finalizeFrame(self.video.frame(frameNo))
+
+ def postFrameRender(self):
+ closePipe(self.video.pipe)
+
+ def getPreviewFrame(self):
+ genericPreview = self.settings.value("pref_genericPreview")
+ startPt = 0
+ if not genericPreview:
+ inputFile = self.parent.window.lineEdit_audioFile.text()
+ if not inputFile or not os.path.exists(inputFile):
+ return
+ duration = getAudioDuration(inputFile)
+ if not duration:
+ return
+ startPt = duration / 3
+
+ command = [
+ self.core.FFMPEG_BIN,
+ '-thread_queue_size', '512',
+ '-r', self.settings.value("outputFrameRate"),
+ '-ss', "{0:.3f}".format(startPt),
+ '-i',
+ os.path.join(self.core.wd, 'background.png')
+ if genericPreview else inputFile,
+ '-f', 'image2pipe',
+ '-pix_fmt', 'rgba',
+ ]
+ command.extend(self.makeFfmpegFilter(preview=True, startPt=startPt))
+ command.extend([
+ '-an',
+ '-s:v', '%sx%s' % scale(self.scale, self.width, self.height, str),
+ '-codec:v', 'rawvideo', '-',
+ '-frames:v', '1',
+ ])
+ logFilename = os.path.join(
+ self.core.dataDir, 'preview_%s.log' % str(self.compPos))
+ with open(logFilename, 'w') as log:
+ log.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as log:
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=log, bufsize=10**8
+ )
+ byteFrame = pipe.stdout.read(self.chunkSize)
+ closePipe(pipe)
+
+ frame = self.finalizeFrame(byteFrame)
+ return frame
+
+ def makeFfmpegFilter(self, preview=False, startPt=0):
+ w, h = scale(self.scale, self.width, self.height, str)
+ if self.amplitude == 0:
+ amplitude = 'sqrt'
+ elif self.amplitude == 1:
+ amplitude = 'cbrt'
+ elif self.amplitude == 2:
+ amplitude = '4thrt'
+ elif self.amplitude == 3:
+ amplitude = '5thrt'
+ elif self.amplitude == 4:
+ amplitude = 'lin'
+ elif self.amplitude == 5:
+ amplitude = 'log'
+ color = self.page.comboBox_color.currentText().lower()
+ genericPreview = self.settings.value("pref_genericPreview")
+
+ if self.filterType == 0: # Spectrum
+ filter_ = (
+ 'showspectrum=s=%sx%s:slide=scroll:win_func=%s:'
+ 'color=%s:scale=%s' % (
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ self.page.comboBox_window.currentText(),
+ color, amplitude,
+ )
+ )
+ elif self.filterType == 1: # Histogram
+ filter_ = (
+ 'ahistogram=r=%s:s=%sx%s:dmode=separate' % (
+ self.settings.value("outputFrameRate"),
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ )
+ )
+ elif self.filterType == 2: # Vector Scope
+ filter_ = (
+ 'avectorscope=s=%sx%s:draw=line:m=polar:scale=log' % (
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ )
+ )
+ elif self.filterType == 3: # Musical Scale
+ filter_ = (
+ 'showcqt=r=%s:s=%sx%s:count=30:text=0' % (
+ self.settings.value("outputFrameRate"),
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ )
+ )
+ elif self.filterType == 4: # Phase
+ filter_ = (
+ 'aphasemeter=r=%s:s=%sx%s:mpc=white:video=1[atrash][vtmp]; '
+ '[atrash] anullsink; [vtmp] null' % (
+ self.settings.value("outputFrameRate"),
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ )
+ )
+
+ return [
+ '-filter_complex',
+ '%s%s%s%s%s [v1]; '
+ '[v1] scale=%s:%s%s [v]' % (
+ exampleSound() if preview and genericPreview else '[0:a] ',
+ 'compand=gain=4,' if self.compress else '',
+ 'aformat=channel_layouts=mono,' if self.mono else '',
+ filter_,
+ ', hflip' if self.mirror else'',
+ w, h,
+ ', trim=start=%s:end=%s' % (
+ "{0:.3f}".format(startPt + 15),
+ "{0:.3f}".format(startPt + 15.5)
+ ) if preview else '',
+ ),
+ '-map', '[v]',
+ ]
+
+ def updateChunksize(self):
+ width, height = scale(self.scale, self.width, self.height, int)
+ oldChunkSize = int(self.chunkSize)
+ self.chunkSize = 4 * width * height
+ changed = self.chunkSize != oldChunkSize
+ return changed
+
+ def finalizeFrame(self, imageData):
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ if self.scale != 100 \
+ or self.x != 0 or self.y != 0:
+ frame = BlankFrame(self.width, self.height)
+ frame.paste(image, box=(self.x, self.y))
+ else:
+ frame = image
+ return frame
diff --git a/src/components/spectrum.ui b/src/components/spectrum.ui
new file mode 100644
index 0000000..59ca0b8
--- /dev/null
+++ b/src/components/spectrum.ui
@@ -0,0 +1,582 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 586
+ 197
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 197
+
+
+
+ Form
+
+
+
-
+
+
+ 4
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Type
+
+
+
+ -
+
+
-
+
+ Spectrum
+
+
+ -
+
+ Histogram
+
+
+ -
+
+ Vector Scope
+
+
+ -
+
+ Musical Scale
+
+
+ -
+
+ Phase
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 5
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ X
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 80
+ 16777215
+
+
+
+ -10000
+
+
+ 10000
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Y
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 80
+ 16777215
+
+
+
+
+ 0
+ 0
+
+
+
+ -10000
+
+
+ 10000
+
+
+ 0
+
+
+
+
+
+ -
+
+
-
+
+
+ Compress
+
+
+
+ -
+
+
+ Mono
+
+
+
+ -
+
+
+ Mirror
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Scale
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QAbstractSpinBox::UpDownArrows
+
+
+ %
+
+
+ 10
+
+
+ 400
+
+
+ 100
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ 0
+
+
+
+
+
+ 0
+ 0
+ 561
+ 72
+
+
+
+
+ QLayout::SetMaximumSize
+
+
+ 0
+
+
-
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 31
+ 0
+
+
+
+ Window
+
+
+ 4
+
+
+
+ -
+
+
-
+
+ hann
+
+
+ -
+
+ gauss
+
+
+ -
+
+ tukey
+
+
+ -
+
+ dolph
+
+
+ -
+
+ cauchy
+
+
+ -
+
+ parzen
+
+
+ -
+
+ poisson
+
+
+ -
+
+ rect
+
+
+ -
+
+ bartlett
+
+
+ -
+
+ hanning
+
+
+ -
+
+ hamming
+
+
+ -
+
+ blackman
+
+
+ -
+
+ welch
+
+
+ -
+
+ flattop
+
+
+ -
+
+ bharris
+
+
+ -
+
+ bnuttall
+
+
+ -
+
+ lanczos
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Amplitude
+
+
+ 4
+
+
+
+ -
+
+
-
+
+ Square root
+
+
+ -
+
+ Cubic root
+
+
+ -
+
+ 4thrt
+
+
+ -
+
+ 5thrt
+
+
+ -
+
+ Linear
+
+
+ -
+
+ Logarithmic
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 10
+ 20
+
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Color
+
+
+ 4
+
+
+
+ -
+
+
-
+
+ Channel
+
+
+ -
+
+ Intensity
+
+
+ -
+
+ Rainbow
+
+
+ -
+
+ Moreland
+
+
+ -
+
+ Nebulae
+
+
+ -
+
+ Fire
+
+
+ -
+
+ Fiery
+
+
+ -
+
+ Fruit
+
+
+ -
+
+ Cool
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 10
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 10
+
+
+
+
+
+
+
+
+
diff --git a/src/components/waveform.py b/src/components/waveform.py
index b4b19e9..6c5133d 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -8,7 +8,9 @@ import subprocess
from component import Component
from toolkit.frame import BlankFrame, scale
from toolkit import checkOutput, rgbFromString, pickColor
-from toolkit.ffmpeg import openPipe, closePipe, getAudioDuration, FfmpegVideo
+from toolkit.ffmpeg import (
+ openPipe, closePipe, getAudioDuration, FfmpegVideo, exampleSound
+)
class Component(Component):
@@ -112,6 +114,8 @@ class Component(Component):
if not duration:
return
startPt = duration / 3
+ if startPt + 3 > duration:
+ startPt += startPt - 3
command = [
self.core.FFMPEG_BIN,
@@ -154,29 +158,43 @@ class Component(Component):
hexcolor = QColor(*self.color).name()
opacity = "{0:.1f}".format(self.opacity / 100)
genericPreview = self.settings.value("pref_genericPreview")
+ if self.mode < 3:
+ filter_ = 'showwaves=r=%s:s=%sx%s:mode=%s:colors=%s@%s:scale=%s' % (
+ self.settings.value("outputFrameRate"),
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ self.page.comboBox_mode.currentText().lower()
+ if self.mode != 3 else 'p2p',
+ hexcolor, opacity, amplitude,
+ )
+ elif self.mode > 2:
+ filter_ = (
+ 'showfreqs=s=%sx%s:mode=%s:colors=%s@%s'
+ ':ascale=%s:fscale=%s' % (
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ 'line' if self.mode == 4 else 'bar',
+ hexcolor, opacity, amplitude,
+ 'log' if self.mono else 'lin'
+ )
+ )
return [
'-filter_complex',
'%s%s%s'
- 'showwaves=r=30:s=%sx%s:mode=%s:colors=%s@%s:scale=%s%s%s [v1]; '
- '[v1] scale=%s:%s%s,setpts=2.0*PTS [v]' % (
- 'aevalsrc=sin(1*2*PI*t)*sin(880*2*PI*t),'
- if preview and genericPreview else '[0:a] ',
- 'compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2'
- ',' if self.compress and not preview else (
- 'compand=gain=5,' if self.compress else ''
- ),
- 'aformat=channel_layouts=mono,' if self.mono else '',
- self.settings.value("outputWidth"),
- self.settings.value("outputHeight"),
- str(self.page.comboBox_mode.currentText()).lower(),
- hexcolor, opacity, amplitude,
+ '%s%s%s [v1]; '
+ '[v1] scale=%s:%s%s [v]' % (
+ exampleSound() if preview and genericPreview else '[0:a] ',
+ 'compand=gain=4,' if self.compress else '',
+ 'aformat=channel_layouts=mono,'
+ if self.mono and self.mode < 3 else '',
+ filter_,
', drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=4:color=%s@%s' % (
hexcolor, opacity
) if self.mode < 2 else '',
', hflip' if self.mirror else'',
w, h,
- ', trim=duration=%s' % "{0:.3f}".format(startPt + 1)
+ ', trim=duration=%s' % "{0:.3f}".format(startPt + 3)
if preview else '',
),
'-map', '[v]',
diff --git a/src/components/waveform.ui b/src/components/waveform.ui
index 0e40380..5473f33 100644
--- a/src/components/waveform.ui
+++ b/src/components/waveform.ui
@@ -66,12 +66,17 @@
-
- P2p
+ Point
-
- Point
+ Frequency Bar
+
+
+ -
+
+ Frequency Line
@@ -180,12 +185,16 @@
-
- Wave Color
+ Color
-
-
+
+
+ Qt::ImhNone
+
+
-
@@ -244,10 +253,10 @@
%
- 10
+ 0
- 400
+ 100
100
diff --git a/src/mainwindow.py b/src/mainwindow.py
index a97081e..d9e95e2 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -581,7 +581,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.showMessage(
msg=msg,
detail=detail,
- icon='Warning',
+ icon='Critical',
)
def changeEncodingStatus(self, status):
diff --git a/src/toolkit/common.py b/src/toolkit/common.py
index 5d424e0..db278c0 100644
--- a/src/toolkit/common.py
+++ b/src/toolkit/common.py
@@ -113,3 +113,46 @@ def formatTraceback(tb=None):
import sys
tb = sys.exc_info()[2]
return 'Traceback:\n%s' % "\n".join(traceback.format_tb(tb))
+
+
+def connectWidget(widget, func):
+ if type(widget) == QtWidgets.QLineEdit:
+ widget.textChanged.connect(func)
+ elif type(widget) == QtWidgets.QSpinBox \
+ or type(widget) == QtWidgets.QDoubleSpinBox:
+ widget.valueChanged.connect(func)
+ elif type(widget) == QtWidgets.QCheckBox:
+ widget.stateChanged.connect(func)
+ elif type(widget) == QtWidgets.QComboBox:
+ widget.currentIndexChanged.connect(func)
+ else:
+ return False
+ return True
+
+
+def setWidgetValue(widget, val):
+ '''Generic setValue method for use with any typical QtWidget'''
+ if type(widget) == QtWidgets.QLineEdit:
+ widget.setText(val)
+ elif type(widget) == QtWidgets.QSpinBox \
+ or type(widget) == QtWidgets.QDoubleSpinBox:
+ widget.setValue(val)
+ elif type(widget) == QtWidgets.QCheckBox:
+ widget.setChecked(val)
+ elif type(widget) == QtWidgets.QComboBox:
+ widget.setCurrentIndex(val)
+ else:
+ return False
+ return True
+
+
+def getWidgetValue(widget):
+ if type(widget) == QtWidgets.QLineEdit:
+ return widget.text()
+ elif type(widget) == QtWidgets.QSpinBox \
+ or type(widget) == QtWidgets.QDoubleSpinBox:
+ return widget.value()
+ elif type(widget) == QtWidgets.QCheckBox:
+ return widget.isChecked()
+ elif type(widget) == QtWidgets.QComboBox:
+ return widget.currentIndex()
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index 4ea2863..3421049 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -37,7 +37,6 @@ class FfmpegVideo:
self.frameNo = -1
self.currentFrame = 'None'
self.map_ = None
- self.debug = False
if 'loopVideo' in kwargs and kwargs['loopVideo']:
self.loopValue = '-1'
@@ -48,8 +47,6 @@ class FfmpegVideo:
kwargs['filter_'].insert(0, '-filter_complex')
else:
kwargs['filter_'] = None
- if 'debug' in kwargs:
- self.debug = True
self.command = [
core.Core.FFMPEG_BIN,
@@ -90,16 +87,15 @@ class FfmpegVideo:
self.frameBuffer.task_done()
def fillBuffer(self):
- if self.debug:
- print(" ".join([word for word in self.command]))
- err = sys.__stdout__
- else:
- err = subprocess.DEVNULL
-
- self.pipe = openPipe(
- self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=err, bufsize=10**8
- )
+ logFilename = os.path.join(
+ core.Core.dataDir, 'extra_%s.log' % str(self.component.compPos))
+ with open(logFilename, 'w') as log:
+ log.write(" ".join(self.command) + '\n\n')
+ with open(logFilename, 'a') as log:
+ self.pipe = openPipe(
+ self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=log, bufsize=10**8
+ )
while True:
if self.parent.canceled:
break
@@ -111,10 +107,18 @@ class FfmpegVideo:
self.frameBuffer.put((self.frameNo-1, self.lastFrame))
continue
except AttributeError:
- FfmpegVideo.threadError = ComponentError(self.component, 'video')
+ FfmpegVideo.threadError = ComponentError(
+ self.component, 'video',
+ "Video seemed playable but wasn't."
+ )
break
- self.currentFrame = self.pipe.stdout.read(self.chunkSize)
+ try:
+ self.currentFrame = self.pipe.stdout.read(self.chunkSize)
+ except ValueError:
+ FfmpegVideo.threadError = ComponentError(
+ self.component, 'video')
+
if len(self.currentFrame) != 0:
self.frameBuffer.put((self.frameNo, self.currentFrame))
self.lastFrame = self.currentFrame
@@ -446,3 +450,10 @@ def readAudioFile(filename, videoWorker):
completeAudioArray = completeAudioArrayCopy
return (completeAudioArray, duration)
+
+
+def exampleSound():
+ return (
+ 'aevalsrc=tan(random(1)*PI*t)*sin(random(0)*2*PI*t),'
+ 'apulsator=offset_l=0.5:offset_r=0.5,'
+ )
--
cgit v1.2.3
From 3c1b52205f183e9a2c943c5f666ed2c01db3aaf5 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Tue, 1 Aug 2017 17:57:39 -0400
Subject: component class now tracks colorwidgets
so adding new color-selection widgets is now simple
---
setup.py | 2 +-
src/component.py | 73 +++++++++++++++++++++++++++++++++++++++++-----
src/components/color.py | 58 +++++-------------------------------
src/components/original.py | 35 +++-------------------
src/components/text.py | 27 ++---------------
src/components/waveform.py | 40 ++++---------------------
src/toolkit/common.py | 19 ------------
src/toolkit/frame.py | 6 ++--
8 files changed, 90 insertions(+), 170 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/setup.py b/setup.py
index d4f226b..4a4511f 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup
import os
-__version__ = '2.0.0.rc2'
+__version__ = '2.0.0.rc3'
def package_files(directory):
diff --git a/src/component.py b/src/component.py
index 36ad9d3..d47aeae 100644
--- a/src/component.py
+++ b/src/component.py
@@ -3,18 +3,20 @@
on making a valid component.
'''
from PyQt5 import uic, QtCore, QtWidgets
+from PyQt5.QtGui import QColor
import os
import sys
import time
from toolkit.frame import BlankFrame
-from toolkit import getWidgetValue, setWidgetValue, connectWidget
+from toolkit import (
+ getWidgetValue, setWidgetValue, connectWidget, rgbFromString
+)
class ComponentMetaclass(type(QtCore.QObject)):
'''
- Checks the validity of each Component class imported, and
- mutates some attributes for easier use by the core program.
+ Checks the validity of each Component class and mutates some attrs.
E.g., takes only major version from version string & decorates methods
'''
@@ -173,6 +175,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._trackedWidgets = {}
self._presetNames = {}
self._commandArgs = {}
+ self._colorWidgets = {}
+ self._relativeWidgets = {}
self._lockedProperties = None
self._lockedError = None
@@ -188,7 +192,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
)
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
- # Critical Methods
+ # Render Methods
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
def previewRender(self):
@@ -286,7 +290,17 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
Call super() at the END if you need to subclass this.
'''
for attr, widget in self._trackedWidgets.items():
- setattr(self, attr, getWidgetValue(widget))
+ if attr in self._colorWidgets:
+ rgbTuple = rgbFromString(widget.text())
+ setattr(self, attr, rgbTuple)
+ btnStyle = (
+ "QPushButton { background-color : %s; outline: none; }"
+ % QColor(*rgbTuple).name()
+ )
+ self._colorWidgets[attr].setStyleSheet(btnStyle)
+ else:
+ setattr(self, attr, getWidgetValue(widget))
+
if not self.core.openingProject:
self.parent.drawPreview()
saveValueStore = self.savePreset()
@@ -305,7 +319,16 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
key = attr if attr not in self._presetNames \
else self._presetNames[attr]
val = presetDict[key]
- setWidgetValue(widget, val)
+
+ if attr in self._colorWidgets:
+ widget.setText('%s,%s,%s' % val)
+ btnStyle = (
+ "QPushButton { background-color : %s; outline: none; }"
+ % QColor(*val).name()
+ )
+ self._colorWidgets[attr].setStyleSheet(btnStyle)
+ else:
+ setWidgetValue(widget, val)
def savePreset(self):
saveValueStore = {}
@@ -352,7 +375,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._trackedWidgets = trackDict
for kwarg in kwargs:
try:
- if kwarg in ('presetNames', 'commandArgs'):
+ if kwarg in (
+ 'presetNames',
+ 'commandArgs',
+ 'colorWidgets',
+ 'relativeWidgets',
+ ):
setattr(self, '_%s' % kwarg, kwargs[kwarg])
else:
raise ComponentError(
@@ -360,6 +388,37 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
except ComponentError:
continue
+ if kwarg == 'colorWidgets':
+ def makeColorFunc(attr):
+ def pickColor_():
+ self.pickColor(
+ self._trackedWidgets[attr],
+ self._colorWidgets[attr]
+ )
+ return pickColor_
+ self._colorFuncs = {
+ attr: makeColorFunc(attr) for attr in kwargs[kwarg]
+ }
+ for attr, func in self._colorFuncs.items():
+ self._colorWidgets[attr].clicked.connect(func)
+ self._colorWidgets[attr].setStyleSheet(
+ "QPushButton {"
+ "background-color : #FFFFFF; outline: none; }"
+ )
+
+ def pickColor(self, textWidget, button):
+ '''Use color picker to get color input from the user.'''
+ dialog = QtWidgets.QColorDialog()
+ dialog.setOption(QtWidgets.QColorDialog.ShowAlphaChannel, True)
+ color = dialog.getColor()
+ if color.isValid():
+ RGBstring = '%s,%s,%s' % (
+ str(color.red()), str(color.green()), str(color.blue()))
+ btnStyle = "QPushButton{background-color: %s; outline: none;}" \
+ % color.name()
+ textWidget.setText(RGBstring)
+ button.setStyleSheet(btnStyle)
+
def lockProperties(self, propList):
self._lockedProperties = propList
diff --git a/src/components/color.py b/src/components/color.py
index 2abd79a..d6fffc6 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -6,7 +6,6 @@ import os
from component import Component
from toolkit.frame import BlankFrame, FloodFrame, FramePainter, PaintColor
-from toolkit import rgbFromString, pickColor
class Component(Component):
@@ -14,25 +13,12 @@ class Component(Component):
version = '1.0.0'
def widget(self, *args):
- self.color1 = (0, 0, 0)
- self.color2 = (133, 133, 133)
self.x = 0
self.y = 0
super().widget(*args)
- self.page.lineEdit_color1.setText('%s,%s,%s' % self.color1)
- self.page.lineEdit_color2.setText('%s,%s,%s' % self.color2)
-
- btnStyle1 = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color1).name()
-
- btnStyle2 = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color2).name()
-
- self.page.pushButton_color1.setStyleSheet(btnStyle1)
- self.page.pushButton_color2.setStyleSheet(btnStyle2)
- self.page.pushButton_color1.clicked.connect(lambda: self.pickColor(1))
- self.page.pushButton_color2.clicked.connect(lambda: self.pickColor(2))
+ self.page.lineEdit_color1.setText('0,0,0')
+ self.page.lineEdit_color2.setText('133,133,133')
# disable color #2 until non-default 'fill' option gets changed
self.page.lineEdit_color2.setDisabled(True)
@@ -66,16 +52,18 @@ class Component(Component):
'LG_end': self.page.spinBox_linearGradient_end,
'RG_centre': self.page.spinBox_radialGradient_spread,
'fillType': self.page.comboBox_fill,
+ 'color1': self.page.lineEdit_color1,
+ 'color2': self.page.lineEdit_color2,
}, presetNames={
'sizeWidth': 'width',
'sizeHeight': 'height',
- }
+ }, colorWidgets={
+ 'color1': self.page.pushButton_color1,
+ 'color2': self.page.pushButton_color2,
+ },
)
def update(self):
- self.color1 = rgbFromString(self.page.lineEdit_color1.text())
- self.color2 = rgbFromString(self.page.lineEdit_color2.text())
-
fillType = self.page.comboBox_fill.currentIndex()
if fillType == 0:
self.page.lineEdit_color2.setEnabled(False)
@@ -161,36 +149,6 @@ class Component(Component):
return image.finalize()
- def loadPreset(self, pr, *args):
- super().loadPreset(pr, *args)
-
- self.page.lineEdit_color1.setText('%s,%s,%s' % pr['color1'])
- self.page.lineEdit_color2.setText('%s,%s,%s' % pr['color2'])
-
- btnStyle1 = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*pr['color1']).name()
- btnStyle2 = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*pr['color2']).name()
- self.page.pushButton_color1.setStyleSheet(btnStyle1)
- self.page.pushButton_color2.setStyleSheet(btnStyle2)
-
- def savePreset(self):
- saveValueStore = super().savePreset()
- saveValueStore['color1'] = self.color1
- saveValueStore['color2'] = self.color2
- return saveValueStore
-
- def pickColor(self, num):
- RGBstring, btnStyle = pickColor()
- if not RGBstring:
- return
- if num == 1:
- self.page.lineEdit_color1.setText(RGBstring)
- self.page.pushButton_color1.setStyleSheet(btnStyle)
- else:
- self.page.lineEdit_color2.setText(RGBstring)
- self.page.pushButton_color2.setStyleSheet(btnStyle)
-
def commandHelp(self):
print('Specify a color:\n color=255,255,255')
diff --git a/src/components/original.py b/src/components/original.py
index 621af6f..950ac7b 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -8,7 +8,6 @@ from copy import copy
from component import Component
from toolkit.frame import BlankFrame
-from toolkit import rgbFromString, pickColor
class Component(Component):
@@ -22,7 +21,6 @@ class Component(Component):
return ['pcm']
def widget(self, *args):
- self.visColor = (255, 255, 255)
self.scale = 20
self.y = 0
super().widget(*args)
@@ -33,35 +31,17 @@ class Component(Component):
self.page.comboBox_visLayout.addItem("Top")
self.page.comboBox_visLayout.setCurrentIndex(0)
- self.page.lineEdit_visColor.setText('%s,%s,%s' % self.visColor)
- self.page.pushButton_visColor.clicked.connect(lambda: self.pickColor())
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.visColor).name()
- self.page.pushButton_visColor.setStyleSheet(btnStyle)
+ self.page.lineEdit_visColor.setText('255,255,255')
self.trackWidgets({
+ 'visColor': self.page.lineEdit_visColor,
'layout': self.page.comboBox_visLayout,
'scale': self.page.spinBox_scale,
'y': self.page.spinBox_y,
+ }, colorWidgets={
+ 'visColor': self.page.pushButton_visColor,
})
- def update(self):
- self.visColor = rgbFromString(self.page.lineEdit_visColor.text())
- super().update()
-
- def loadPreset(self, pr, *args):
- super().loadPreset(pr, *args)
-
- self.page.lineEdit_visColor.setText('%s,%s,%s' % pr['visColor'])
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*pr['visColor']).name()
- self.page.pushButton_visColor.setStyleSheet(btnStyle)
-
- def savePreset(self):
- saveValueStore = super().savePreset()
- saveValueStore['visColor'] = self.visColor
- return saveValueStore
-
def previewRender(self):
spectrum = numpy.fromfunction(
lambda x: float(self.scale)/2500*(x-128)**2, (255,), dtype="int16")
@@ -99,13 +79,6 @@ class Component(Component):
self.spectrumArray[arrayNo],
self.visColor, self.layout)
- def pickColor(self):
- RGBstring, btnStyle = pickColor()
- if not RGBstring:
- return
- self.page.lineEdit_visColor.setText(RGBstring)
- self.page.pushButton_visColor.setStyleSheet(btnStyle)
-
def transformData(
self, i, completeAudioArray, sampleSize,
smoothConstantDown, smoothConstantUp, lastSpectrum):
diff --git a/src/components/text.py b/src/components/text.py
index 8a302ff..1fe3467 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -5,7 +5,6 @@ import os
from component import Component
from toolkit.frame import FramePainter
-from toolkit import rgbFromString, pickColor
class Component(Component):
@@ -33,11 +32,6 @@ class Component(Component):
self.page.comboBox_textAlign.addItem("Right")
self.page.lineEdit_textColor.setText('%s,%s,%s' % self.textColor)
- self.page.pushButton_textColor.clicked.connect(self.pickColor)
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.textColor).name()
- self.page.pushButton_textColor.setStyleSheet(btnStyle)
-
self.page.lineEdit_title.setText(self.title)
self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
self.page.spinBox_fontSize.setValue(int(self.fontSize))
@@ -48,21 +42,18 @@ class Component(Component):
self.update
)
self.trackWidgets({
+ 'textColor': self.page.lineEdit_textColor,
'title': self.page.lineEdit_title,
'alignment': self.page.comboBox_textAlign,
'fontSize': self.page.spinBox_fontSize,
'xPosition': self.page.spinBox_xTextAlign,
'yPosition': self.page.spinBox_yTextAlign,
+ }, colorWidgets={
+ 'textColor': self.page.pushButton_textColor,
})
def update(self):
self.titleFont = self.page.fontComboBox_titleFont.currentFont()
- self.textColor = rgbFromString(
- self.page.lineEdit_textColor.text())
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.textColor).name()
- self.page.pushButton_textColor.setStyleSheet(btnStyle)
-
super().update()
def getXY(self):
@@ -86,15 +77,10 @@ class Component(Component):
font = QFont()
font.fromString(pr['titleFont'])
self.page.fontComboBox_titleFont.setCurrentFont(font)
- self.page.lineEdit_textColor.setText('%s,%s,%s' % pr['textColor'])
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*pr['textColor']).name()
- self.page.pushButton_textColor.setStyleSheet(btnStyle)
def savePreset(self):
saveValueStore = super().savePreset()
saveValueStore['titleFont'] = self.titleFont.toString()
- saveValueStore['textColor'] = self.textColor
return saveValueStore
def previewRender(self):
@@ -122,13 +108,6 @@ class Component(Component):
return image.finalize()
- def pickColor(self):
- RGBstring, btnStyle = pickColor()
- if not RGBstring:
- return
- self.page.lineEdit_textColor.setText(RGBstring)
- self.page.pushButton_textColor.setStyleSheet(btnStyle)
-
def commandHelp(self):
print('Enter a string to use as centred white text:')
print(' "title=User Error"')
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 6c5133d..9c3cf86 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -7,7 +7,7 @@ import subprocess
from component import Component
from toolkit.frame import BlankFrame, scale
-from toolkit import checkOutput, rgbFromString, pickColor
+from toolkit import checkOutput
from toolkit.ffmpeg import (
openPipe, closePipe, getAudioDuration, FfmpegVideo, exampleSound
)
@@ -18,15 +18,9 @@ class Component(Component):
version = '1.0.0'
def widget(self, *args):
- self.color = (255, 255, 255)
super().widget(*args)
- self.page.lineEdit_color.setText('%s,%s,%s' % self.color)
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color).name()
- self.page.pushButton_color.setStyleSheet(btnStyle)
- self.page.pushButton_color.clicked.connect(lambda: self.pickColor())
- self.page.spinBox_scale.valueChanged.connect(self.updateChunksize)
+ self.page.lineEdit_color.setText('255,255,255')
if hasattr(self.parent, 'window'):
self.parent.window.lineEdit_audioFile.textChanged.connect(
@@ -35,6 +29,7 @@ class Component(Component):
self.trackWidgets(
{
+ 'color': self.page.lineEdit_color,
'mode': self.page.comboBox_mode,
'amplitude': self.page.comboBox_amplitude,
'x': self.page.spinBox_x,
@@ -44,36 +39,11 @@ class Component(Component):
'opacity': self.page.spinBox_opacity,
'compress': self.page.checkBox_compress,
'mono': self.page.checkBox_mono,
+ }, colorWidgets={
+ 'color': self.page.pushButton_color,
}
)
- def update(self):
- self.color = rgbFromString(self.page.lineEdit_color.text())
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*self.color).name()
- self.page.pushButton_color.setStyleSheet(btnStyle)
- super().update()
-
- def loadPreset(self, pr, *args):
- super().loadPreset(pr, *args)
-
- self.page.lineEdit_color.setText('%s,%s,%s' % pr['color'])
- btnStyle = "QPushButton { background-color : %s; outline: none; }" \
- % QColor(*pr['color']).name()
- self.page.pushButton_color.setStyleSheet(btnStyle)
-
- def savePreset(self):
- saveValueStore = super().savePreset()
- saveValueStore['color'] = self.color
- return saveValueStore
-
- def pickColor(self):
- RGBstring, btnStyle = pickColor()
- if not RGBstring:
- return
- self.page.lineEdit_color.setText(RGBstring)
- self.page.pushButton_color.setStyleSheet(btnStyle)
-
def previewRender(self):
self.updateChunksize()
frame = self.getPreviewFrame(self.width, self.height)
diff --git a/src/toolkit/common.py b/src/toolkit/common.py
index db278c0..eba57d9 100644
--- a/src/toolkit/common.py
+++ b/src/toolkit/common.py
@@ -74,25 +74,6 @@ def disableWhenOpeningProject(func):
return decorator
-def pickColor():
- '''
- 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 = QtWidgets.QColorDialog()
- dialog.setOption(QtWidgets.QColorDialog.ShowAlphaChannel, True)
- color = dialog.getColor()
- if color.isValid():
- RGBstring = '%s,%s,%s' % (
- str(color.red()), str(color.green()), str(color.blue()))
- btnStyle = "QPushButton{background-color: %s; outline: none;}" \
- % color.name()
- return RGBstring, btnStyle
- else:
- return None, None
-
-
def rgbFromString(string):
'''Turns an RGB string like "255, 255, 255" into a tuple'''
try:
diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py
index f42d4c9..c007188 100644
--- a/src/toolkit/frame.py
+++ b/src/toolkit/frame.py
@@ -42,9 +42,9 @@ class PaintColor(QtGui.QColor):
super().__init__(b, g, r, a)
-def scale(scale, width, height, returntype=None):
- width = (float(width) / 100.0) * float(scale)
- height = (float(height) / 100.0) * float(scale)
+def scale(scalePercent, width, height, returntype=None):
+ width = (float(width) / 100.0) * float(scalePercent)
+ height = (float(height) / 100.0) * float(scalePercent)
if returntype == str:
return (str(math.ceil(width)), str(math.ceil(height)))
elif returntype == int:
--
cgit v1.2.3
From 5784cdbcf87556b61519782cd1fc27065ffbc631 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Tue, 1 Aug 2017 21:57:36 -0400
Subject: x/y pixel values update to match output resolution
---
src/component.py | 39 ++++++++++++++++++++++++++++++++++++---
src/components/color.py | 3 +++
src/components/image.py | 3 +++
src/components/original.py | 2 ++
src/components/spectrum.py | 3 +++
src/components/text.py | 19 +++++++++++--------
src/components/video.py | 3 +++
src/components/waveform.py | 3 +++
src/mainwindow.py | 5 ++++-
9 files changed, 68 insertions(+), 12 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index d47aeae..5dfe2ab 100644
--- a/src/component.py
+++ b/src/component.py
@@ -6,6 +6,7 @@ from PyQt5 import uic, QtCore, QtWidgets
from PyQt5.QtGui import QColor
import os
import sys
+import math
import time
from toolkit.frame import BlankFrame
@@ -176,7 +177,9 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._presetNames = {}
self._commandArgs = {}
self._colorWidgets = {}
+ self._colorFuncs = {}
self._relativeWidgets = {}
+ self._relativeValues = {}
self._lockedProperties = None
self._lockedError = None
@@ -291,14 +294,44 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
'''
for attr, widget in self._trackedWidgets.items():
if attr in self._colorWidgets:
+ # Color Widgets: text stored as tuple & update the button color
rgbTuple = rgbFromString(widget.text())
- setattr(self, attr, rgbTuple)
btnStyle = (
"QPushButton { background-color : %s; outline: none; }"
- % QColor(*rgbTuple).name()
- )
+ % QColor(*rgbTuple).name())
self._colorWidgets[attr].setStyleSheet(btnStyle)
+ setattr(self, attr, rgbTuple)
+
+ elif attr in self._relativeWidgets:
+ # Relative widgets: number scales to fit export resolution
+ if self._relativeWidgets[attr] == 'x':
+ dimension = self.width
+ else:
+ dimension = self.height
+ try:
+ oldUserValue = getattr(self, attr)
+ except AttributeError:
+ oldUserValue = self._trackedWidgets[attr].value()
+ newUserValue = self._trackedWidgets[attr].value()
+ newRelativeVal = newUserValue / dimension
+
+ if attr in self._relativeValues:
+ if oldUserValue == newUserValue:
+ oldRelativeVal = self._relativeValues[attr]
+ if oldRelativeVal != newRelativeVal:
+ # Float changed without pixel value changing, which
+ # means the pixel value needs to be updated
+ self._trackedWidgets[attr].blockSignals(True)
+ self._trackedWidgets[attr].setValue(
+ math.ceil(dimension * oldRelativeVal))
+ self._trackedWidgets[attr].blockSignals(False)
+ if oldUserValue != newUserValue \
+ or attr not in self._relativeValues:
+ self._relativeValues[attr] = newRelativeVal
+ setattr(self, attr, self._trackedWidgets[attr].value())
+
else:
+ # Normal tracked widget
setattr(self, attr, getWidgetValue(widget))
if not self.core.openingProject:
diff --git a/src/components/color.py b/src/components/color.py
index d6fffc6..703caca 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -60,6 +60,9 @@ class Component(Component):
}, colorWidgets={
'color1': self.page.pushButton_color1,
'color2': self.page.pushButton_color2,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
},
)
diff --git a/src/components/image.py b/src/components/image.py
index a96f127..2ffa5a1 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -28,6 +28,9 @@ class Component(Component):
'imagePath': 'image',
'xPosition': 'x',
'yPosition': 'y',
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
},
)
diff --git a/src/components/original.py b/src/components/original.py
index 950ac7b..67e3239 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -40,6 +40,8 @@ class Component(Component):
'y': self.page.spinBox_y,
}, colorWidgets={
'visColor': self.page.pushButton_visColor,
+ }, relativeWidgets={
+ 'y': 'y',
})
def previewRender(self):
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 8ab8404..2cc641d 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -49,6 +49,9 @@ class Component(Component):
'compress': self.page.checkBox_compress,
'mono': self.page.checkBox_mono,
'hue': self.page.spinBox_hue,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
}
)
for widget in self._trackedWidgets.values():
diff --git a/src/components/text.py b/src/components/text.py
index 1fe3467..0f87038 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -17,15 +17,12 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
- height = int(self.settings.value('outputHeight'))
- width = int(self.settings.value('outputWidth'))
+ # height = int(self.settings.value('outputHeight'))
+ # width = int(self.settings.value('outputWidth'))
self.textColor = (255, 255, 255)
self.title = 'Text'
self.alignment = 1
- self.fontSize = height / 13.5
- fm = QtGui.QFontMetrics(self.titleFont)
- self.xPosition = width / 2 - fm.width(self.title)/2
- self.yPosition = height / 2 * 1.036
+ self.fontSize = self.height / 13.5
self.page.comboBox_textAlign.addItem("Left")
self.page.comboBox_textAlign.addItem("Middle")
@@ -35,8 +32,11 @@ class Component(Component):
self.page.lineEdit_title.setText(self.title)
self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
self.page.spinBox_fontSize.setValue(int(self.fontSize))
- self.page.spinBox_xTextAlign.setValue(int(self.xPosition))
- self.page.spinBox_yTextAlign.setValue(int(self.yPosition))
+
+ fm = QtGui.QFontMetrics(self.titleFont)
+ self.page.spinBox_xTextAlign.setValue(
+ self.width / 2 - fm.width(self.title)/2)
+ self.page.spinBox_yTextAlign.setValue(self.height / 2 * 1.036)
self.page.fontComboBox_titleFont.currentFontChanged.connect(
self.update
@@ -50,6 +50,9 @@ class Component(Component):
'yPosition': self.page.spinBox_yTextAlign,
}, colorWidgets={
'textColor': self.page.pushButton_textColor,
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
})
def update(self):
diff --git a/src/components/video.py b/src/components/video.py
index 6cd16e5..3569d17 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -38,6 +38,9 @@ class Component(Component):
'loopVideo': 'loop',
'xPosition': 'x',
'yPosition': 'y',
+ }, relativeWidgets={
+ 'xPosition': 'x',
+ 'yPosition': 'y',
}
)
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 9c3cf86..a25116b 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -41,6 +41,9 @@ class Component(Component):
'mono': self.page.checkBox_mono,
}, colorWidgets={
'color': self.page.pushButton_color,
+ }, relativeWidgets={
+ 'x': 'x',
+ 'y': 'y',
}
)
diff --git a/src/mainwindow.py b/src/mainwindow.py
index d9e95e2..1c8806d 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -644,9 +644,12 @@ class MainWindow(QtWidgets.QMainWindow):
def updateResolution(self):
resIndex = int(self.window.comboBox_resolution.currentIndex())
res = Core.resolutions[resIndex].split('x')
+ changed = res[0] != self.settings.value("outputWidth")
self.settings.setValue('outputWidth', res[0])
self.settings.setValue('outputHeight', res[1])
- self.drawPreview()
+ if changed:
+ for i in range(len(self.core.selectedComponents)):
+ self.core.updateComponent(i)
def drawPreview(self, force=False, **kwargs):
'''Use autosave keyword arg to force saving or not saving if needed'''
--
cgit v1.2.3
From 6611492b30a7daf7bdbe77f6e12f9d322bdd90c1 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Thu, 3 Aug 2017 00:44:46 -0400
Subject: relative gradients & last good frame used for preview errors
---
src/components/color.py | 5 +++++
src/components/spectrum.py | 15 ++++++++++-----
src/components/text.py | 2 --
src/components/video.py | 15 ++++-----------
src/components/waveform.py | 15 ++++++++++-----
5 files changed, 29 insertions(+), 23 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/components/color.py b/src/components/color.py
index 2b100d9..f5d618e 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -65,6 +65,11 @@ class Component(Component):
'y': 'y',
'sizeWidth': 'x',
'sizeHeight': 'y',
+ 'RG_start': 'x',
+ 'LG_start': 'x',
+ 'RG_end': 'x',
+ 'LG_end': 'x',
+ 'RG_centre': 'x',
},
)
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 2cc641d..9a0c59a 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -20,6 +20,7 @@ class Component(Component):
def widget(self, *args):
self.previewFrame = None
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.chunkSize = 4 * self.width * self.height
self.changedOptions = True
@@ -268,11 +269,15 @@ class Component(Component):
return changed
def finalizeFrame(self, imageData):
- image = Image.frombytes(
- 'RGBA',
- scale(self.scale, self.width, self.height, int),
- imageData
- )
+ try:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ self._image = image
+ except ValueError:
+ image = self._image
if self.scale != 100 \
or self.x != 0 or self.y != 0:
frame = BlankFrame(self.width, self.height)
diff --git a/src/components/text.py b/src/components/text.py
index be4de4a..2a5d433 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -17,8 +17,6 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
- # height = int(self.settings.value('outputHeight'))
- # width = int(self.settings.value('outputWidth'))
self.textColor = (255, 255, 255)
self.title = 'Text'
self.alignment = 1
diff --git a/src/components/video.py b/src/components/video.py
index 3569d17..2cd67c6 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -16,12 +16,12 @@ class Component(Component):
def widget(self, *args):
self.videoPath = ''
- self.badVideo = False
self.badAudio = False
self.x = 0
self.y = 0
self.loopVideo = False
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.page.pushButton_video.clicked.connect(self.pickVideo)
self.trackWidgets(
{
@@ -70,8 +70,6 @@ class Component(Component):
if not self.videoPath:
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(outputFile):
@@ -199,14 +197,10 @@ class Component(Component):
'RGBA',
scale(self.scale, self.width, self.height, int),
imageData)
-
+ self._image = image
except ValueError:
- print(
- '### BAD VIDEO SELECTED ###\n'
- 'Video will not export with these settings'
- )
- self.badVideo = True
- return BlankFrame(self.width, self.height)
+ # use last good frame
+ image = self._image
if self.scale != 100 \
or self.xPosition != 0 or self.yPosition != 0:
@@ -214,5 +208,4 @@ class Component(Component):
frame.paste(image, box=(self.xPosition, self.yPosition))
else:
frame = image
- self.badVideo = False
return frame
diff --git a/src/components/waveform.py b/src/components/waveform.py
index a25116b..526e6fb 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -19,6 +19,7 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
+ self._image = BlankFrame(self.width, self.height)
self.page.lineEdit_color.setText('255,255,255')
@@ -178,11 +179,15 @@ class Component(Component):
self.chunkSize = 4 * width * height
def finalizeFrame(self, imageData):
- image = Image.frombytes(
- 'RGBA',
- scale(self.scale, self.width, self.height, int),
- imageData
- )
+ try:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, self.width, self.height, int),
+ imageData
+ )
+ self._image = image
+ except ValueError:
+ image = self._image
if self.scale != 100 \
or self.x != 0 or self.y != 0:
frame = BlankFrame(self.width, self.height)
--
cgit v1.2.3
From 219e846984bb10e9674432fa7aeac4157635c743 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Thu, 3 Aug 2017 12:16:57 -0400
Subject: relativeWidgets might as well be a list
---
src/component.py | 5 +---
src/components/color.py | 63 +++++++++++++++++++++-------------------------
src/components/image.py | 36 ++++++++++++--------------
src/components/original.py | 6 ++---
src/components/spectrum.py | 47 ++++++++++++++++------------------
src/components/text.py | 8 +++---
src/components/video.py | 37 +++++++++++++--------------
src/components/waveform.py | 35 ++++++++++++--------------
8 files changed, 106 insertions(+), 131 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index 5dfe2ab..c5bc44b 100644
--- a/src/component.py
+++ b/src/component.py
@@ -304,10 +304,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
elif attr in self._relativeWidgets:
# Relative widgets: number scales to fit export resolution
- if self._relativeWidgets[attr] == 'x':
- dimension = self.width
- else:
- dimension = self.height
+ dimension = self.width
try:
oldUserValue = getattr(self, attr)
except AttributeError:
diff --git a/src/components/color.py b/src/components/color.py
index f5d618e..5d1233e 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -37,41 +37,34 @@ class Component(Component):
self.page.comboBox_fill.addItem(label)
self.page.comboBox_fill.setCurrentIndex(0)
- self.trackWidgets(
- {
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'sizeWidth': self.page.spinBox_width,
- 'sizeHeight': self.page.spinBox_height,
- 'trans': self.page.checkBox_trans,
- 'spread': self.page.comboBox_spread,
- 'stretch': self.page.checkBox_stretch,
- 'RG_start': self.page.spinBox_radialGradient_start,
- 'LG_start': self.page.spinBox_linearGradient_start,
- 'RG_end': self.page.spinBox_radialGradient_end,
- 'LG_end': self.page.spinBox_linearGradient_end,
- 'RG_centre': self.page.spinBox_radialGradient_spread,
- 'fillType': self.page.comboBox_fill,
- 'color1': self.page.lineEdit_color1,
- 'color2': self.page.lineEdit_color2,
- }, presetNames={
- 'sizeWidth': 'width',
- 'sizeHeight': 'height',
- }, colorWidgets={
- 'color1': self.page.pushButton_color1,
- 'color2': self.page.pushButton_color2,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- 'sizeWidth': 'x',
- 'sizeHeight': 'y',
- 'RG_start': 'x',
- 'LG_start': 'x',
- 'RG_end': 'x',
- 'LG_end': 'x',
- 'RG_centre': 'x',
- },
- )
+ self.trackWidgets({
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'sizeWidth': self.page.spinBox_width,
+ 'sizeHeight': self.page.spinBox_height,
+ 'trans': self.page.checkBox_trans,
+ 'spread': self.page.comboBox_spread,
+ 'stretch': self.page.checkBox_stretch,
+ 'RG_start': self.page.spinBox_radialGradient_start,
+ 'LG_start': self.page.spinBox_linearGradient_start,
+ 'RG_end': self.page.spinBox_radialGradient_end,
+ 'LG_end': self.page.spinBox_linearGradient_end,
+ 'RG_centre': self.page.spinBox_radialGradient_spread,
+ 'fillType': self.page.comboBox_fill,
+ 'color1': self.page.lineEdit_color1,
+ 'color2': self.page.lineEdit_color2,
+ }, presetNames={
+ 'sizeWidth': 'width',
+ 'sizeHeight': 'height',
+ }, colorWidgets={
+ 'color1': self.page.pushButton_color1,
+ 'color2': self.page.pushButton_color2,
+ }, relativeWidgets=[
+ 'x', 'y',
+ 'sizeWidth', 'sizeHeight',
+ 'LG_start', 'LG_end',
+ 'RG_start', 'RG_end', 'RG_centre',
+ ])
def update(self):
fillType = self.page.comboBox_fill.currentIndex()
diff --git a/src/components/image.py b/src/components/image.py
index 2ffa5a1..19c4796 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -13,26 +13,22 @@ class Component(Component):
def widget(self, *args):
super().widget(*args)
self.page.pushButton_image.clicked.connect(self.pickImage)
- self.trackWidgets(
- {
- 'imagePath': self.page.lineEdit_image,
- 'scale': self.page.spinBox_scale,
- 'rotate': self.page.spinBox_rotate,
- 'color': self.page.spinBox_color,
- 'xPosition': self.page.spinBox_x,
- 'yPosition': self.page.spinBox_y,
- 'stretched': self.page.checkBox_stretch,
- 'mirror': self.page.checkBox_mirror,
- },
- presetNames={
- 'imagePath': 'image',
- 'xPosition': 'x',
- 'yPosition': 'y',
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- },
- )
+ self.trackWidgets({
+ 'imagePath': self.page.lineEdit_image,
+ 'scale': self.page.spinBox_scale,
+ 'rotate': self.page.spinBox_rotate,
+ 'color': self.page.spinBox_color,
+ 'xPosition': self.page.spinBox_x,
+ 'yPosition': self.page.spinBox_y,
+ 'stretched': self.page.checkBox_stretch,
+ }, presetNames={
+ 'mirror': self.page.checkBox_mirror,
+ 'imagePath': 'image',
+ 'xPosition': 'x',
+ 'yPosition': 'y',
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition',
+ ])
def previewRender(self):
return self.drawFrame(self.width, self.height)
diff --git a/src/components/original.py b/src/components/original.py
index 67e3239..f886374 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -40,9 +40,9 @@ class Component(Component):
'y': self.page.spinBox_y,
}, colorWidgets={
'visColor': self.page.pushButton_visColor,
- }, relativeWidgets={
- 'y': 'y',
- })
+ }, relativeWidgets=[
+ 'y',
+ ])
def previewRender(self):
spectrum = numpy.fromfunction(
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 9a0c59a..666e20a 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -30,31 +30,28 @@ class Component(Component):
self.update
)
- self.trackWidgets(
- {
- 'filterType': self.page.comboBox_filterType,
- 'window': self.page.comboBox_window,
- 'mode': self.page.comboBox_mode,
- 'amplitude': self.page.comboBox_amplitude0,
- 'amplitude1': self.page.comboBox_amplitude1,
- 'amplitude2': self.page.comboBox_amplitude2,
- 'display': self.page.comboBox_display,
- 'zoom': self.page.spinBox_zoom,
- 'tc': self.page.spinBox_tc,
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'mirror': self.page.checkBox_mirror,
- 'draw': self.page.checkBox_draw,
- 'scale': self.page.spinBox_scale,
- 'color': self.page.comboBox_color,
- 'compress': self.page.checkBox_compress,
- 'mono': self.page.checkBox_mono,
- 'hue': self.page.spinBox_hue,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- }
- )
+ self.trackWidgets({
+ 'filterType': self.page.comboBox_filterType,
+ 'window': self.page.comboBox_window,
+ 'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude0,
+ 'amplitude1': self.page.comboBox_amplitude1,
+ 'amplitude2': self.page.comboBox_amplitude2,
+ 'display': self.page.comboBox_display,
+ 'zoom': self.page.spinBox_zoom,
+ 'tc': self.page.spinBox_tc,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'draw': self.page.checkBox_draw,
+ 'scale': self.page.spinBox_scale,
+ 'color': self.page.comboBox_color,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
+ 'hue': self.page.spinBox_hue,
+ }, relativeWidgets=[
+ 'x', 'y',
+ ])
for widget in self._trackedWidgets.values():
connectWidget(widget, lambda: self.changed())
diff --git a/src/components/text.py b/src/components/text.py
index 2a5d433..b7c244e 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -48,11 +48,9 @@ class Component(Component):
'yPosition': self.page.spinBox_yTextAlign,
}, colorWidgets={
'textColor': self.page.pushButton_textColor,
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- 'fontSize': 'y',
- })
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition', 'fontSize',
+ ])
def update(self):
self.titleFont = self.page.fontComboBox_titleFont.currentFont()
diff --git a/src/components/video.py b/src/components/video.py
index 2cd67c6..b6bdd52 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -23,26 +23,23 @@ class Component(Component):
super().widget(*args)
self._image = BlankFrame(self.width, self.height)
self.page.pushButton_video.clicked.connect(self.pickVideo)
- self.trackWidgets(
- {
- 'videoPath': self.page.lineEdit_video,
- 'loopVideo': self.page.checkBox_loop,
- 'useAudio': self.page.checkBox_useAudio,
- 'distort': self.page.checkBox_distort,
- 'scale': self.page.spinBox_scale,
- 'volume': self.page.spinBox_volume,
- 'xPosition': self.page.spinBox_x,
- 'yPosition': self.page.spinBox_y,
- }, presetNames={
- 'videoPath': 'video',
- 'loopVideo': 'loop',
- 'xPosition': 'x',
- 'yPosition': 'y',
- }, relativeWidgets={
- 'xPosition': 'x',
- 'yPosition': 'y',
- }
- )
+ self.trackWidgets({
+ 'videoPath': self.page.lineEdit_video,
+ 'loopVideo': self.page.checkBox_loop,
+ 'useAudio': self.page.checkBox_useAudio,
+ 'distort': self.page.checkBox_distort,
+ 'scale': self.page.spinBox_scale,
+ 'volume': self.page.spinBox_volume,
+ 'xPosition': self.page.spinBox_x,
+ 'yPosition': self.page.spinBox_y,
+ }, presetNames={
+ 'videoPath': 'video',
+ 'loopVideo': 'loop',
+ 'xPosition': 'x',
+ 'yPosition': 'y',
+ }, relativeWidgets=[
+ 'xPosition', 'yPosition',
+ ])
def update(self):
if self.page.checkBox_useAudio.isChecked():
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 526e6fb..71cbcac 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -28,25 +28,22 @@ class Component(Component):
self.update
)
- self.trackWidgets(
- {
- 'color': self.page.lineEdit_color,
- 'mode': self.page.comboBox_mode,
- 'amplitude': self.page.comboBox_amplitude,
- 'x': self.page.spinBox_x,
- 'y': self.page.spinBox_y,
- 'mirror': self.page.checkBox_mirror,
- 'scale': self.page.spinBox_scale,
- 'opacity': self.page.spinBox_opacity,
- 'compress': self.page.checkBox_compress,
- 'mono': self.page.checkBox_mono,
- }, colorWidgets={
- 'color': self.page.pushButton_color,
- }, relativeWidgets={
- 'x': 'x',
- 'y': 'y',
- }
- )
+ self.trackWidgets({
+ 'color': self.page.lineEdit_color,
+ 'mode': self.page.comboBox_mode,
+ 'amplitude': self.page.comboBox_amplitude,
+ 'x': self.page.spinBox_x,
+ 'y': self.page.spinBox_y,
+ 'mirror': self.page.checkBox_mirror,
+ 'scale': self.page.spinBox_scale,
+ 'opacity': self.page.spinBox_opacity,
+ 'compress': self.page.checkBox_compress,
+ 'mono': self.page.checkBox_mono,
+ }, colorWidgets={
+ 'color': self.page.pushButton_color,
+ }, relativeWidgets=[
+ 'x', 'y',
+ ])
def previewRender(self):
self.updateChunksize()
--
cgit v1.2.3
From 1c4afc96d69789f16284c067ffd7098dc7b2ca70 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Thu, 10 Aug 2017 16:04:41 -0400
Subject: using the builtin logging module
---
src/component.py | 14 ++++++---
src/components/spectrum.py | 16 ++++++----
src/components/video.py | 19 +++++++++---
src/components/waveform.py | 18 +++++++++---
src/core.py | 73 +++++++++++++++++++++++++++++++++++++++++-----
src/main.py | 6 ++++
src/mainwindow.py | 57 +++++++++++++++++++++++++++---------
src/preview_thread.py | 9 ++++--
src/toolkit/ffmpeg.py | 19 +++++++-----
src/toolkit/frame.py | 6 ++++
src/video_thread.py | 24 ++++++++++-----
11 files changed, 206 insertions(+), 55 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index 5b6f9a7..a1e24db 100644
--- a/src/component.py
+++ b/src/component.py
@@ -8,6 +8,7 @@ import os
import sys
import math
import time
+import logging
from toolkit.frame import BlankFrame
from toolkit import (
@@ -15,6 +16,9 @@ from toolkit import (
)
+log = logging.getLogger('AVP.ComponentHandler')
+
+
class ComponentMetaclass(type(QtCore.QObject)):
'''
Checks the validity of each Component class and mutates some attrs.
@@ -135,17 +139,17 @@ class ComponentMetaclass(type(QtCore.QObject)):
# Turn version string into a number
try:
if 'version' not in attrs:
- print(
+ log.error(
'No version attribute in %s. Defaulting to 1' %
attrs['name'])
attrs['version'] = 1
else:
attrs['version'] = int(attrs['version'].split('.')[0])
except ValueError:
- print('%s component has an invalid version string:\n%s' % (
+ log.critical('%s component has an invalid version string:\n%s' % (
attrs['name'], str(attrs['version'])))
except KeyError:
- print('%s component has no version string.' % attrs['name'])
+ log.critical('%s component has no version string.' % attrs['name'])
else:
return super().__new__(cls, name, parents, attrs)
quit(1)
@@ -546,6 +550,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
and oldRelativeVal != newRelativeVal:
# Float changed without pixel value changing, which
# means the pixel value needs to be updated
+ log.debug('Updating %s #%s\'s relative widget: %s' % (
+ self.name, self.compPos, attr))
self._trackedWidgets[attr].blockSignals(True)
self.updateRelativeWidgetMaximum(attr)
pixelVal = self.pixelValForAttr(attr, oldRelativeVal)
@@ -576,7 +582,7 @@ class ComponentError(RuntimeError):
msg = str(sys.exc_info()[1])
else:
msg = 'Unknown error.'
- print("##### ComponentError by %s's %s: %s" % (
+ log.error("ComponentError by %s's %s: %s" % (
caller.name, name, msg))
# Don't create multiple windows for quickly repeated messages
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 666e20a..32763c0 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -4,6 +4,7 @@ import os
import math
import subprocess
import time
+import logging
from component import Component
from toolkit.frame import BlankFrame, scale
@@ -13,6 +14,9 @@ from toolkit.ffmpeg import (
)
+log = logging.getLogger('AVP.Components.Spectrum')
+
+
class Component(Component):
name = 'Spectrum'
version = '1.0.0'
@@ -68,6 +72,7 @@ class Component(Component):
if not changedSize \
and not self.changedOptions \
and self.previewFrame is not None:
+ log.debug('Comp #%s is reusing old preview frame' % self.compPos)
return self.previewFrame
frame = self.getPreviewFrame()
@@ -131,13 +136,14 @@ class Component(Component):
'-frames:v', '1',
])
logFilename = os.path.join(
- self.core.dataDir, 'preview_%s.log' % str(self.compPos))
- with open(logFilename, 'w') as log:
- log.write(" ".join(command) + '\n\n')
- with open(logFilename, 'a') as log:
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
pipe = openPipe(
command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=log, bufsize=10**8
+ stderr=logf, bufsize=10**8
)
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
diff --git a/src/components/video.py b/src/components/video.py
index b6bdd52..a189f60 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -3,6 +3,7 @@ from PyQt5 import QtGui, QtCore, QtWidgets
import os
import math
import subprocess
+import logging
from component import Component
from toolkit.frame import BlankFrame, scale
@@ -10,6 +11,9 @@ from toolkit.ffmpeg import openPipe, closePipe, testAudioStream, FfmpegVideo
from toolkit import checkOutput
+log = logging.getLogger('AVP.Components.Video')
+
+
class Component(Component):
name = 'Video'
version = '1.0.0'
@@ -134,10 +138,17 @@ class Component(Component):
'-ss', '90',
'-frames:v', '1',
])
- pipe = openPipe(
- command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL, bufsize=10**8
- )
+
+ logFilename = os.path.join(
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=logf, bufsize=10**8
+ )
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 71cbcac..1517be2 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -4,6 +4,7 @@ from PyQt5.QtGui import QColor
import os
import math
import subprocess
+import logging
from component import Component
from toolkit.frame import BlankFrame, scale
@@ -13,6 +14,9 @@ from toolkit.ffmpeg import (
)
+log = logging.getLogger('AVP.Components.Waveform')
+
+
class Component(Component):
name = 'Waveform'
version = '1.0.0'
@@ -106,10 +110,16 @@ class Component(Component):
'-codec:v', 'rawvideo', '-',
'-frames:v', '1',
])
- pipe = openPipe(
- command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=subprocess.DEVNULL, bufsize=10**8
- )
+ logFilename = os.path.join(
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=logf, bufsize=10**8
+ )
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
diff --git a/src/core.py b/src/core.py
index 61905eb..4023542 100644
--- a/src/core.py
+++ b/src/core.py
@@ -7,11 +7,17 @@ import sys
import os
import json
from importlib import import_module
+import logging
import toolkit
import video_thread
+log = logging.getLogger('AVP.Core')
+STDOUT_LOGLVL = logging.WARNING
+FILE_LOGLVL = logging.DEBUG
+
+
class Core:
'''
MainWindow and Command module both use an instance of this class
@@ -35,6 +41,7 @@ class Core:
continue
elif ext == '.py':
yield name
+ log.debug('Importing component modules')
self.modules = [
import_module('components.%s' % name)
for name in findComponents()
@@ -67,7 +74,7 @@ class Core:
compPos = len(self.selectedComponents)
if len(self.selectedComponents) > 50:
return None
-
+ log.debug('Inserting Component from module #%s' % moduleIndex)
component = self.modules[moduleIndex].Component(
moduleIndex, compPos, self
)
@@ -104,7 +111,7 @@ class Core:
self.componentListChanged()
def updateComponent(self, i):
- # print('updating %s' % self.selectedComponents[i])
+ log.debug('Updating %s #%s' % (self.selectedComponents[i], str(i)))
self.selectedComponents[i].update()
def moduleIndexFor(self, compName):
@@ -125,12 +132,17 @@ class Core:
if not saveValueStore:
return False
try:
- self.selectedComponents[compIndex].loadPreset(
+ comp = self.selectedComponents[compIndex]
+ comp.loadPreset(
saveValueStore,
presetName
)
except KeyError as e:
- print('preset missing value: %s' % e)
+ log.warning(
+ '%s #%s\'s preset is missing value: %s' % (
+ comp.name, str(compIndex), str(e)
+ )
+ )
self.savedPresets[presetName] = dict(saveValueStore)
return True
@@ -206,7 +218,7 @@ class Core:
preset['preset']
)
except KeyError as e:
- print('%s missing value: %s' % (
+ log.warning('%s missing value: %s' % (
self.selectedComponents[i], e)
)
@@ -224,7 +236,7 @@ class Core:
typ, value, tb = data
if typ.__name__ == 'KeyError':
# probably just an old version, still loadable
- print('file missing value: %s' % value)
+ log.warning('Project file missing value: %s' % value)
return
if hasattr(loader, 'createNewProject'):
loader.createNewProject(prompt=False)
@@ -244,6 +256,7 @@ class Core:
Returns dictionary with section names as the keys, each one
contains a list of tuples: (compName, version, compPresetDict)
'''
+ log.debug('Parsing av file: %s' % filepath)
validSections = (
'Components',
'Settings',
@@ -362,6 +375,7 @@ class Core:
def createProjectFile(self, filepath, window=None):
'''Create a project file (.avp) using the current program state'''
+ log.info('Creating %s' % filepath)
settingsKeys = [
'componentDir',
'inputDir',
@@ -374,9 +388,8 @@ class Core:
filepath += '.avp'
if os.path.exists(filepath):
os.remove(filepath)
- with open(filepath, 'w') as f:
- print('creating %s' % filepath)
+ with open(filepath, 'w') as f:
f.write('[Components]\n')
for comp in self.selectedComponents:
saveValueStore = comp.savePreset()
@@ -443,6 +456,7 @@ class Core:
'settings': QtCore.QSettings(
os.path.join(dataDir, 'settings.ini'),
QtCore.QSettings.IniFormat),
+ 'logDir': os.path.join(dataDir, 'log'),
'presetDir': os.path.join(dataDir, 'presets'),
'componentsPath': os.path.join(wd, 'components'),
'encoderOptions': encoderOptions,
@@ -489,6 +503,13 @@ class Core:
setattr(cls, classvar, val)
cls.loadDefaultSettings()
+ if not os.path.exists(cls.dataDir):
+ os.makedirs(cls.dataDir)
+ for neededDirectory in (
+ cls.presetDir, cls.logDir, cls.settings.value("projectDir")):
+ if not os.path.exists(neededDirectory):
+ os.mkdir(neededDirectory)
+ cls.makeLogger()
@classmethod
def loadDefaultSettings(cls):
@@ -522,6 +543,42 @@ class Core:
if val in ('true', 'false'):
cls.settings.setValue(key, True if val == 'true' else False)
+ @staticmethod
+ def makeLogger():
+ logFilename = os.path.join(Core.logDir, 'avp_debug.log')
+ libLogFilename = os.path.join(Core.logDir, 'global_debug.log')
+ # delete old logs
+ for log in (logFilename, libLogFilename):
+ if os.path.exists(log):
+ os.remove(log)
+
+ # create file handlers to capture every log message somewhere
+ logFile = logging.FileHandler(logFilename)
+ logFile.setLevel(FILE_LOGLVL)
+ libLogFile = logging.FileHandler(libLogFilename)
+ libLogFile.setLevel(FILE_LOGLVL)
+
+ # send some critical log messages to stdout as well
+ logStream = logging.StreamHandler()
+ logStream.setLevel(STDOUT_LOGLVL)
+
+ # create formatters and put everything together
+ fileFormatter = logging.Formatter(
+ '[%(asctime)s] <%(name)s> %(levelname)s: %(message)s'
+ )
+ streamFormatter = logging.Formatter(
+ '<%(name)s> %(message)s'
+ )
+ logFile.setFormatter(fileFormatter)
+ libLogFile.setFormatter(fileFormatter)
+ logStream.setFormatter(streamFormatter)
+ log = logging.getLogger('AVP')
+ log.setLevel(FILE_LOGLVL)
+ log.addHandler(logFile)
+ log.addHandler(logStream)
+ libLog = logging.getLogger()
+ libLog.setLevel(FILE_LOGLVL)
+ libLog.addHandler(libLogFile)
# always store settings in class variables even if a Core object is not created
Core.storeSettings()
diff --git a/src/main.py b/src/main.py
index 421a09f..3a6fbe7 100644
--- a/src/main.py
+++ b/src/main.py
@@ -1,10 +1,14 @@
from PyQt5 import uic, QtWidgets
import sys
import os
+import logging
from __init__ import wd
+log = logging.getLogger('AVP.Entrypoint')
+
+
def main():
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("audio-visualizer")
@@ -28,6 +32,7 @@ def main():
from command import Command
main = Command()
+ log.debug("Finished creating command object")
elif mode == 'GUI':
from mainwindow import MainWindow
@@ -48,6 +53,7 @@ def main():
# window.verticalLayout_2.setContentsMargins(0, topMargin, 0, 0)
main = MainWindow(window, proj)
+ log.debug("Finished creating main window")
window.raise_()
signal.signal(signal.SIGINT, main.cleanUp)
diff --git a/src/mainwindow.py b/src/mainwindow.py
index 789a6e7..114015c 100644
--- a/src/mainwindow.py
+++ b/src/mainwindow.py
@@ -13,6 +13,7 @@ import os
import signal
import filecmp
import time
+import logging
from core import Core
import preview_thread
@@ -20,11 +21,15 @@ from presetmanager import PresetManager
from toolkit import disableWhenEncoding, disableWhenOpeningProject, checkOutput
+log = logging.getLogger('AVP.MainWindow')
+
+
class PreviewWindow(QtWidgets.QLabel):
'''
Paints the preview QLabel and maintains the aspect ratio when the
window is resized.
'''
+ log = logging.getLogger('AVP.MainWindow.Preview')
def __init__(self, parent, img):
super(PreviewWindow, self).__init__()
@@ -58,11 +63,15 @@ class PreviewWindow(QtWidgets.QLabel):
if i >= 0:
component = self.parent.core.selectedComponents[i]
if not hasattr(component, 'previewClickEvent'):
+ self.log.info('Ignored click event')
return
pos = (event.x(), event.y())
size = (self.width(), self.height())
+ butt = event.button()
+ self.log.info('Click event for #%s: %s button %s' % (
+ i, pos, butt))
component.previewClickEvent(
- pos, size, event.button()
+ pos, size, butt
)
self.parent.core.updateComponent(i)
@@ -91,9 +100,10 @@ class MainWindow(QtWidgets.QMainWindow):
def __init__(self, window, project):
QtWidgets.QMainWindow.__init__(self)
- # print('main thread id: {}'.format(QtCore.QThread.currentThreadId()))
self.window = window
self.core = Core()
+ log.debug(
+ 'Main thread id: {}'.format(QtCore.QThread.currentThreadId()))
# widgets of component settings
self.pages = []
@@ -103,27 +113,23 @@ class MainWindow(QtWidgets.QMainWindow):
self.autosaveCooldown = 0.2
self.encoding = False
- # Create data directory, load/create settings
+ # Find settings created by Core object
self.dataDir = Core.dataDir
self.presetDir = Core.presetDir
self.autosavePath = os.path.join(self.dataDir, 'autosave.avp')
self.settings = Core.settings
+
self.presetManager = PresetManager(
uic.loadUi(
os.path.join(Core.wd, 'presetmanager.ui')), self)
- if not os.path.exists(self.dataDir):
- os.makedirs(self.dataDir)
- for neededDirectory in (
- self.presetDir, self.settings.value("projectDir")):
- if not os.path.exists(neededDirectory):
- os.mkdir(neededDirectory)
-
# Create the preview window and its thread, queues, and timers
+ log.debug('Creating preview window')
self.previewWindow = PreviewWindow(self, os.path.join(
Core.wd, "background.png"))
window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
+ log.debug('Starting preview thread')
self.previewQueue = Queue()
self.previewThread = QtCore.QThread(self)
self.previewWorker = preview_thread.Worker(self, self.previewQueue)
@@ -132,6 +138,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.previewWorker.imageCreated.connect(self.showPreviewImage)
self.previewThread.start()
+ log.debug('Starting preview timer')
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.processTask.emit)
self.timer.start(500)
@@ -141,6 +148,8 @@ class MainWindow(QtWidgets.QMainWindow):
componentList = self.window.listWidget_componentList
if sys.platform == 'darwin':
+ log.debug(
+ 'Darwin detected: showing progress label below progress bar')
window.progressBar_createVideo.setTextVisible(False)
else:
window.progressLabel.setHidden(True)
@@ -276,6 +285,7 @@ class MainWindow(QtWidgets.QMainWindow):
)
self.updateWindowTitle()
+ log.debug('Showing main window')
window.show()
if project and project != self.autosavePath:
@@ -398,6 +408,7 @@ class MainWindow(QtWidgets.QMainWindow):
@QtCore.pyqtSlot()
def cleanUp(self, *args):
+ log.info('Ending the preview thread')
self.timer.stop()
self.previewThread.quit()
self.previewThread.wait()
@@ -414,11 +425,12 @@ class MainWindow(QtWidgets.QMainWindow):
appName += '*'
except AttributeError:
pass
+ log.debug('Setting window title to %s' % appName)
self.window.setWindowTitle(appName)
@QtCore.pyqtSlot(int, dict)
def updateComponentTitle(self, pos, presetStore=False):
- if type(presetStore) == dict:
+ if type(presetStore) is dict:
name = presetStore['preset']
if name is None or name not in self.core.savedPresets:
modified = False
@@ -428,11 +440,20 @@ class MainWindow(QtWidgets.QMainWindow):
modified = bool(presetStore)
if pos < 0:
pos = len(self.core.selectedComponents)-1
- title = str(self.core.selectedComponents[pos])
+ name = str(self.core.selectedComponents[pos])
+ title = str(name)
if self.core.selectedComponents[pos].currentPreset:
title += ' - %s' % self.core.selectedComponents[pos].currentPreset
if modified:
title += '*'
+ if type(presetStore) is bool:
+ log.debug('Forcing %s #%s\'s modified status to %s: %s' % (
+ name, pos, modified, title
+ ))
+ else:
+ log.debug('Setting %s #%s\'s title: %s' % (
+ name, pos, title
+ ))
self.window.listWidget_componentList.item(pos).setText(title)
def updateCodecs(self):
@@ -493,6 +514,8 @@ class MainWindow(QtWidgets.QMainWindow):
elif force or timeDiff >= self.autosaveCooldown * 5:
self.autosaveCooldown = 0.2
self.autosaveTimes.insert(0, self.lastAutosave)
+ else:
+ log.debug('Autosave rejected by cooldown')
def autosaveExists(self, identical=True):
'''Determines if creating the autosave should be blocked.'''
@@ -500,9 +523,14 @@ class MainWindow(QtWidgets.QMainWindow):
if self.currentProject and os.path.exists(self.autosavePath) \
and filecmp.cmp(
self.autosavePath, self.currentProject) == identical:
+ log.debug(
+ 'Autosave found %s to be identical' % \
+ 'not' if not identical else ''
+ )
return True
except FileNotFoundError:
- print('project file couldn\'t be located:', self.currentProject)
+ log.error(
+ 'Project file couldn\'t be located:', self.currentProject)
return identical
return False
@@ -543,7 +571,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.window.lineEdit_outputFile.setText(fileName)
def stopVideo(self):
- print('stop')
+ log.info('Export cancelled')
self.videoWorker.cancel()
self.canceled = True
@@ -773,6 +801,7 @@ class MainWindow(QtWidgets.QMainWindow):
mousePos = -1
else:
mousePos = mousePos.index(True)
+ log.debug('Click component list row %s' % mousePos)
return mousePos
@disableWhenEncoding
diff --git a/src/preview_thread.py b/src/preview_thread.py
index bb22f0c..9615884 100644
--- a/src/preview_thread.py
+++ b/src/preview_thread.py
@@ -8,11 +8,15 @@ from PIL import Image
from PIL.ImageQt import ImageQt
from queue import Queue, Empty
import os
+import logging
from toolkit.frame import Checkerboard
from toolkit import disableWhenOpeningProject
+log = logging.getLogger("AVP.PreviewThread")
+
+
class Worker(QtCore.QObject):
imageCreated = pyqtSignal(QtGui.QImage)
@@ -55,7 +59,7 @@ class Worker(QtCore.QObject):
self.background = Checkerboard(width, height)
frame = self.background.copy()
-
+ log.debug('Creating new preview frame')
components = nextPreviewInformation["components"]
for component in reversed(components):
try:
@@ -73,10 +77,11 @@ class Worker(QtCore.QObject):
newFrame.width, newFrame.height,
width, height
)
+ log.critical(errMsg)
self.error.emit(errMsg)
break
except RuntimeError as e:
- print(e)
+ log.error(str(e))
else:
self.frame = ImageQt(frame)
self.imageCreated.emit(QtGui.QImage(self.frame))
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index 3421049..6ab445c 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -8,12 +8,16 @@ import subprocess
import threading
import signal
from queue import PriorityQueue
+import logging
import core
from toolkit.common import checkOutput, pipeWrapper
from component import ComponentError
+log = logging.getLogger('AVP.Toolkit.Ffmpeg')
+
+
class FfmpegVideo:
'''Opens a pipe to ffmpeg and stores a buffer of raw video frames.'''
@@ -88,13 +92,14 @@ class FfmpegVideo:
def fillBuffer(self):
logFilename = os.path.join(
- core.Core.dataDir, 'extra_%s.log' % str(self.component.compPos))
- with open(logFilename, 'w') as log:
- log.write(" ".join(self.command) + '\n\n')
- with open(logFilename, 'a') as log:
+ core.Core.logDir, 'render_%s.log' % str(self.component.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(self.command) + '\n\n')
+ with open(logFilename, 'a') as logf:
self.pipe = openPipe(
self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=log, bufsize=10**8
+ stderr=logf, bufsize=10**8
)
while True:
if self.parent.canceled:
@@ -375,7 +380,7 @@ def getAudioDuration(filename):
try:
info = fileInfo.decode("utf-8").split('\n')
except UnicodeDecodeError as e:
- print('Unicode error:', str(e))
+ log.error('Unicode error:', str(e))
return False
for line in info:
@@ -398,7 +403,7 @@ def readAudioFile(filename, videoWorker):
'''
duration = getAudioDuration(filename)
if not duration:
- print('Audio file doesn\'t exist or unreadable.')
+ log.error('Audio file doesn\'t exist or unreadable.')
return
command = [
diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py
index 7e83d58..02f9229 100644
--- a/src/toolkit/frame.py
+++ b/src/toolkit/frame.py
@@ -7,10 +7,14 @@ from PIL.ImageQt import ImageQt
import sys
import os
import math
+import logging
import core
+log = logging.getLogger('AVP.Toolkit.Frame')
+
+
class FramePainter(QtGui.QPainter):
'''
A QPainter for a blank frame, which can be converted into a
@@ -79,6 +83,7 @@ def FloodFrame(width, height, RgbaTuple):
@defaultSize
def BlankFrame(width, height):
'''The base frame used by each component to start drawing.'''
+ log.debug('Creating new %s*%s blank frame' % (width, height))
return FloodFrame(width, height, (0, 0, 0, 0))
@@ -88,6 +93,7 @@ def Checkerboard(width, height):
A checkerboard to represent transparency to the user.
TODO: Would be cool to generate this image with numpy instead.
'''
+ log.debug('Creating new %s*%s checkerboard' % (width, height))
image = FloodFrame(1920, 1080, (0, 0, 0, 0))
image.paste(Image.open(
os.path.join(core.Core.wd, "background.png")),
diff --git a/src/video_thread.py b/src/video_thread.py
index 5963def..e7e4136 100644
--- a/src/video_thread.py
+++ b/src/video_thread.py
@@ -17,6 +17,7 @@ from queue import Queue, PriorityQueue
from threading import Thread, Event
import time
import signal
+import logging
from component import ComponentError
from toolkit.frame import Checkerboard
@@ -26,6 +27,9 @@ from toolkit.ffmpeg import (
)
+log = logging.getLogger("AVP.VideoThread")
+
+
class Worker(QtCore.QObject):
imageCreated = pyqtSignal(['QImage'])
@@ -92,7 +96,7 @@ class Worker(QtCore.QObject):
by a renderNode later. All indices are multiples of self.sampleSize
sampleSize * frameNo = audioI, AKA audio data starting at frameNo
'''
- print('Dispatching Frames for Compositing...')
+ log.debug('Dispatching Frames for Compositing...')
for audioI in range(0, len(self.completeAudioArray), self.sampleSize):
self.compositeQueue.put(audioI)
@@ -156,10 +160,12 @@ class Worker(QtCore.QObject):
self.progressBarUpdate.emit(0)
self.progressBarSetText.emit("Starting components...")
canceledByComponent = False
- print('Loaded Components:', ", ".join([
+ initText = ", ".join([
"%s) %s" % (num, str(component))
for num, component in enumerate(reversed(self.components))
- ]))
+ ])
+ print('Loaded Components:', initText)
+ log.info('Calling preFrameRender for %s' % initText)
self.staticComponents = {}
for compNo, comp in enumerate(reversed(self.components)):
try:
@@ -191,6 +197,7 @@ class Worker(QtCore.QObject):
compError[0]
)
)
+ log.critical(errMsg)
comp._error.emit(errMsg, compError[1])
break
if 'static' in compProps:
@@ -199,7 +206,7 @@ class Worker(QtCore.QObject):
if self.canceled:
if canceledByComponent:
- print('Export cancelled by component #%s (%s): %s' % (
+ log.critical('Export cancelled by component #%s (%s): %s' % (
compNo,
comp.name,
'No message.' if comp.error() is None else (
@@ -224,8 +231,11 @@ class Worker(QtCore.QObject):
ffmpegCommand = createFfmpegCommand(
self.inputFile, self.outputFile, self.components, duration
)
- print('###### FFMPEG COMMAND ######\n%s' % " ".join(ffmpegCommand))
+ cmd = " ".join(ffmpegCommand)
+ print('###### FFMPEG COMMAND ######\n%s' % cmd)
print('############################')
+ log.info('Opening pipe to ffmpeg')
+ log.info(cmd)
self.out_pipe = openPipe(
ffmpegCommand, stdin=sp.PIPE, stdout=sys.stdout, stderr=sys.stdout
)
@@ -298,9 +308,9 @@ class Worker(QtCore.QObject):
try:
self.out_pipe.stdin.close()
except BrokenPipeError:
- print('Broken pipe to ffmpeg!')
+ log.error('Broken pipe to ffmpeg!')
if self.out_pipe.stderr is not None:
- print(self.out_pipe.stderr.read())
+ log.error(self.out_pipe.stderr.read())
self.out_pipe.stderr.close()
self.error = True
self.out_pipe.wait()
--
cgit v1.2.3
From ea1a422cc52bc972574070fbe784a35876ff8baa Mon Sep 17 00:00:00 2001
From: tassaron
Date: Mon, 14 Aug 2017 14:28:30 -0400
Subject: better aevalsrc inputs for spectrum previews
---
src/components/spectrum.py | 32 ++++++++++++++++++++++++++------
src/components/waveform.py | 25 +++++++++++++++----------
src/toolkit/ffmpeg.py | 19 ++++++++++++++-----
test.wav | Bin 0 -> 14348366 bytes
4 files changed, 55 insertions(+), 21 deletions(-)
create mode 100644 test.wav
(limited to 'src/components/waveform.py')
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 246b839..89130a2 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -19,7 +19,7 @@ log = logging.getLogger('AVP.Components.Spectrum')
class Component(Component):
name = 'Spectrum'
- version = '1.0.0'
+ version = '1.0.1'
def widget(self, *args):
self.previewFrame = None
@@ -65,8 +65,17 @@ class Component(Component):
self.changedOptions = True
def update(self):
- self.page.stackedWidget.setCurrentIndex(
- self.page.comboBox_filterType.currentIndex())
+ filterType = self.page.comboBox_filterType.currentIndex()
+ self.page.stackedWidget.setCurrentIndex(filterType)
+ if filterType == 3:
+ self.page.spinBox_hue.setEnabled(False)
+ else:
+ self.page.spinBox_hue.setEnabled(True)
+ if filterType == 2 or filterType == 4:
+ self.page.checkBox_mono.setEnabled(False)
+ else:
+ self.page.checkBox_mono.setEnabled(True)
+
super().update()
def previewRender(self):
@@ -81,6 +90,8 @@ class Component(Component):
frame = self.getPreviewFrame()
self.changedOptions = False
if not frame:
+ log.warning(
+ 'Spectrum #%s failed to create a preview frame' % self.compPos)
self.previewFrame = None
return BlankFrame(self.width, self.height)
else:
@@ -244,13 +255,21 @@ class Component(Component):
)
)
+ if self.filterType < 2:
+ exampleSnd = exampleSound('freq')
+ elif self.filterType == 2 or self.filterType == 4:
+ exampleSnd = exampleSound('stereo')
+ elif self.filterType == 3:
+ exampleSnd = exampleSound('white')
+
return [
'-filter_complex',
'%s%s%s%s [v1]; '
'[v1] %s%s%s%s%s [v]' % (
- exampleSound() if preview and genericPreview else '[0:a] ',
+ exampleSnd if preview and genericPreview else '[0:a] ',
'compand=gain=4,' if self.compress else '',
- 'aformat=channel_layouts=mono,' if self.mono else '',
+ 'aformat=channel_layouts=mono,'
+ if self.mono and self.filterType not in (2, 4) else '',
filter_,
'hflip, ' if self.mirror else '',
'trim=start=%s:end=%s, ' % (
@@ -259,7 +278,8 @@ class Component(Component):
) if preview else '',
'scale=%sx%s' % scale(
self.scale, self.width, self.height, str),
- ', hue=h=%s:s=10' % str(self.hue) if self.hue > 0 else '',
+ ', hue=h=%s:s=10' % str(self.hue)
+ if self.hue > 0 and self.filterType != 3 else '',
', convolution=-2 -1 0 -1 1 1 0 1 2:-2 -1 0 -1 1 1 0 1 2:-2 '
'-1 0 -1 1 1 0 1 2:-2 -1 0 -1 1 1 0 1 2'
if self.filterType == 3 else ''
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 1517be2..0743e55 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -140,13 +140,16 @@ class Component(Component):
opacity = "{0:.1f}".format(self.opacity / 100)
genericPreview = self.settings.value("pref_genericPreview")
if self.mode < 3:
- filter_ = 'showwaves=r=%s:s=%sx%s:mode=%s:colors=%s@%s:scale=%s' % (
- self.settings.value("outputFrameRate"),
- self.settings.value("outputWidth"),
- self.settings.value("outputHeight"),
- self.page.comboBox_mode.currentText().lower()
- if self.mode != 3 else 'p2p',
- hexcolor, opacity, amplitude,
+ filter_ = (
+ 'showwaves='
+ 'r=%s:s=%sx%s:mode=%s:colors=%s@%s:scale=%s' % (
+ self.settings.value("outputFrameRate"),
+ self.settings.value("outputWidth"),
+ self.settings.value("outputHeight"),
+ self.page.comboBox_mode.currentText().lower()
+ if self.mode != 3 else 'p2p',
+ hexcolor, opacity, amplitude,
+ )
)
elif self.mode > 2:
filter_ = (
@@ -160,18 +163,20 @@ class Component(Component):
)
)
+ baselineHeight = int(self.height * (4 / 1080))
return [
'-filter_complex',
'%s%s%s'
'%s%s%s [v1]; '
'[v1] scale=%s:%s%s [v]' % (
- exampleSound() if preview and genericPreview else '[0:a] ',
+ exampleSound('wave', extra='')
+ if preview and genericPreview else '[0:a] ',
'compand=gain=4,' if self.compress else '',
'aformat=channel_layouts=mono,'
if self.mono and self.mode < 3 else '',
filter_,
- ', drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=4:color=%s@%s' % (
- hexcolor, opacity
+ ', drawbox=x=(iw-w)/2:y=(ih-h)/2:w=iw:h=%s:color=%s@%s' % (
+ baselineHeight, hexcolor, opacity,
) if self.mode < 2 else '',
', hflip' if self.mirror else'',
w, h,
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index afcb37c..8fe9148 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -457,8 +457,17 @@ def readAudioFile(filename, videoWorker):
return (completeAudioArray, duration)
-def exampleSound():
- return (
- 'aevalsrc=tan(random(1)*PI*t)*sin(random(0)*2*PI*t),'
- 'apulsator=offset_l=0.5:offset_r=0.5,'
- )
+def exampleSound(
+ style='white', extra='apulsator=offset_l=0.35:offset_r=0.67'):
+ '''Help generate an example sound for use in creating a preview'''
+
+ if style == 'white':
+ src = '-2+random(0)'
+ elif style == 'freq':
+ src = 'sin(1000*t*PI*t)'
+ elif style == 'wave':
+ src = 'sin(random(0)*2*PI*t)*tan(random(0)*2*PI*t)'
+ elif style == 'stereo':
+ src = '0.1*sin(2*PI*(360-2.5/2)*t) : 0.1*sin(2*PI*(360+2.5/2)*t)'
+
+ return "aevalsrc='%s', %s%s" % (src, extra, ', ' if extra else '')
diff --git a/test.wav b/test.wav
new file mode 100644
index 0000000..98afe5f
Binary files /dev/null and b/test.wav differ
--
cgit v1.2.3
From c07f2426ceeada205fdacbfba66329179a74a1dc Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sat, 19 Aug 2017 18:32:12 -0400
Subject: fixed issues with undoing relative widgets
---
src/component.py | 198 +++++++++++++++++++++++++++++++++------------
src/components/color.py | 2 -
src/components/image.py | 2 -
src/components/life.py | 1 -
src/components/sound.py | 1 -
src/components/spectrum.py | 4 +-
src/components/text.py | 1 -
src/components/video.py | 2 -
src/components/waveform.py | 2 +-
src/core.py | 11 +--
src/gui/actions.py | 11 ++-
src/gui/mainwindow.py | 4 +-
src/gui/presetmanager.py | 4 +
src/gui/preview_thread.py | 2 +-
src/gui/preview_win.py | 2 +-
src/main.py | 2 +-
src/toolkit/common.py | 47 +++++++++--
17 files changed, 215 insertions(+), 81 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index 1fe9237..ba86422 100644
--- a/src/component.py
+++ b/src/component.py
@@ -9,6 +9,7 @@ import sys
import math
import time
import logging
+from copy import copy
from toolkit.frame import BlankFrame
from toolkit import (
@@ -113,14 +114,20 @@ class ComponentMetaclass(type(QtCore.QObject)):
def presetWrapper(self, *args):
with openingPreset(self):
- return func(self, *args)
+ try:
+ return func(self, *args)
+ except Exception:
+ try:
+ raise ComponentError(self, 'preset loader')
+ except ComponentError:
+ return
return presetWrapper
def updateWrapper(func):
'''
- For undoable updates triggered by the user,
- call _userUpdate() after the subclass's update() method.
- For non-user updates, call _autoUpdate()
+ Calls _preUpdate before every subclass update().
+ Afterwards, for non-user updates, calls _autoUpdate().
+ For undoable updates triggered by the user, calls _userUpdate()
'''
class wrap:
def __init__(self, comp, auto):
@@ -128,24 +135,57 @@ class ComponentMetaclass(type(QtCore.QObject)):
self.auto = auto
def __enter__(self):
- pass
+ self.comp._preUpdate()
def __exit__(self, *args):
if self.auto or self.comp.openingPreset \
or not hasattr(self.comp.parent, 'undoStack'):
+ log.verbose('Automatic update')
self.comp._autoUpdate()
else:
+ log.verbose('User update')
self.comp._userUpdate()
def updateWrapper(self, **kwargs):
- auto = False
- if 'auto' in kwargs:
- auto = kwargs['auto']
-
+ auto = kwargs['auto'] if 'auto' in kwargs else False
with wrap(self, auto):
- return func(self)
+ try:
+ return func(self)
+ except Exception:
+ try:
+ raise ComponentError(self, 'update method')
+ except ComponentError:
+ return
return updateWrapper
+ def widgetWrapper(func):
+ '''Connects all widgets to update method after the subclass's method'''
+ class wrap:
+ def __init__(self, comp):
+ self.comp = comp
+
+ def __enter__(self):
+ pass
+
+ def __exit__(self, *args):
+ for widgetList in self.comp._allWidgets.values():
+ for widget in widgetList:
+ log.verbose('Connecting %s' % str(
+ widget.__class__.__name__))
+ connectWidget(widget, self.comp.update)
+
+ def widgetWrapper(self, *args, **kwargs):
+ auto = kwargs['auto'] if 'auto' in kwargs else False
+ with wrap(self):
+ try:
+ return func(self, *args, **kwargs)
+ except Exception:
+ try:
+ raise ComponentError(self, 'widget creation')
+ except ComponentError:
+ return
+ return widgetWrapper
+
def __new__(cls, name, parents, attrs):
if 'ui' not in attrs:
# Use module name as ui filename by default
@@ -153,13 +193,12 @@ class ComponentMetaclass(type(QtCore.QObject)):
attrs['__module__'].split('.')[-1]
)[0]
- # if parents[0] == QtCore.QObject: else:
decorate = (
'names', # Class methods
'error', 'audio', 'properties', # Properties
'preFrameRender', 'previewRender',
'frameRender', 'command',
- 'loadPreset', 'update'
+ 'loadPreset', 'update', 'widget',
)
# Auto-decorate methods
@@ -184,6 +223,8 @@ class ComponentMetaclass(type(QtCore.QObject)):
attrs[key] = cls.loadPresetWrapper(attrs[key])
elif key == 'update':
attrs[key] = cls.updateWrapper(attrs[key])
+ elif key == 'widget' and parents[0] != QtCore.QObject:
+ attrs[key] = cls.widgetWrapper(attrs[key])
# Turn version string into a number
try:
@@ -224,23 +265,28 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self.moduleIndex = moduleIndex
self.compPos = compPos
self.core = core
- self.currentPreset = None
- self.openingPreset = False
+ # STATUS VARIABLES
+ self.currentPreset = None
+ self._allWidgets = {}
self._trackedWidgets = {}
self._presetNames = {}
self._commandArgs = {}
self._colorWidgets = {}
self._colorFuncs = {}
self._relativeWidgets = {}
- # pixel values stored as floats
+ # Pixel values stored as floats
self._relativeValues = {}
- # maximum values of spinBoxes at 1080p (Core.resolutions[0])
+ # Maximum values of spinBoxes at 1080p (Core.resolutions[0])
self._relativeMaximums = {}
+ # LOCKING VARIABLES
+ self.openingPreset = False
self._lockedProperties = None
self._lockedError = None
self._lockedSize = None
+ # If set to a dict, values are used as basis to update relative widgets
+ self.oldAttrs = None
# Stop lengthy processes in response to this variable
self.canceled = False
@@ -338,21 +384,21 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
'''
self.parent = parent
self.settings = parent.settings
+ log.verbose('Creating UI for %s #%s\'s widget' % (
+ self.name, self.compPos
+ ))
self.page = self.loadUi(self.__class__.ui)
- # Connect widget signals
- widgets = {
+ # Find all normal widgets which will be connected after subclass method
+ self._allWidgets = {
'lineEdit': self.page.findChildren(QtWidgets.QLineEdit),
'checkBox': self.page.findChildren(QtWidgets.QCheckBox),
'spinBox': self.page.findChildren(QtWidgets.QSpinBox),
'comboBox': self.page.findChildren(QtWidgets.QComboBox),
}
- widgets['spinBox'].extend(
+ self._allWidgets['spinBox'].extend(
self.page.findChildren(QtWidgets.QDoubleSpinBox)
)
- for widgetList in widgets.values():
- for widget in widgetList:
- connectWidget(widget, self.update)
def update(self):
'''
@@ -427,10 +473,15 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
# "Private" Methods
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
+ def _preUpdate(self):
+ '''Happens before subclass update()'''
+ for attr in self._relativeWidgets:
+ self.updateRelativeWidget(attr)
+
def _userUpdate(self):
- '''An undoable component update triggered by the user'''
+ '''Happens after subclass update() for an undoable update by user.'''
oldWidgetVals = {
- attr: getattr(self, attr)
+ attr: copy(getattr(self, attr))
for attr in self._trackedWidgets
}
newWidgetVals = {
@@ -443,13 +494,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
for attr, val in newWidgetVals.items()
if val != oldWidgetVals[attr]
}
-
if modifiedWidgets:
action = ComponentUpdate(self, oldWidgetVals, modifiedWidgets)
self.parent.undoStack.push(action)
def _autoUpdate(self):
- '''An internal component update that is not undoable'''
+ '''Happens after subclass update() for an internal component update.'''
newWidgetVals = {
attr: getWidgetValue(widget)
for attr, widget in self._trackedWidgets.items()
@@ -459,12 +509,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
def setAttrs(self, attrDict):
'''
- Sets attrs (linked to trackedWidgets) in this preset to
+ Sets attrs (linked to trackedWidgets) in this component to
the values in the attrDict. Mutates certain widget values if needed
'''
for attr, val in attrDict.items():
if attr in self._colorWidgets:
- # Color Widgets: text stored as tuple & update the button color
+ # Color Widgets must have a tuple & have a button to update
if type(val) is tuple:
rgbTuple = val
else:
@@ -475,15 +525,25 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._colorWidgets[attr].setStyleSheet(btnStyle)
setattr(self, attr, rgbTuple)
- elif attr in self._relativeWidgets:
- # Relative widgets: number scales to fit export resolution
- self.updateRelativeWidget(attr)
- setattr(self, attr, val)
-
else:
# Normal tracked widget
setattr(self, attr, val)
+ def setWidgetValues(self, attrDict):
+ '''
+ Sets widgets defined by keys in trackedWidgets in this preset to
+ the values in the attrDict.
+ '''
+ affectedWidgets = [
+ self._trackedWidgets[attr] for attr in attrDict
+ ]
+ with blockSignals(affectedWidgets):
+ for attr, val in attrDict.items():
+ widget = self._trackedWidgets[attr]
+ if attr in self._colorWidgets:
+ val = '%s,%s,%s' % val
+ setWidgetValue(widget, val)
+
def _sendUpdateSignal(self):
if not self.core.openingProject:
self.parent.drawPreview()
@@ -499,6 +559,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
Optional args:
'presetNames': preset variable names to replace attr names
'commandArgs': arg keywords that differ from attr names
+ 'colorWidgets': identify attr as RGB tuple & update button CSS
+ 'relativeWidgets': change value proportionally to resolution
NOTE: Any kwarg key set to None will selectively disable tracking.
'''
@@ -542,6 +604,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._relativeMaximums[attr] = \
self._trackedWidgets[attr].maximum()
self.updateRelativeWidgetMaximum(attr)
+ self._preUpdate()
+ self._autoUpdate()
def pickColor(self, textWidget, button):
'''Use color picker to get color input from the user.'''
@@ -627,12 +691,28 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
def setRelativeWidget(self, attr, floatVal):
'''Set a relative widget using a float'''
pixelVal = self.pixelValForAttr(attr, floatVal)
- self._trackedWidgets[attr].setValue(pixelVal)
+ with blockSignals(self._allWidgets):
+ self._trackedWidgets[attr].setValue(pixelVal)
+ self.update(auto=True)
+
+ def getOldAttr(self, attr):
+ '''
+ Returns previous state of this attr. Used to determine whether
+ a relative widget must be updated. Required because undoing/redoing
+ can make determining the 'previous' value tricky.
+ '''
+ if self.oldAttrs is not None:
+ log.verbose('Using nonstandard oldAttr for %s' % attr)
+ return self.oldAttrs[attr]
+ else:
+ return getattr(self, attr)
def updateRelativeWidget(self, attr):
+ '''Called by _preUpdate() for each relativeWidget before each update'''
try:
- oldUserValue = getattr(self, attr)
- except AttributeError:
+ oldUserValue = self.getOldAttr(attr)
+ except (AttributeError, KeyError):
+ log.info('Using visible values as basis for relative widgets')
oldUserValue = self._trackedWidgets[attr].value()
newUserValue = self._trackedWidgets[attr].value()
newRelativeVal = self.floatValForAttr(attr, newUserValue)
@@ -645,11 +725,10 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
# means the pixel value needs to be updated
log.debug('Updating %s #%s\'s relative widget: %s' % (
self.name, self.compPos, attr))
- self._trackedWidgets[attr].blockSignals(True)
- self.updateRelativeWidgetMaximum(attr)
- pixelVal = self.pixelValForAttr(attr, oldRelativeVal)
- self._trackedWidgets[attr].setValue(pixelVal)
- self._trackedWidgets[attr].blockSignals(False)
+ with blockSignals(self._trackedWidgets[attr]):
+ self.updateRelativeWidgetMaximum(attr)
+ pixelVal = self.pixelValForAttr(attr, oldRelativeVal)
+ self._trackedWidgets[attr].setValue(pixelVal)
if attr not in self._relativeValues \
or oldUserValue != newUserValue:
@@ -725,14 +804,22 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
parent.name, parent.compPos
)
)
+ self.undone = False
self.parent = parent
self.oldWidgetVals = {
- attr: val
+ attr: copy(val)
for attr, val in oldWidgetVals.items()
if attr in modifiedVals
}
self.modifiedVals = modifiedVals
+ # Because relative widgets change themselves every update based on
+ # their previous value, we must store ALL their values in case of undo
+ self.redoRelativeWidgetVals = {
+ attr: copy(getattr(self.parent, attr))
+ for attr in self.parent._relativeWidgets
+ }
+
# Determine if this update is mergeable
self.id_ = -1
if len(self.modifiedVals) == 1:
@@ -755,15 +842,26 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
return True
def redo(self):
+ if self.undone:
+ log.debug('Redoing component update')
+ self.parent.setWidgetValues(self.modifiedVals)
self.parent.setAttrs(self.modifiedVals)
- self.parent._sendUpdateSignal()
+ if self.undone:
+ self.parent.oldAttrs = self.redoRelativeWidgetVals
+ self.parent.update(auto=True)
+ self.parent.oldAttrs = None
+ else:
+ self.undoRelativeWidgetVals = {
+ attr: copy(getattr(self.parent, attr))
+ for attr in self.parent._relativeWidgets
+ }
+ self.parent._sendUpdateSignal()
def undo(self):
+ log.debug('Undoing component update')
+ self.undone = True
+ self.parent.oldAttrs = self.undoRelativeWidgetVals
+ self.parent.setWidgetValues(self.oldWidgetVals)
self.parent.setAttrs(self.oldWidgetVals)
- with blockSignals(self.parent):
- for attr, val in self.oldWidgetVals.items():
- widget = self.parent._trackedWidgets[attr]
- if attr in self.parent._colorWidgets:
- val = '%s,%s,%s' % val
- setWidgetValue(widget, val)
- self.parent._sendUpdateSignal()
+ self.parent.update(auto=True)
+ self.parent.oldAttrs = None
diff --git a/src/components/color.py b/src/components/color.py
index d09cee8..a55aa10 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -82,8 +82,6 @@ class Component(Component):
self.page.pushButton_color2.setEnabled(False)
self.page.fillWidget.setCurrentIndex(fillType)
- super().update()
-
def previewRender(self):
return self.drawFrame(self.width, self.height)
diff --git a/src/components/image.py b/src/components/image.py
index 63bee1a..c57b69c 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -84,7 +84,6 @@ class Component(Component):
if filename:
self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename)
- self.update()
def command(self, arg):
if '=' in arg:
@@ -123,4 +122,3 @@ class Component(Component):
else:
scaleBox.setVisible(True)
stretchScaleBox.setVisible(False)
- super().update()
diff --git a/src/components/life.py b/src/components/life.py
index 2383d30..76d2c5f 100644
--- a/src/components/life.py
+++ b/src/components/life.py
@@ -53,7 +53,6 @@ class Component(Component):
if filename:
self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_image.setText(filename)
- self.update()
def shiftGrid(self, d):
def newGrid(Xchange, Ychange):
diff --git a/src/components/sound.py b/src/components/sound.py
index 26ecf93..b86f40c 100644
--- a/src/components/sound.py
+++ b/src/components/sound.py
@@ -53,7 +53,6 @@ class Component(Component):
if filename:
self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_sound.setText(filename)
- self.update()
def commandHelp(self):
print('Path to audio file:\n path=/filepath/to/sound.ogg')
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 89130a2..2b98dc2 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -76,8 +76,6 @@ class Component(Component):
else:
self.page.checkBox_mono.setEnabled(True)
- super().update()
-
def previewRender(self):
changedSize = self.updateChunksize()
if not changedSize \
@@ -138,7 +136,7 @@ class Component(Component):
'-r', self.settings.value("outputFrameRate"),
'-ss', "{0:.3f}".format(startPt),
'-i',
- os.path.join(self.core.wd, 'background.png')
+ self.core.junkStream
if genericPreview else inputFile,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
diff --git a/src/components/text.py b/src/components/text.py
index d3afd5c..92f0599 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -68,7 +68,6 @@ class Component(Component):
self.page.spinBox_shadY.setHidden(True)
self.page.label_shadBlur.setHidden(True)
self.page.spinBox_shadBlur.setHidden(True)
- super().update()
def centerXY(self):
self.setRelativeWidget('xPosition', 0.5)
diff --git a/src/components/video.py b/src/components/video.py
index a189f60..9c0d608 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -52,7 +52,6 @@ class Component(Component):
else:
self.page.label_volume.setEnabled(False)
self.page.spinBox_volume.setEnabled(False)
- super().update()
def previewRender(self):
self.updateChunksize()
@@ -119,7 +118,6 @@ class Component(Component):
if filename:
self.settings.setValue("componentDir", os.path.dirname(filename))
self.page.lineEdit_video.setText(filename)
- self.update()
def getPreviewFrame(self, width, height):
if not self.videoPath or not os.path.exists(self.videoPath):
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 0743e55..5c02bbf 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -98,7 +98,7 @@ class Component(Component):
'-r', self.settings.value("outputFrameRate"),
'-ss', "{0:.3f}".format(startPt),
'-i',
- os.path.join(self.core.wd, 'background.png')
+ self.core.junkStream
if genericPreview else inputFile,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
diff --git a/src/core.py b/src/core.py
index d9499f7..169716c 100644
--- a/src/core.py
+++ b/src/core.py
@@ -13,7 +13,7 @@ import toolkit
log = logging.getLogger('AVP.Core')
-STDOUT_LOGLVL = logging.WARNING
+STDOUT_LOGLVL = logging.VERBOSE
FILE_LOGLVL = logging.DEBUG
@@ -81,10 +81,7 @@ class Core:
component = self.modules[moduleIndex].Component(
moduleIndex, compPos, self
)
- # init component's widget for loading/saving presets
component.widget(loader)
- # use autoUpdate() method before update() this 1 time to set attrs
- component._autoUpdate()
else:
moduleIndex = -1
log.debug(
@@ -186,9 +183,8 @@ class Core:
if hasattr(loader, 'window'):
for widget, value in data['WindowFields']:
widget = eval('loader.window.%s' % widget)
- widget.blockSignals(True)
- toolkit.setWidgetValue(widget, value)
- widget.blockSignals(False)
+ with toolkit.blockSignals(widget):
+ toolkit.setWidgetValue(widget, value)
for key, value in data['Settings']:
Core.settings.setValue(key, value)
@@ -474,6 +470,7 @@ class Core:
'logDir': os.path.join(dataDir, 'log'),
'presetDir': os.path.join(dataDir, 'presets'),
'componentsPath': os.path.join(wd, 'components'),
+ 'junkStream': os.path.join(wd, 'gui', 'background.png'),
'encoderOptions': encoderOptions,
'resolutions': [
'1920x1080',
diff --git a/src/gui/actions.py b/src/gui/actions.py
index 0fe97f2..1444569 100644
--- a/src/gui/actions.py
+++ b/src/gui/actions.py
@@ -20,11 +20,20 @@ class AddComponent(QUndoCommand):
self.parent = parent
self.moduleI = moduleI
self.compI = compI
+ self.comp = None
def redo(self):
- self.parent.core.insertComponent(self.compI, self.moduleI, self.parent)
+ if self.comp is None:
+ self.parent.core.insertComponent(
+ self.compI, self.moduleI, self.parent)
+ else:
+ # inserting previously-created component
+ self.parent.core.insertComponent(
+ self.compI, self.comp, self.parent)
+
def undo(self):
+ self.comp = self.parent.core.selectedComponents[self.compI]
self.parent._removeComponent(self.compI)
diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py
index 8000b3b..76c53af 100644
--- a/src/gui/mainwindow.py
+++ b/src/gui/mainwindow.py
@@ -25,7 +25,7 @@ from toolkit import (
)
-log = logging.getLogger('AVP.MainWindow')
+log = logging.getLogger('AVP.Gui.MainWindow')
class MainWindow(QtWidgets.QMainWindow):
@@ -76,7 +76,7 @@ class MainWindow(QtWidgets.QMainWindow):
# Create the preview window and its thread, queues, and timers
log.debug('Creating preview window')
self.previewWindow = PreviewWindow(self, os.path.join(
- Core.wd, "background.png"))
+ Core.wd, 'gui', "background.png"))
window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
log.debug('Starting preview thread')
diff --git a/src/gui/presetmanager.py b/src/gui/presetmanager.py
index dce5333..befa7cd 100644
--- a/src/gui/presetmanager.py
+++ b/src/gui/presetmanager.py
@@ -5,12 +5,16 @@
from PyQt5 import QtCore, QtWidgets
import string
import os
+import logging
from toolkit import badName
from core import Core
from gui.actions import *
+log = logging.getLogger('AVP.Gui.PresetManager')
+
+
class PresetManager(QtWidgets.QDialog):
def __init__(self, window, parent):
super().__init__(parent.window)
diff --git a/src/gui/preview_thread.py b/src/gui/preview_thread.py
index 9615884..33a9e7a 100644
--- a/src/gui/preview_thread.py
+++ b/src/gui/preview_thread.py
@@ -14,7 +14,7 @@ from toolkit.frame import Checkerboard
from toolkit import disableWhenOpeningProject
-log = logging.getLogger("AVP.PreviewThread")
+log = logging.getLogger("AVP.Gui.PreviewThread")
class Worker(QtCore.QObject):
diff --git a/src/gui/preview_win.py b/src/gui/preview_win.py
index 40c19c6..c6b9a32 100644
--- a/src/gui/preview_win.py
+++ b/src/gui/preview_win.py
@@ -7,7 +7,7 @@ class PreviewWindow(QtWidgets.QLabel):
Paints the preview QLabel in MainWindow and maintains the aspect ratio
when the window is resized.
'''
- log = logging.getLogger('AVP.PreviewWindow')
+ log = logging.getLogger('AVP.Gui.PreviewWindow')
def __init__(self, parent, img):
super(PreviewWindow, self).__init__()
diff --git a/src/main.py b/src/main.py
index c1278da..6d18af3 100644
--- a/src/main.py
+++ b/src/main.py
@@ -6,7 +6,7 @@ import logging
from __init__ import wd
-log = logging.getLogger('AVP.Entrypoint')
+log = logging.getLogger('AVP.Main')
def main():
diff --git a/src/toolkit/common.py b/src/toolkit/common.py
index 51ad023..74143e8 100644
--- a/src/toolkit/common.py
+++ b/src/toolkit/common.py
@@ -6,19 +6,53 @@ import string
import os
import sys
import subprocess
+import logging
+from copy import copy
from collections import OrderedDict
+log = logging.getLogger('AVP.Toolkit.Common')
+
+
class blockSignals:
- '''A context manager to temporarily block a Qt widget from updating'''
- def __init__(self, widget):
- self.widget = widget
+ '''
+ Context manager to temporarily block list of QtWidgets from updating,
+ and guarantee restoring the previous state afterwards.
+ '''
+ def __init__(self, widgets):
+ if type(widgets) is dict:
+ self.widgets = concatDictVals(widgets)
+ else:
+ self.widgets = (
+ widgets if hasattr(widgets, '__iter__')
+ else [widgets]
+ )
def __enter__(self):
- self.widget.blockSignals(True)
+ log.verbose('Blocking signals for %s' % ", ".join([
+ str(w.__class__.__name__) for w in self.widgets
+ ]))
+ self.oldStates = [w.signalsBlocked() for w in self.widgets]
+ for w in self.widgets:
+ w.blockSignals(True)
def __exit__(self, *args):
- self.widget.blockSignals(False)
+ log.verbose('Resetting blockSignals to %s' % sum(self.oldStates))
+ for w, state in zip(self.widgets, self.oldStates):
+ w.blockSignals(state)
+
+
+def concatDictVals(d):
+ '''Concatenates all values in given dict into one list.'''
+ key, value = d.popitem()
+ d[key] = value
+ final = copy(value)
+ if type(final) is not list:
+ final = [final]
+ final.extend([val for val in d.values()])
+ else:
+ value.extend([item for val in d.values() for item in val])
+ return final
def badName(name):
@@ -119,12 +153,14 @@ def connectWidget(widget, func):
elif type(widget) == QtWidgets.QComboBox:
widget.currentIndexChanged.connect(func)
else:
+ log.warning('Failed to connect %s ' % str(widget.__class__.__name__))
return False
return True
def setWidgetValue(widget, val):
'''Generic setValue method for use with any typical QtWidget'''
+ log.verbose('Setting %s to %s' % (str(widget.__class__.__name__), val))
if type(widget) == QtWidgets.QLineEdit:
widget.setText(val)
elif type(widget) == QtWidgets.QSpinBox \
@@ -135,6 +171,7 @@ def setWidgetValue(widget, val):
elif type(widget) == QtWidgets.QComboBox:
widget.setCurrentIndex(val)
else:
+ log.warning('Failed to set %s ' % str(widget.__class__.__name__))
return False
return True
--
cgit v1.2.3
From 4a310ffb2870babf6774da843cad271f8a477bcc Mon Sep 17 00:00:00 2001
From: tassaron
Date: Sun, 27 Aug 2017 12:10:21 -0400
Subject: file logging can be turned completely off
and various changes to log levels and messages everywhere
---
src/component.py | 22 ++++++++----
src/components/spectrum.py | 21 ++++++++----
src/components/video.py | 21 ++++++++----
src/components/waveform.py | 20 +++++++----
src/core.py | 85 ++++++++++++++++++++++------------------------
src/gui/mainwindow.py | 18 ++++------
src/toolkit/ffmpeg.py | 22 ++++++++----
7 files changed, 119 insertions(+), 90 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/component.py b/src/component.py
index 01c1d06..f3ee188 100644
--- a/src/component.py
+++ b/src/component.py
@@ -423,7 +423,14 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
for attr, widget in self._trackedWidgets.items():
key = attr if attr not in self._presetNames \
else self._presetNames[attr]
- val = presetDict[key]
+ try:
+ val = presetDict[key]
+ except KeyError as e:
+ log.info(
+ '%s missing value %s. Outdated preset?',
+ self.currentPreset, str(e)
+ )
+ val = getattr(self, key)
if attr in self._colorWidgets:
widget.setText('%s,%s,%s' % val)
@@ -580,7 +587,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
'colorWidgets',
'relativeWidgets',
):
- setattr(self, '_%s' % kwarg, kwargs[kwarg])
+ setattr(self, '_{}'.format(kwarg), kwargs[kwarg])
else:
raise ComponentError(
self, 'Nonsensical keywords to trackWidgets.')
@@ -613,6 +620,10 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
self._relativeMaximums[attr] = \
self._trackedWidgets[attr].maximum()
self.updateRelativeWidgetMaximum(attr)
+ setattr(
+ self, attr, getWidgetValue(self._trackedWidgets[attr])
+ )
+
self._preUpdate()
self._autoUpdate()
@@ -732,13 +743,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass):
can make determining the 'previous' value tricky.
'''
if self.oldAttrs is not None:
- log.verbose('Using nonstandard oldAttr for %s', attr)
return self.oldAttrs[attr]
else:
try:
return getattr(self, attr)
except AttributeError:
- log.info('Using visible values instead of attrs')
+ log.error('Using visible values instead of oldAttrs')
return self._trackedWidgets[attr].value()
def updateRelativeWidget(self, attr):
@@ -893,7 +903,7 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
def redo(self):
if self.undone:
- log.debug('Redoing component update')
+ log.info('Redoing component update')
self.parent.oldAttrs = self.relativeWidgetValsAfterUndo
self.setWidgetValues(self.modifiedVals)
self.parent.update(auto=True)
@@ -906,7 +916,7 @@ class ComponentUpdate(QtWidgets.QUndoCommand):
self.parent._sendUpdateSignal()
def undo(self):
- log.debug('Undoing component update')
+ log.info('Undoing component update')
self.undone = True
self.parent.oldAttrs = self.relativeWidgetValsAfterRedo
self.setWidgetValues(self.oldWidgetVals)
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 2b98dc2..77cb086 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -148,15 +148,22 @@ class Component(Component):
'-codec:v', 'rawvideo', '-',
'-frames:v', '1',
])
- logFilename = os.path.join(
- self.core.logDir, 'preview_%s.log' % str(self.compPos))
- log.debug('Creating ffmpeg process (log at %s)' % logFilename)
- with open(logFilename, 'w') as logf:
- logf.write(" ".join(command) + '\n\n')
- with open(logFilename, 'a') as logf:
+
+ if self.core.logEnabled:
+ logFilename = os.path.join(
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ self.previewPipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=logf, bufsize=10**8
+ )
+ else:
self.previewPipe = openPipe(
command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=logf, bufsize=10**8
+ stderr=subprocess.DEVNULL, bufsize=10**8
)
byteFrame = self.previewPipe.stdout.read(self.chunkSize)
closePipe(self.previewPipe)
diff --git a/src/components/video.py b/src/components/video.py
index e6486ea..8ad21b5 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -139,16 +139,23 @@ class Component(Component):
'-frames:v', '1',
])
- logFilename = os.path.join(
- self.core.logDir, 'preview_%s.log' % str(self.compPos))
- log.debug('Creating ffmpeg process (log at %s)' % logFilename)
- with open(logFilename, 'w') as logf:
- logf.write(" ".join(command) + '\n\n')
- with open(logFilename, 'a') as logf:
+ if self.core.logEnabled:
+ logFilename = os.path.join(
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg process (log at %s)' % logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=logf, bufsize=10**8
+ )
+ else:
pipe = openPipe(
command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=logf, bufsize=10**8
+ stderr=subprocess.DEVNULL, bufsize=10**8
)
+
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 5c02bbf..cbfc47f 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -110,15 +110,21 @@ class Component(Component):
'-codec:v', 'rawvideo', '-',
'-frames:v', '1',
])
- logFilename = os.path.join(
- self.core.logDir, 'preview_%s.log' % str(self.compPos))
- log.debug('Creating ffmpeg process (log at %s)' % logFilename)
- with open(logFilename, 'w') as logf:
- logf.write(" ".join(command) + '\n\n')
- with open(logFilename, 'a') as logf:
+ if self.core.logEnabled:
+ logFilename = os.path.join(
+ self.core.logDir, 'preview_%s.log' % str(self.compPos))
+ log.debug('Creating ffmpeg log at %s', logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ pipe = openPipe(
+ command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
+ stderr=logf, bufsize=10**8
+ )
+ else:
pipe = openPipe(
command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=logf, bufsize=10**8
+ stderr=subprocess.DEVNULL, bufsize=10**8
)
byteFrame = pipe.stdout.read(self.chunkSize)
closePipe(pipe)
diff --git a/src/core.py b/src/core.py
index b9e2335..1a90296 100644
--- a/src/core.py
+++ b/src/core.py
@@ -13,8 +13,8 @@ import toolkit
log = logging.getLogger('AVP.Core')
-STDOUT_LOGLVL = logging.VERBOSE
-FILE_LOGLVL = logging.DEBUG
+STDOUT_LOGLVL = logging.INFO
+FILE_LOGLVL = logging.VERBOSE
class Core:
@@ -145,17 +145,11 @@ class Core:
saveValueStore = self.getPreset(filepath)
if not saveValueStore:
return False
- try:
- comp = self.selectedComponents[compIndex]
- comp.loadPreset(
- saveValueStore,
- presetName
- )
- except KeyError as e:
- log.warning(
- '%s #%s\'s preset is missing value: %s',
- comp.name, str(compIndex), str(e)
- )
+ comp = self.selectedComponents[compIndex]
+ comp.loadPreset(
+ saveValueStore,
+ presetName
+ )
self.savedPresets[presetName] = dict(saveValueStore)
return True
@@ -472,11 +466,12 @@ class Core:
encoderOptions = json.load(json_file)
settings = {
+ 'canceled': False,
+ 'FFMPEG_BIN': findFfmpeg(),
'dataDir': dataDir,
'settings': QtCore.QSettings(
os.path.join(dataDir, 'settings.ini'),
QtCore.QSettings.IniFormat),
- 'logDir': os.path.join(dataDir, 'log'),
'presetDir': os.path.join(dataDir, 'presets'),
'componentsPath': os.path.join(wd, 'components'),
'junkStream': os.path.join(wd, 'gui', 'background.png'),
@@ -486,8 +481,8 @@ class Core:
'1280x720',
'854x480',
],
- 'FFMPEG_BIN': findFfmpeg(),
- 'canceled': False,
+ 'logDir': os.path.join(dataDir, 'log'),
+ 'logEnabled': False,
}
settings['videoFormats'] = toolkit.appendUppercase([
@@ -572,42 +567,42 @@ class Core:
@staticmethod
def makeLogger():
- logFilename = os.path.join(Core.logDir, 'avp_debug.log')
- libLogFilename = os.path.join(Core.logDir, 'global_debug.log')
- # delete old logs
- for log in (logFilename, libLogFilename):
- if os.path.exists(log):
- os.remove(log)
-
- # create file handlers to capture every log message somewhere
- logFile = logging.FileHandler(logFilename)
- logFile.setLevel(FILE_LOGLVL)
- libLogFile = logging.FileHandler(libLogFilename)
- libLogFile.setLevel(FILE_LOGLVL)
-
- # send some critical log messages to stdout as well
+ # send critical log messages to stdout
logStream = logging.StreamHandler()
logStream.setLevel(STDOUT_LOGLVL)
-
- # create formatters for each stream
- fileFormatter = logging.Formatter(
- '[%(asctime)s] %(threadName)-10.10s %(name)-23.23s %(levelname)s: '
- '%(message)s'
- )
streamFormatter = logging.Formatter(
- '<%(name)s> %(message)s'
+ '<%(name)s> %(levelname)s: %(message)s'
)
- logFile.setFormatter(fileFormatter)
- libLogFile.setFormatter(fileFormatter)
logStream.setFormatter(streamFormatter)
-
log = logging.getLogger('AVP')
- log.addHandler(logFile)
log.addHandler(logStream)
- libLog = logging.getLogger()
- libLog.addHandler(libLogFile)
- # lowest level must be explicitly set on the root Logger
- libLog.setLevel(0)
+
+ if FILE_LOGLVL is not None:
+ # write log files as well!
+ Core.logEnabled = True
+ logFilename = os.path.join(Core.logDir, 'avp_debug.log')
+ libLogFilename = os.path.join(Core.logDir, 'global_debug.log')
+ # delete old logs
+ for log_ in (logFilename, libLogFilename):
+ if os.path.exists(log_):
+ os.remove(log_)
+
+ logFile = logging.FileHandler(logFilename)
+ logFile.setLevel(FILE_LOGLVL)
+ libLogFile = logging.FileHandler(libLogFilename)
+ libLogFile.setLevel(FILE_LOGLVL)
+ fileFormatter = logging.Formatter(
+ '[%(asctime)s] %(threadName)-10.10s %(name)-23.23s %(levelname)s: '
+ '%(message)s'
+ )
+ logFile.setFormatter(fileFormatter)
+ libLogFile.setFormatter(fileFormatter)
+
+ libLog = logging.getLogger()
+ log.addHandler(logFile)
+ libLog.addHandler(libLogFile)
+ # lowest level must be explicitly set on the root Logger
+ libLog.setLevel(0)
# always store settings in class variables even if a Core object is not created
Core.storeSettings()
diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py
index d7fde5c..81c5d7c 100644
--- a/src/gui/mainwindow.py
+++ b/src/gui/mainwindow.py
@@ -92,6 +92,10 @@ class MainWindow(QtWidgets.QMainWindow):
self.previewWorker.moveToThread(self.previewThread)
self.previewWorker.imageCreated.connect(self.showPreviewImage)
self.previewThread.start()
+ self.previewThread.finished.connect(
+ lambda:
+ log.critical('PREVIEW THREAD DIED! This should never happen.')
+ )
timeout = 500
log.debug(
@@ -442,7 +446,7 @@ class MainWindow(QtWidgets.QMainWindow):
appName += '*'
except AttributeError:
pass
- log.debug('Setting window title to %s' % appName)
+ log.verbose('Setting window title to %s' % appName)
self.window.setWindowTitle(appName)
@QtCore.pyqtSlot(int, dict)
@@ -459,16 +463,8 @@ class MainWindow(QtWidgets.QMainWindow):
modified = False
else:
modified = (presetStore != self.core.savedPresets[name])
- if modified:
- log.verbose(
- 'Differing values between presets: %s',
- ", ".join([
- '%s: %s' % item for item in presetStore.items()
- if val != self.core.savedPresets[name][key]
- ])
- )
- else:
- modified = bool(presetStore)
+
+ modified = bool(presetStore)
if pos < 0:
pos = len(self.core.selectedComponents)-1
name = self.core.selectedComponents[pos].name
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index a77831e..d78d803 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -91,16 +91,24 @@ class FfmpegVideo:
def fillBuffer(self):
from component import ComponentError
- logFilename = os.path.join(
- core.Core.logDir, 'render_%s.log' % str(self.component.compPos))
- log.debug('Creating ffmpeg process (log at %s)', logFilename)
- with open(logFilename, 'w') as logf:
- logf.write(" ".join(self.command) + '\n\n')
- with open(logFilename, 'a') as logf:
+ if core.Core.logEnabled:
+ logFilename = os.path.join(
+ core.Core.logDir, 'render_%s.log' % str(self.component.compPos)
+ )
+ log.debug('Creating ffmpeg process (log at %s)', logFilename)
+ with open(logFilename, 'w') as logf:
+ logf.write(" ".join(self.command) + '\n\n')
+ with open(logFilename, 'a') as logf:
+ self.pipe = openPipe(
+ self.command, stdin=subprocess.DEVNULL,
+ stdout=subprocess.PIPE, stderr=logf, bufsize=10**8
+ )
+ else:
self.pipe = openPipe(
self.command, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
- stderr=logf, bufsize=10**8
+ stderr=subprocess.DEVNULL, bufsize=10**8
)
+
while True:
if self.parent.canceled:
break
--
cgit v1.2.3
From 05d2ebc3c69f5a876d602004f69202c5ba8b09f7 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Fri, 22 Apr 2022 17:09:50 -0400
Subject: make pip-installable as a package
---
MANIFEST.in | 7 ++++++
setup.py | 61 ++++++++++++++++++++++++++--------------------
src/__init__.py | 6 ++---
src/__main__.py | 4 +--
src/component.py | 4 +--
src/components/color.py | 4 +--
src/components/image.py | 4 +--
src/components/life.py | 4 +--
src/components/original.py | 4 +--
src/components/sound.py | 4 +--
src/components/spectrum.py | 8 +++---
src/components/text.py | 4 +--
src/components/video.py | 8 +++---
src/components/waveform.py | 8 +++---
src/core.py | 12 ++++-----
src/gui/actions.py | 2 +-
src/gui/mainwindow.py | 13 +++++-----
src/gui/presetmanager.py | 6 ++---
src/gui/preview_thread.py | 4 +--
src/main.py | 11 ++++-----
src/toolkit/__init__.py | 2 +-
src/toolkit/ffmpeg.py | 8 +++---
src/toolkit/frame.py | 2 +-
src/video_thread.py | 8 +++---
24 files changed, 106 insertions(+), 92 deletions(-)
create mode 100644 MANIFEST.in
(limited to 'src/components/waveform.py')
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..2b2d794
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,7 @@
+recursive-include src/tests
+include src/components/*.ui
+include src/gui/*.ui
+include src/gui/background.png
+include src/encoder-options.json
+global-exclude src/components/__template__.ui
+global-exclude *.py[cod]
diff --git a/setup.py b/setup.py
index cdf4c4a..5e01229 100644
--- a/setup.py
+++ b/setup.py
@@ -1,29 +1,39 @@
-from setuptools import setup
-import os
+from setuptools import setup, find_packages
+from importlib import import_module
+from os import path
+import re
-__version__ = '2.0.0rc5'
+def getTextFromFile(filename, fallback):
+ try:
+ with open(
+ path.join(path.abspath(path.dirname(__file__)), filename), encoding="utf-8"
+ ) as f:
+ output = f.read()
+ except Exception:
+ output = fallback
+ return output
-def package_files(directory):
- paths = []
- for (path, directories, filenames) in os.walk(directory):
- for filename in filenames:
- paths.append(os.path.join('..', path, filename))
- return paths
+PACKAGE_NAME = 'avp'
+SOURCE_DIRECTORY = 'src'
+SOURCE_PACKAGE_REGEX = re.compile(rf'^{SOURCE_DIRECTORY}')
+PACKAGE_DESCRIPTION = 'Create audio visualization videos from a GUI or commandline'
+
+
+avp = import_module(SOURCE_DIRECTORY)
+source_packages = find_packages(include=[SOURCE_DIRECTORY, f'{SOURCE_DIRECTORY}.*'])
+proj_packages = [SOURCE_PACKAGE_REGEX.sub(PACKAGE_NAME, name) for name in source_packages]
setup(
name='audio_visualizer_python',
- version=__version__,
+ version=avp.__version__,
url='https://github.com/djfun/audio-visualizer-python/tree/feature-newgui',
license='MIT',
- description='Create audio visualization videos from a GUI or commandline',
- long_description="Create customized audio visualization videos and save "
- "them as Projects to continue editing later. Different components can "
- "be added and layered to add visualizers, images, videos, gradients, "
- "text, etc. Use Projects created in the GUI with commandline mode to "
- "automate your video production workflow without any complex syntax.",
+ description=PACKAGE_DESCRIPTION,
+ author=getTextFromFile('AUTHORS', 'djfun, tassaron'),
+ long_description=getTextFromFile('README.md', PACKAGE_DESCRIPTION),
classifiers=[
'Development Status :: 4 - Beta',
'License :: OSI Approved :: MIT License',
@@ -35,19 +45,18 @@ setup(
'visualizer', 'visualization', 'commandline video',
'video editor', 'ffmpeg', 'podcast'
],
- packages=[
- 'avpython',
- 'avpython.toolkit',
- 'avpython.components'
+ packages=proj_packages,
+ package_dir={PACKAGE_NAME: SOURCE_DIRECTORY},
+ include_package_data=True,
+ install_requires=[
+ 'Pillow-SIMD',
+ 'PyQt5',
+ 'numpy',
+ 'pytest'
],
- package_dir={'avpython': 'src'},
- package_data={
- 'avpython': package_files('src'),
- },
- install_requires=['Pillow-SIMD', 'PyQt5', 'numpy'],
entry_points={
'gui_scripts': [
- 'avp = avpython.main:main'
+ f'avp = {PACKAGE_NAME}.main:main'
],
}
)
diff --git a/src/__init__.py b/src/__init__.py
index 73f174a..08131ce 100644
--- a/src/__init__.py
+++ b/src/__init__.py
@@ -3,6 +3,9 @@ import os
import logging
+__version__ = '2.0.0rc6'
+
+
class Logger(logging.getLoggerClass()):
'''
Custom Logger class to handle custom VERBOSE log level.
@@ -31,6 +34,3 @@ if getattr(sys, 'frozen', False):
else:
# unfrozen
wd = os.path.dirname(os.path.realpath(__file__))
-
-# make relative imports work when using /src as a package
-sys.path.insert(0, wd)
diff --git a/src/__main__.py b/src/__main__.py
index 3babeae..3206bc8 100644
--- a/src/__main__.py
+++ b/src/__main__.py
@@ -1,5 +1,5 @@
-# Allows for launching with python3 -m avpython
+# Allows for launching with python3 -m avp
-from avpython.main import main
+from .main import main
main()
diff --git a/src/component.py b/src/component.py
index f3ee188..33c7657 100644
--- a/src/component.py
+++ b/src/component.py
@@ -11,8 +11,8 @@ import time
import logging
from copy import copy
-from toolkit.frame import BlankFrame
-from toolkit import (
+from .toolkit.frame import BlankFrame
+from .toolkit import (
getWidgetValue, setWidgetValue, connectWidget, rgbFromString, blockSignals
)
diff --git a/src/components/color.py b/src/components/color.py
index 7d4f86d..6336194 100644
--- a/src/components/color.py
+++ b/src/components/color.py
@@ -4,8 +4,8 @@ from PyQt5.QtGui import QColor
from PIL.ImageQt import ImageQt
import os
-from component import Component
-from toolkit.frame import BlankFrame, FloodFrame, FramePainter, PaintColor
+from ..component import Component
+from ..toolkit.frame import BlankFrame, FloodFrame, FramePainter, PaintColor
class Component(Component):
diff --git a/src/components/image.py b/src/components/image.py
index dd363bf..42f9564 100644
--- a/src/components/image.py
+++ b/src/components/image.py
@@ -2,8 +2,8 @@ from PIL import Image, ImageDraw, ImageEnhance
from PyQt5 import QtGui, QtCore, QtWidgets
import os
-from component import Component
-from toolkit.frame import BlankFrame
+from ..component import Component
+from ..toolkit.frame import BlankFrame
class Component(Component):
diff --git a/src/components/life.py b/src/components/life.py
index 7a610eb..94704bc 100644
--- a/src/components/life.py
+++ b/src/components/life.py
@@ -4,8 +4,8 @@ from PIL import Image, ImageDraw, ImageEnhance, ImageChops, ImageFilter
import os
import math
-from component import Component
-from toolkit.frame import BlankFrame, scale
+from ..component import Component
+from ..toolkit.frame import BlankFrame, scale
class Component(Component):
diff --git a/src/components/original.py b/src/components/original.py
index f886374..80228fe 100644
--- a/src/components/original.py
+++ b/src/components/original.py
@@ -6,8 +6,8 @@ import os
import time
from copy import copy
-from component import Component
-from toolkit.frame import BlankFrame
+from ..component import Component
+from ..toolkit.frame import BlankFrame
class Component(Component):
diff --git a/src/components/sound.py b/src/components/sound.py
index 18d2a65..118ea23 100644
--- a/src/components/sound.py
+++ b/src/components/sound.py
@@ -1,8 +1,8 @@
from PyQt5 import QtGui, QtCore, QtWidgets
import os
-from component import Component
-from toolkit.frame import BlankFrame
+from ..component import Component
+from ..toolkit.frame import BlankFrame
class Component(Component):
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index 6675f5b..d1f8fb6 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -6,10 +6,10 @@ import subprocess
import time
import logging
-from component import Component
-from toolkit.frame import BlankFrame, scale
-from toolkit import checkOutput, connectWidget
-from toolkit.ffmpeg import (
+from ..component import Component
+from ..toolkit.frame import BlankFrame, scale
+from ..toolkit import checkOutput, connectWidget
+from ..toolkit.ffmpeg import (
openPipe, closePipe, getAudioDuration, FfmpegVideo, exampleSound
)
diff --git a/src/components/text.py b/src/components/text.py
index 32a108e..e8c5a9c 100644
--- a/src/components/text.py
+++ b/src/components/text.py
@@ -4,8 +4,8 @@ from PyQt5 import QtGui, QtCore, QtWidgets
import os
import logging
-from component import Component
-from toolkit.frame import FramePainter, PaintColor
+from ..component import Component
+from ..toolkit.frame import FramePainter, PaintColor
log = logging.getLogger('AVP.Components.Text')
diff --git a/src/components/video.py b/src/components/video.py
index 8ad21b5..070940d 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -5,10 +5,10 @@ import math
import subprocess
import logging
-from component import Component
-from toolkit.frame import BlankFrame, scale
-from toolkit.ffmpeg import openPipe, closePipe, testAudioStream, FfmpegVideo
-from toolkit import checkOutput
+from ..component import Component
+from ..toolkit.frame import BlankFrame, scale
+from ..toolkit.ffmpeg import openPipe, closePipe, testAudioStream, FfmpegVideo
+from ..toolkit import checkOutput
log = logging.getLogger('AVP.Components.Video')
diff --git a/src/components/waveform.py b/src/components/waveform.py
index cbfc47f..1a6035f 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -6,10 +6,10 @@ import math
import subprocess
import logging
-from component import Component
-from toolkit.frame import BlankFrame, scale
-from toolkit import checkOutput
-from toolkit.ffmpeg import (
+from ..component import Component
+from ..toolkit.frame import BlankFrame, scale
+from ..toolkit import checkOutput
+from ..toolkit.ffmpeg import (
openPipe, closePipe, getAudioDuration, FfmpegVideo, exampleSound
)
diff --git a/src/core.py b/src/core.py
index d7445c9..bc6f9b4 100644
--- a/src/core.py
+++ b/src/core.py
@@ -9,12 +9,12 @@ import json
from importlib import import_module
import logging
-import toolkit
+from . import toolkit
log = logging.getLogger('AVP.Core')
STDOUT_LOGLVL = logging.WARNING
-FILE_LOGLVL = None
+FILE_LOGLVL = logging.ERROR
class Core:
@@ -47,7 +47,7 @@ class Core:
yield name
log.debug('Importing component modules')
self.modules = [
- import_module('components.%s' % name)
+ import_module('.components.%s' % name, __package__)
for name in findComponents()
]
# store canonical module names and indexes
@@ -426,7 +426,7 @@ class Core:
def newVideoWorker(self, loader, audioFile, outputPath):
'''loader is MainWindow or Command object which must own the thread'''
- import video_thread
+ from . import video_thread
self.videoThread = QtCore.QThread(loader)
videoWorker = video_thread.Worker(
loader, audioFile, outputPath, self.selectedComponents
@@ -450,8 +450,8 @@ class Core:
@classmethod
def storeSettings(cls):
'''Store settings/paths to directories as class variables'''
- from __init__ import wd
- from toolkit.ffmpeg import findFfmpeg
+ from .__init__ import wd
+ from .toolkit.ffmpeg import findFfmpeg
cls.wd = wd
dataDir = QtCore.QStandardPaths.writableLocation(
diff --git a/src/gui/actions.py b/src/gui/actions.py
index 8e867b9..eb7b953 100644
--- a/src/gui/actions.py
+++ b/src/gui/actions.py
@@ -5,7 +5,7 @@ from PyQt5.QtWidgets import QUndoCommand
import os
from copy import copy
-from core import Core
+from ..core import Core
# =~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~==~=~=~=~=~=~=~=~=~=~=~=~=~=~
diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py
index 75534c2..da8370d 100644
--- a/src/gui/mainwindow.py
+++ b/src/gui/mainwindow.py
@@ -16,12 +16,12 @@ import filecmp
import time
import logging
-from core import Core
-import gui.preview_thread as preview_thread
-from gui.preview_win import PreviewWindow
-from gui.presetmanager import PresetManager
-from gui.actions import *
-from toolkit import (
+from ..core import Core
+from . import preview_thread
+from .preview_win import PreviewWindow
+from .presetmanager import PresetManager
+from .actions import *
+from ..toolkit import (
disableWhenEncoding, disableWhenOpeningProject, checkOutput, blockSignals
)
@@ -65,7 +65,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.settings = Core.settings
# Register clean-up functions
- signal.signal(signal.SIGINT, self.terminate)
atexit.register(self.cleanUp)
# Create stack of undoable user actions
diff --git a/src/gui/presetmanager.py b/src/gui/presetmanager.py
index 2445760..1e47a7f 100644
--- a/src/gui/presetmanager.py
+++ b/src/gui/presetmanager.py
@@ -7,9 +7,9 @@ import string
import os
import logging
-from toolkit import badName
-from core import Core
-from gui.actions import *
+from ..toolkit import badName
+from ..core import Core
+from .actions import *
log = logging.getLogger('AVP.Gui.PresetManager')
diff --git a/src/gui/preview_thread.py b/src/gui/preview_thread.py
index d3e0581..7829476 100644
--- a/src/gui/preview_thread.py
+++ b/src/gui/preview_thread.py
@@ -10,8 +10,8 @@ from queue import Queue, Empty
import os
import logging
-from toolkit.frame import Checkerboard
-from toolkit import disableWhenOpeningProject
+from ..toolkit.frame import Checkerboard
+from ..toolkit import disableWhenOpeningProject
log = logging.getLogger("AVP.Gui.PreviewThread")
diff --git a/src/main.py b/src/main.py
index 126e4a8..5fabda3 100644
--- a/src/main.py
+++ b/src/main.py
@@ -3,7 +3,7 @@ import sys
import os
import logging
-from __init__ import wd
+from .__init__ import wd
log = logging.getLogger('AVP.Main')
@@ -12,6 +12,7 @@ log = logging.getLogger('AVP.Main')
def main():
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("audio-visualizer")
+ proj = None
# Determine mode
mode = 'GUI'
@@ -23,19 +24,17 @@ def main():
else:
# opening a project file with gui
proj = sys.argv[1]
- else:
- # normal gui launch
- proj = None
# Launch program
if mode == 'commandline':
- from command import Command
+ from .command import Command
main = Command()
+ main.parseArgs()
log.debug("Finished creating command object")
elif mode == 'GUI':
- from gui.mainwindow import MainWindow
+ from .gui.mainwindow import MainWindow
window = uic.loadUi(os.path.join(wd, "gui", "mainwindow.ui"))
# window.adjustSize()
diff --git a/src/toolkit/__init__.py b/src/toolkit/__init__.py
index 3fca275..55e5f84 100644
--- a/src/toolkit/__init__.py
+++ b/src/toolkit/__init__.py
@@ -1 +1 @@
-from toolkit.common import *
+from .common import *
diff --git a/src/toolkit/ffmpeg.py b/src/toolkit/ffmpeg.py
index 419d491..3298c04 100644
--- a/src/toolkit/ffmpeg.py
+++ b/src/toolkit/ffmpeg.py
@@ -10,8 +10,8 @@ import signal
from queue import PriorityQueue
import logging
-import core
-from toolkit.common import checkOutput, pipeWrapper
+from .. import core
+from .common import checkOutput, pipeWrapper
log = logging.getLogger('AVP.Toolkit.Ffmpeg')
@@ -90,7 +90,7 @@ class FfmpegVideo:
self.frameBuffer.task_done()
def fillBuffer(self):
- from component import ComponentError
+ from ..component import ComponentError
if core.Core.logEnabled:
logFilename = os.path.join(
core.Core.logDir, 'render_%s.log' % str(self.component.compPos)
@@ -144,7 +144,7 @@ def openPipe(commandList, **kwargs):
def closePipe(pipe):
pipe.stdout.close()
- pipe.send_signal(signal.SIGINT)
+ pipe.send_signal(signal.SIGTERM)
def findFfmpeg():
diff --git a/src/toolkit/frame.py b/src/toolkit/frame.py
index 0e200b5..f2511fe 100644
--- a/src/toolkit/frame.py
+++ b/src/toolkit/frame.py
@@ -9,7 +9,7 @@ import os
import math
import logging
-import core
+from .. import core
log = logging.getLogger('AVP.Toolkit.Frame')
diff --git a/src/video_thread.py b/src/video_thread.py
index 0a39f28..31331a3 100644
--- a/src/video_thread.py
+++ b/src/video_thread.py
@@ -19,9 +19,9 @@ import time
import signal
import logging
-from component import ComponentError
-from toolkit.frame import Checkerboard
-from toolkit.ffmpeg import (
+from .component import ComponentError
+from .toolkit.frame import Checkerboard
+from .toolkit.ffmpeg import (
openPipe, readAudioFile,
getAudioDuration, createFfmpegCommand
)
@@ -400,7 +400,7 @@ class Worker(QtCore.QObject):
comp.cancel()
try:
- self.out_pipe.send_signal(signal.SIGINT)
+ self.out_pipe.send_signal(signal.SIGTERM)
except Exception:
pass
--
cgit v1.2.3
From c2c3f0aa5adf3127b84b3d50da9e1aa655c8a824 Mon Sep 17 00:00:00 2001
From: tassaron
Date: Fri, 29 Apr 2022 21:15:17 -0400
Subject: remove extra window properties from window objects instead of windows
with properties which are windows, windows now have the UI added directly to
them using an argument of `uic.loadUi` Also, DPI scaling moved to MainWindow
__init__
---
src/components/spectrum.py | 6 +-
src/components/video.py | 4 +-
src/components/waveform.py | 6 +-
src/core.py | 2 +-
src/gui/actions.py | 8 +-
src/gui/mainwindow.py | 351 +++++++++++++++++++++++----------------------
src/gui/presetmanager.py | 88 ++++++------
src/gui/preview_win.py | 2 +-
src/main.py | 18 +--
9 files changed, 242 insertions(+), 243 deletions(-)
(limited to 'src/components/waveform.py')
diff --git a/src/components/spectrum.py b/src/components/spectrum.py
index d1f8fb6..91f2afb 100644
--- a/src/components/spectrum.py
+++ b/src/components/spectrum.py
@@ -30,9 +30,9 @@ class Component(Component):
self.previewSize = (214, 120)
self.previewPipe = None
- if hasattr(self.parent, 'window'):
+ if hasattr(self.parent, 'lineEdit_audioFile'):
# update preview when audio file changes (if genericPreview is off)
- self.parent.window.lineEdit_audioFile.textChanged.connect(
+ self.parent.lineEdit_audioFile.textChanged.connect(
self.update
)
@@ -123,7 +123,7 @@ class Component(Component):
genericPreview = self.settings.value("pref_genericPreview")
startPt = 0
if not genericPreview:
- inputFile = self.parent.window.lineEdit_audioFile.text()
+ inputFile = self.parent.lineEdit_audioFile.text()
if not inputFile or not os.path.exists(inputFile):
return
duration = getAudioDuration(inputFile)
diff --git a/src/components/video.py b/src/components/video.py
index 070940d..9fffc26 100644
--- a/src/components/video.py
+++ b/src/components/video.py
@@ -63,8 +63,8 @@ class Component(Component):
def properties(self):
props = []
- if hasattr(self.parent, 'window'):
- outputFile = self.parent.window.lineEdit_outputFile.text()
+ if hasattr(self.parent, 'lineEdit_outputFile'):
+ outputFile = self.parent.lineEdit_outputFile.text()
else:
outputFile = str(self.parent.args.output)
diff --git a/src/components/waveform.py b/src/components/waveform.py
index 1a6035f..227f711 100644
--- a/src/components/waveform.py
+++ b/src/components/waveform.py
@@ -27,8 +27,8 @@ class Component(Component):
self.page.lineEdit_color.setText('255,255,255')
- if hasattr(self.parent, 'window'):
- self.parent.window.lineEdit_audioFile.textChanged.connect(
+ if hasattr(self.parent, 'lineEdit_audioFile'):
+ self.parent.lineEdit_audioFile.textChanged.connect(
self.update
)
@@ -82,7 +82,7 @@ class Component(Component):
genericPreview = self.settings.value("pref_genericPreview")
startPt = 0
if not genericPreview:
- inputFile = self.parent.window.lineEdit_audioFile.text()
+ inputFile = self.parent.lineEdit_audioFile.text()
if not inputFile or not os.path.exists(inputFile):
return
duration = getAudioDuration(inputFile)
diff --git a/src/core.py b/src/core.py
index 42fd1c3..225d8e0 100644
--- a/src/core.py
+++ b/src/core.py
@@ -181,7 +181,7 @@ class Core:
try:
if hasattr(loader, 'window'):
for widget, value in data['WindowFields']:
- widget = eval('loader.window.%s' % widget)
+ widget = eval('loader.%s' % widget)
with toolkit.blockSignals(widget):
toolkit.setWidgetValue(widget, value)
diff --git a/src/gui/actions.py b/src/gui/actions.py
index eb7b953..afb980a 100644
--- a/src/gui/actions.py
+++ b/src/gui/actions.py
@@ -41,7 +41,7 @@ class RemoveComponent(QUndoCommand):
def __init__(self, parent, selectedRows):
super().__init__('remove component')
self.parent = parent
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
self.selectedRows = [
componentList.row(selected) for selected in selectedRows
]
@@ -53,7 +53,7 @@ class RemoveComponent(QUndoCommand):
self.parent._removeComponent(self.selectedRows[0])
def undo(self):
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
for index, comp in zip(self.selectedRows, self.components):
self.parent.core.insertComponent(
index, comp, self.parent
@@ -78,7 +78,7 @@ class MoveComponent(QUndoCommand):
return True
def do(self, rowa, rowb):
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
page = self.parent.pages.pop(rowa)
self.parent.pages.insert(rowb, page)
@@ -86,7 +86,7 @@ class MoveComponent(QUndoCommand):
item = componentList.takeItem(rowa)
componentList.insertItem(rowb, item)
- stackedWidget = self.parent.window.stackedWidget
+ stackedWidget = self.parent.stackedWidget
widget = stackedWidget.removeWidget(page)
stackedWidget.insertWidget(rowb, page)
componentList.setCurrentRow(rowb)
diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py
index 463d028..c31eec9 100644
--- a/src/gui/mainwindow.py
+++ b/src/gui/mainwindow.py
@@ -4,13 +4,12 @@
This shows a preview of the video being created and allows for saving
projects and exporting the video at a later time.
'''
-from PyQt5 import QtCore, QtGui, uic, QtWidgets
-from PyQt5.QtWidgets import QMenu, QShortcut
+from PyQt5 import QtCore, QtGui, QtWidgets, uic
+import PyQt5.QtWidgets as QtWidgets
from PIL import Image
from queue import Queue
import sys
import os
-import signal
import atexit
import filecmp
import time
@@ -43,11 +42,22 @@ class MainWindow(QtWidgets.QMainWindow):
newTask = QtCore.pyqtSignal(list) # for the preview window
processTask = QtCore.pyqtSignal()
- def __init__(self, window, project):
- QtWidgets.QMainWindow.__init__(self)
+ def __init__(self, project):
+ super().__init__()
log.debug(
'Main thread id: {}'.format(int(QtCore.QThread.currentThreadId())))
- self.window = window
+ uic.loadUi(os.path.join(Core.wd, "gui", "mainwindow.ui"), self)
+ desk = QtWidgets.QDesktopWidget()
+ dpi = desk.physicalDpiX()
+ log.info("Detected screen DPI: %s", dpi)
+
+ self.resize(
+ int(self.width() *
+ (dpi / 96)),
+ int(self.height() *
+ (dpi / 96))
+ )
+
self.core = Core()
Core.mode = 'GUI'
# widgets of component settings
@@ -73,15 +83,13 @@ class MainWindow(QtWidgets.QMainWindow):
self.undoStack.setUndoLimit(undoLimit)
# Create Preset Manager
- self.presetManager = PresetManager(
- uic.loadUi(
- os.path.join(Core.wd, 'gui', 'presetmanager.ui')), self)
+ self.presetManager = PresetManager(self)
# Create the preview window and its thread, queues, and timers
log.debug('Creating preview window')
self.previewWindow = PreviewWindow(self, os.path.join(
Core.wd, 'gui', "background.png"))
- window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
+ self.verticalLayout_previewWrapper.addWidget(self.previewWindow)
log.debug('Starting preview thread')
self.previewQueue = Queue()
@@ -105,7 +113,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.timer.start(timeout)
# Begin decorating the window and connecting events
- componentList = self.window.listWidget_componentList
+ componentList = self.listWidget_componentList
# Undo Feature
def toggleUndoButtonEnabled(*_):
@@ -116,15 +124,15 @@ class MainWindow(QtWidgets.QMainWindow):
# program is probably in midst of exiting
pass
- style = window.pushButton_undo.style()
- undoButton = window.pushButton_undo
+ style = self.pushButton_undo.style()
+ undoButton = self.pushButton_undo
undoButton.setIcon(
style.standardIcon(QtWidgets.QStyle.SP_FileDialogBack)
)
undoButton.clicked.connect(self.undoStack.undo)
undoButton.setEnabled(False)
self.undoStack.cleanChanged.connect(toggleUndoButtonEnabled)
- self.undoMenu = QMenu()
+ self.undoMenu = QtWidgets.QMenu()
self.undoMenu.addAction(
self.undoStack.createUndoAction(self)
)
@@ -138,93 +146,93 @@ class MainWindow(QtWidgets.QMainWindow):
undoButton.setMenu(self.undoMenu)
# end of Undo Feature
- style = window.pushButton_listMoveUp.style()
- window.pushButton_listMoveUp.setIcon(
+ style = self.pushButton_listMoveUp.style()
+ self.pushButton_listMoveUp.setIcon(
style.standardIcon(QtWidgets.QStyle.SP_ArrowUp)
)
- style = window.pushButton_listMoveDown.style()
- window.pushButton_listMoveDown.setIcon(
+ style = self.pushButton_listMoveDown.style()
+ self.pushButton_listMoveDown.setIcon(
style.standardIcon(QtWidgets.QStyle.SP_ArrowDown)
)
- style = window.pushButton_removeComponent.style()
- window.pushButton_removeComponent.setIcon(
+ style = self.pushButton_removeComponent.style()
+ self.pushButton_removeComponent.setIcon(
style.standardIcon(QtWidgets.QStyle.SP_DialogDiscardButton)
)
if sys.platform == 'darwin':
log.debug(
'Darwin detected: showing progress label below progress bar')
- window.progressBar_createVideo.setTextVisible(False)
+ self.progressBar_createVideo.setTextVisible(False)
else:
- window.progressLabel.setHidden(True)
+ self.progressLabel.setHidden(True)
- window.toolButton_selectAudioFile.clicked.connect(
+ self.toolButton_selectAudioFile.clicked.connect(
self.openInputFileDialog)
- window.toolButton_selectOutputFile.clicked.connect(
+ self.toolButton_selectOutputFile.clicked.connect(
self.openOutputFileDialog)
def changedField():
self.autosave()
self.updateWindowTitle()
- window.lineEdit_audioFile.textChanged.connect(changedField)
- window.lineEdit_outputFile.textChanged.connect(changedField)
+ self.lineEdit_audioFile.textChanged.connect(changedField)
+ self.lineEdit_outputFile.textChanged.connect(changedField)
- window.progressBar_createVideo.setValue(0)
+ self.progressBar_createVideo.setValue(0)
- window.pushButton_createVideo.clicked.connect(
+ self.pushButton_createVideo.clicked.connect(
self.createAudioVisualisation)
- window.pushButton_Cancel.clicked.connect(self.stopVideo)
+ self.pushButton_Cancel.clicked.connect(self.stopVideo)
for i, container in enumerate(Core.encoderOptions['containers']):
- window.comboBox_videoContainer.addItem(container['name'])
+ self.comboBox_videoContainer.addItem(container['name'])
if container['name'] == self.settings.value('outputContainer'):
selectedContainer = i
- window.comboBox_videoContainer.setCurrentIndex(selectedContainer)
- window.comboBox_videoContainer.currentIndexChanged.connect(
+ self.comboBox_videoContainer.setCurrentIndex(selectedContainer)
+ self.comboBox_videoContainer.currentIndexChanged.connect(
self.updateCodecs
)
self.updateCodecs()
- for i in range(window.comboBox_videoCodec.count()):
- codec = window.comboBox_videoCodec.itemText(i)
+ for i in range(self.comboBox_videoCodec.count()):
+ codec = self.comboBox_videoCodec.itemText(i)
if codec == self.settings.value('outputVideoCodec'):
- window.comboBox_videoCodec.setCurrentIndex(i)
+ self.comboBox_videoCodec.setCurrentIndex(i)
- for i in range(window.comboBox_audioCodec.count()):
- codec = window.comboBox_audioCodec.itemText(i)
+ for i in range(self.comboBox_audioCodec.count()):
+ codec = self.comboBox_audioCodec.itemText(i)
if codec == self.settings.value('outputAudioCodec'):
- window.comboBox_audioCodec.setCurrentIndex(i)
+ self.comboBox_audioCodec.setCurrentIndex(i)
- window.comboBox_videoCodec.currentIndexChanged.connect(
+ self.comboBox_videoCodec.currentIndexChanged.connect(
self.updateCodecSettings
)
- window.comboBox_audioCodec.currentIndexChanged.connect(
+ self.comboBox_audioCodec.currentIndexChanged.connect(
self.updateCodecSettings
)
vBitrate = int(self.settings.value('outputVideoBitrate'))
aBitrate = int(self.settings.value('outputAudioBitrate'))
- window.spinBox_vBitrate.setValue(vBitrate)
- window.spinBox_aBitrate.setValue(aBitrate)
- window.spinBox_vBitrate.valueChanged.connect(self.updateCodecSettings)
- window.spinBox_aBitrate.valueChanged.connect(self.updateCodecSettings)
+ self.spinBox_vBitrate.setValue(vBitrate)
+ self.spinBox_aBitrate.setValue(aBitrate)
+ self.spinBox_vBitrate.valueChanged.connect(self.updateCodecSettings)
+ self.spinBox_aBitrate.valueChanged.connect(self.updateCodecSettings)
# Make component buttons
- self.compMenu = QMenu()
+ self.compMenu = QtWidgets.QMenu()
for i, comp in enumerate(self.core.modules):
action = self.compMenu.addAction(comp.Component.name)
action.triggered.connect(
lambda _, item=i: self.addComponent(0, item)
)
- self.window.pushButton_addComponent.setMenu(self.compMenu)
+ self.pushButton_addComponent.setMenu(self.compMenu)
componentList.dropEvent = self.dragComponent
componentList.itemSelectionChanged.connect(
@@ -233,7 +241,7 @@ class MainWindow(QtWidgets.QMainWindow):
componentList.itemSelectionChanged.connect(
self.presetManager.clearPresetListSelection
)
- self.window.pushButton_removeComponent.clicked.connect(
+ self.pushButton_removeComponent.clicked.connect(
lambda: self.removeComponent()
)
@@ -245,33 +253,33 @@ class MainWindow(QtWidgets.QMainWindow):
currentRes = str(self.settings.value('outputWidth'))+'x' + \
str(self.settings.value('outputHeight'))
for i, res in enumerate(Core.resolutions):
- window.comboBox_resolution.addItem(res)
+ self.comboBox_resolution.addItem(res)
if res == currentRes:
currentRes = i
- window.comboBox_resolution.setCurrentIndex(currentRes)
- window.comboBox_resolution.currentIndexChanged.connect(
+ self.comboBox_resolution.setCurrentIndex(currentRes)
+ self.comboBox_resolution.currentIndexChanged.connect(
self.updateResolution
)
- self.window.pushButton_listMoveUp.clicked.connect(
+ self.pushButton_listMoveUp.clicked.connect(
lambda: self.moveComponent(-1)
)
- self.window.pushButton_listMoveDown.clicked.connect(
+ self.pushButton_listMoveDown.clicked.connect(
lambda: self.moveComponent(1)
)
# Configure the Projects Menu
- self.projectMenu = QMenu()
- self.window.menuButton_newProject = self.projectMenu.addAction(
+ self.projectMenu = QtWidgets.QMenu()
+ self.menuButton_newProject = self.projectMenu.addAction(
"New Project"
)
- self.window.menuButton_newProject.triggered.connect(
+ self.menuButton_newProject.triggered.connect(
lambda: self.createNewProject()
)
- self.window.menuButton_openProject = self.projectMenu.addAction(
+ self.menuButton_openProject = self.projectMenu.addAction(
"Open Project"
)
- self.window.menuButton_openProject.triggered.connect(
+ self.menuButton_openProject.triggered.connect(
lambda: self.openOpenProjectDialog()
)
@@ -281,16 +289,16 @@ class MainWindow(QtWidgets.QMainWindow):
action = self.projectMenu.addAction("Save Project As")
action.triggered.connect(self.openSaveProjectDialog)
- self.window.pushButton_projects.setMenu(self.projectMenu)
+ self.pushButton_projects.setMenu(self.projectMenu)
# Configure the Presets Button
- self.window.pushButton_presets.clicked.connect(
+ self.pushButton_presets.clicked.connect(
self.openPresetManager
)
self.updateWindowTitle()
log.debug('Showing main window')
- window.show()
+ self.show()
if project and project != self.autosavePath:
if not project.endswith('.avp'):
@@ -358,77 +366,80 @@ class MainWindow(QtWidgets.QMainWindow):
self.settings.setValue("ffmpegMsgShown", True)
# Hotkeys for projects
- QtWidgets.QShortcut("Ctrl+S", self.window, self.saveCurrentProject)
- QtWidgets.QShortcut("Ctrl+A", self.window, self.openSaveProjectDialog)
- QtWidgets.QShortcut("Ctrl+O", self.window, self.openOpenProjectDialog)
- QtWidgets.QShortcut("Ctrl+N", self.window, self.createNewProject)
+ QtWidgets.QShortcut("Ctrl+S", self, self.saveCurrentProject)
+ QtWidgets.QShortcut("Ctrl+A", self, self.openSaveProjectDialog)
+ QtWidgets.QShortcut("Ctrl+O", self, self.openOpenProjectDialog)
+ QtWidgets.QShortcut("Ctrl+N", self, self.createNewProject)
- QtWidgets.QShortcut("Ctrl+Z", self.window, self.undoStack.undo)
- QtWidgets.QShortcut("Ctrl+Y", self.window, self.undoStack.redo)
- QtWidgets.QShortcut("Ctrl+Shift+Z", self.window, self.undoStack.redo)
+ # Hotkeys for undo/redo
+ QtWidgets.QShortcut("Ctrl+Z", self, self.undoStack.undo)
+ QtWidgets.QShortcut("Ctrl+Y", self, self.undoStack.redo)
+ QtWidgets.QShortcut("Ctrl+Shift+Z", self, self.undoStack.redo)
# Hotkeys for component list
for inskey in ("Ctrl+T", QtCore.Qt.Key_Insert):
QtWidgets.QShortcut(
- inskey, self.window,
- activated=lambda: self.window.pushButton_addComponent.click()
+ inskey, self,
+ activated=lambda: self.pushButton_addComponent.click()
)
for delkey in ("Ctrl+R", QtCore.Qt.Key_Delete):
QtWidgets.QShortcut(
- delkey, self.window.listWidget_componentList,
+ delkey, self.listWidget_componentList,
self.removeComponent
)
QtWidgets.QShortcut(
- "Ctrl+Space", self.window,
- activated=lambda: self.window.listWidget_componentList.setFocus()
+ "Ctrl+Space", self,
+ activated=lambda: self.listWidget_componentList.setFocus()
)
QtWidgets.QShortcut(
- "Ctrl+Shift+S", self.window,
+ "Ctrl+Shift+S", self,
self.presetManager.openSavePresetDialog
)
QtWidgets.QShortcut(
- "Ctrl+Shift+C", self.window, self.presetManager.clearPreset
+ "Ctrl+Shift+C", self, self.presetManager.clearPreset
)
QtWidgets.QShortcut(
- "Ctrl+Up", self.window.listWidget_componentList,
+ "Ctrl+Up", self.listWidget_componentList,
activated=lambda: self.moveComponent(-1)
)
QtWidgets.QShortcut(
- "Ctrl+Down", self.window.listWidget_componentList,
+ "Ctrl+Down", self.listWidget_componentList,
activated=lambda: self.moveComponent(1)
)
QtWidgets.QShortcut(
- "Ctrl+Home", self.window.listWidget_componentList,
+ "Ctrl+Home", self.listWidget_componentList,
activated=lambda: self.moveComponent('top')
)
QtWidgets.QShortcut(
- "Ctrl+End", self.window.listWidget_componentList,
+ "Ctrl+End", self.listWidget_componentList,
activated=lambda: self.moveComponent('bottom')
)
QtWidgets.QShortcut(
- "Ctrl+Shift+F", self.window, self.showFfmpegCommand
+ "Ctrl+Shift+F", self, self.showFfmpegCommand
)
QtWidgets.QShortcut(
- "Ctrl+Shift+U", self.window, self.showUndoStack
+ "Ctrl+Shift+U", self, self.showUndoStack
)
if log.isEnabledFor(logging.DEBUG):
QtWidgets.QShortcut(
- "Ctrl+Alt+Shift+R", self.window, self.drawPreview
+ "Ctrl+Alt+Shift+R", self, self.drawPreview
)
QtWidgets.QShortcut(
- "Ctrl+Alt+Shift+A", self.window, lambda: log.debug(repr(self))
+ "Ctrl+Alt+Shift+A", self, lambda: log.debug(repr(self))
)
def __repr__(self):
return (
+ '%s\n'
'\n%s\n'
'#####\n'
'Preview thread is %s\n' % (
- repr(self.core),
- 'live' if self.previewThread.isRunning() else 'dead',
+ super().__repr__(),
+ "core not initialized" if not hasattr(self, "core") else repr(self.core),
+ 'live' if hasattr(self, "previewThread") and self.previewThread.isRunning() else 'dead',
)
)
@@ -456,7 +467,7 @@ class MainWindow(QtWidgets.QMainWindow):
except AttributeError:
pass
log.verbose(f'Window title is "{appName}"')
- self.window.setWindowTitle(appName)
+ self.setWindowTitle(appName)
@QtCore.pyqtSlot(int, dict)
def updateComponentTitle(self, pos, presetStore=False):
@@ -492,12 +503,12 @@ class MainWindow(QtWidgets.QMainWindow):
'Setting %s #%s\'s title: %s',
name, pos, title
)
- self.window.listWidget_componentList.item(pos).setText(title)
+ self.listWidget_componentList.item(pos).setText(title)
def updateCodecs(self):
- containerWidget = self.window.comboBox_videoContainer
- vCodecWidget = self.window.comboBox_videoCodec
- aCodecWidget = self.window.comboBox_audioCodec
+ containerWidget = self.comboBox_videoContainer
+ vCodecWidget = self.comboBox_videoCodec
+ aCodecWidget = self.comboBox_audioCodec
index = containerWidget.currentIndex()
name = containerWidget.itemText(index)
self.settings.setValue('outputContainer', name)
@@ -514,10 +525,10 @@ class MainWindow(QtWidgets.QMainWindow):
def updateCodecSettings(self):
'''Updates settings.ini to match encoder option widgets'''
- vCodecWidget = self.window.comboBox_videoCodec
- vBitrateWidget = self.window.spinBox_vBitrate
- aBitrateWidget = self.window.spinBox_aBitrate
- aCodecWidget = self.window.comboBox_audioCodec
+ vCodecWidget = self.comboBox_videoCodec
+ vBitrateWidget = self.spinBox_vBitrate
+ aBitrateWidget = self.spinBox_aBitrate
+ aCodecWidget = self.comboBox_audioCodec
currentVideoCodec = vCodecWidget.currentIndex()
currentVideoCodec = vCodecWidget.itemText(currentVideoCodec)
currentVideoBitrate = vBitrateWidget.value()
@@ -535,7 +546,7 @@ class MainWindow(QtWidgets.QMainWindow):
if os.path.exists(self.autosavePath):
os.remove(self.autosavePath)
elif force or time.time() - self.lastAutosave >= self.autosaveCooldown:
- self.core.createProjectFile(self.autosavePath, self.window)
+ self.core.createProjectFile(self.autosavePath, self)
self.lastAutosave = time.time()
if len(self.autosaveTimes) >= 5:
# Do some math to reduce autosave spam. This gives a smooth
@@ -588,25 +599,25 @@ class MainWindow(QtWidgets.QMainWindow):
inputDir = self.settings.value("inputDir", os.path.expanduser("~"))
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
- self.window, "Open Audio File",
+ self, "Open Audio File",
inputDir, "Audio Files (%s)" % " ".join(Core.audioFormats))
if fileName:
self.settings.setValue("inputDir", os.path.dirname(fileName))
- self.window.lineEdit_audioFile.setText(fileName)
+ self.lineEdit_audioFile.setText(fileName)
def openOutputFileDialog(self):
outputDir = self.settings.value("outputDir", os.path.expanduser("~"))
fileName, _ = QtWidgets.QFileDialog.getSaveFileName(
- self.window, "Set Output Video File",
+ self, "Set Output Video File",
outputDir,
"Video Files (%s);; All Files (*)" % " ".join(
Core.videoFormats))
if fileName:
self.settings.setValue("outputDir", os.path.dirname(fileName))
- self.window.lineEdit_outputFile.setText(fileName)
+ self.lineEdit_outputFile.setText(fileName)
def stopVideo(self):
log.info('Export cancelled')
@@ -615,8 +626,8 @@ class MainWindow(QtWidgets.QMainWindow):
def createAudioVisualisation(self):
# create output video if mandatory settings are filled in
- audioFile = self.window.lineEdit_audioFile.text()
- outputPath = self.window.lineEdit_outputFile.text()
+ audioFile = self.lineEdit_audioFile.text()
+ outputPath = self.lineEdit_outputFile.text()
if audioFile and outputPath and self.core.selectedComponents:
if not os.path.dirname(outputPath):
@@ -670,62 +681,62 @@ class MainWindow(QtWidgets.QMainWindow):
def changeEncodingStatus(self, status):
self.encoding = status
if status:
- self.window.pushButton_createVideo.setEnabled(False)
- self.window.pushButton_Cancel.setEnabled(True)
- self.window.comboBox_resolution.setEnabled(False)
- self.window.stackedWidget.setEnabled(False)
- self.window.tab_encoderSettings.setEnabled(False)
- self.window.label_audioFile.setEnabled(False)
- self.window.toolButton_selectAudioFile.setEnabled(False)
- self.window.label_outputFile.setEnabled(False)
- self.window.toolButton_selectOutputFile.setEnabled(False)
- self.window.lineEdit_audioFile.setEnabled(False)
- self.window.lineEdit_outputFile.setEnabled(False)
- self.window.pushButton_addComponent.setEnabled(False)
- self.window.pushButton_removeComponent.setEnabled(False)
- self.window.pushButton_listMoveDown.setEnabled(False)
- self.window.pushButton_listMoveUp.setEnabled(False)
- self.window.menuButton_newProject.setEnabled(False)
- self.window.menuButton_openProject.setEnabled(False)
+ self.pushButton_createVideo.setEnabled(False)
+ self.pushButton_Cancel.setEnabled(True)
+ self.comboBox_resolution.setEnabled(False)
+ self.stackedWidget.setEnabled(False)
+ self.tab_encoderSettings.setEnabled(False)
+ self.label_audioFile.setEnabled(False)
+ self.toolButton_selectAudioFile.setEnabled(False)
+ self.label_outputFile.setEnabled(False)
+ self.toolButton_selectOutputFile.setEnabled(False)
+ self.lineEdit_audioFile.setEnabled(False)
+ self.lineEdit_outputFile.setEnabled(False)
+ self.pushButton_addComponent.setEnabled(False)
+ self.pushButton_removeComponent.setEnabled(False)
+ self.pushButton_listMoveDown.setEnabled(False)
+ self.pushButton_listMoveUp.setEnabled(False)
+ self.menuButton_newProject.setEnabled(False)
+ self.menuButton_openProject.setEnabled(False)
if sys.platform == 'darwin':
- self.window.progressLabel.setHidden(False)
+ self.progressLabel.setHidden(False)
else:
- self.window.listWidget_componentList.setEnabled(False)
+ self.listWidget_componentList.setEnabled(False)
else:
- self.window.pushButton_createVideo.setEnabled(True)
- self.window.pushButton_Cancel.setEnabled(False)
- self.window.comboBox_resolution.setEnabled(True)
- self.window.stackedWidget.setEnabled(True)
- self.window.tab_encoderSettings.setEnabled(True)
- self.window.label_audioFile.setEnabled(True)
- self.window.toolButton_selectAudioFile.setEnabled(True)
- self.window.lineEdit_audioFile.setEnabled(True)
- self.window.label_outputFile.setEnabled(True)
- self.window.toolButton_selectOutputFile.setEnabled(True)
- self.window.lineEdit_outputFile.setEnabled(True)
- self.window.pushButton_addComponent.setEnabled(True)
- self.window.pushButton_removeComponent.setEnabled(True)
- self.window.pushButton_listMoveDown.setEnabled(True)
- self.window.pushButton_listMoveUp.setEnabled(True)
- self.window.menuButton_newProject.setEnabled(True)
- self.window.menuButton_openProject.setEnabled(True)
- self.window.listWidget_componentList.setEnabled(True)
- self.window.progressLabel.setHidden(True)
+ self.pushButton_createVideo.setEnabled(True)
+ self.pushButton_Cancel.setEnabled(False)
+ self.comboBox_resolution.setEnabled(True)
+ self.stackedWidget.setEnabled(True)
+ self.tab_encoderSettings.setEnabled(True)
+ self.label_audioFile.setEnabled(True)
+ self.toolButton_selectAudioFile.setEnabled(True)
+ self.lineEdit_audioFile.setEnabled(True)
+ self.label_outputFile.setEnabled(True)
+ self.toolButton_selectOutputFile.setEnabled(True)
+ self.lineEdit_outputFile.setEnabled(True)
+ self.pushButton_addComponent.setEnabled(True)
+ self.pushButton_removeComponent.setEnabled(True)
+ self.pushButton_listMoveDown.setEnabled(True)
+ self.pushButton_listMoveUp.setEnabled(True)
+ self.menuButton_newProject.setEnabled(True)
+ self.menuButton_openProject.setEnabled(True)
+ self.listWidget_componentList.setEnabled(True)
+ self.progressLabel.setHidden(True)
self.drawPreview(True)
@QtCore.pyqtSlot(int)
def progressBarUpdated(self, value):
- self.window.progressBar_createVideo.setValue(value)
+ self.progressBar_createVideo.setValue(value)
@QtCore.pyqtSlot(str)
def progressBarSetText(self, value):
if sys.platform == 'darwin':
- self.window.progressLabel.setText(value)
+ self.progressLabel.setText(value)
else:
- self.window.progressBar_createVideo.setFormat(value)
+ self.progressBar_createVideo.setFormat(value)
def updateResolution(self):
- resIndex = int(self.window.comboBox_resolution.currentIndex())
+ resIndex = int(self.comboBox_resolution.currentIndex())
res = Core.resolutions[resIndex].split('x')
changed = res[0] != self.settings.value("outputWidth")
self.settings.setValue('outputWidth', res[0])
@@ -750,7 +761,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.previewWindow.changePixmap(image)
def showUndoStack(self):
- dialog = QtWidgets.QDialog(self.window)
+ dialog = QtWidgets.QDialog(self)
undoView = QtWidgets.QUndoView(self.undoStack)
layout = QtWidgets.QVBoxLayout()
layout.addWidget(undoView)
@@ -761,8 +772,8 @@ class MainWindow(QtWidgets.QMainWindow):
from textwrap import wrap
from ..toolkit.ffmpeg import createFfmpegCommand
command = createFfmpegCommand(
- self.window.lineEdit_audioFile.text(),
- self.window.lineEdit_outputFile.text(),
+ self.lineEdit_audioFile.text(),
+ self.lineEdit_outputFile.text(),
self.core.selectedComponents
)
command = " ".join(command)
@@ -779,8 +790,8 @@ class MainWindow(QtWidgets.QMainWindow):
def insertComponent(self, index):
'''Triggered by Core to finish initializing a new component.'''
- componentList = self.window.listWidget_componentList
- stackedWidget = self.window.stackedWidget
+ componentList = self.listWidget_componentList
+ stackedWidget = self.stackedWidget
componentList.insertItem(
index,
@@ -798,15 +809,15 @@ class MainWindow(QtWidgets.QMainWindow):
return index
def removeComponent(self):
- componentList = self.window.listWidget_componentList
+ componentList = self.listWidget_componentList
selected = componentList.selectedItems()
if selected:
action = RemoveComponent(self, selected)
self.undoStack.push(action)
def _removeComponent(self, index):
- stackedWidget = self.window.stackedWidget
- componentList = self.window.listWidget_componentList
+ stackedWidget = self.stackedWidget
+ componentList = self.listWidget_componentList
stackedWidget.removeWidget(self.pages[index])
componentList.takeItem(index)
self.core.removeComponent(index)
@@ -817,7 +828,7 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def moveComponent(self, change):
'''Moves a component relatively from its current position'''
- componentList = self.window.listWidget_componentList
+ componentList = self.listWidget_componentList
tag = change
if change == 'top':
change = -componentList.currentRow()
@@ -837,7 +848,7 @@ class MainWindow(QtWidgets.QMainWindow):
Given a QPos, returns the component index under the mouse cursor
or -1 if no component is there.
'''
- componentList = self.window.listWidget_componentList
+ componentList = self.listWidget_componentList
modelIndexes = [
componentList.model().index(i)
@@ -859,7 +870,7 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def dragComponent(self, event):
'''Used as Qt drop event for the component listwidget'''
- componentList = self.window.listWidget_componentList
+ componentList = self.listWidget_componentList
mousePos = self.getComponentListMousePos(event.pos())
if mousePos > -1:
change = (componentList.currentRow() - mousePos) * -1
@@ -868,25 +879,25 @@ class MainWindow(QtWidgets.QMainWindow):
self.moveComponent(change)
def changeComponentWidget(self):
- selected = self.window.listWidget_componentList.selectedItems()
+ selected = self.listWidget_componentList.selectedItems()
if selected:
- index = self.window.listWidget_componentList.row(selected[0])
- self.window.stackedWidget.setCurrentIndex(index)
+ index = self.listWidget_componentList.row(selected[0])
+ self.stackedWidget.setCurrentIndex(index)
def openPresetManager(self):
'''Preset manager for importing, exporting, renaming, deleting'''
- self.presetManager.show()
+ self.presetManager.show_()
def clear(self):
'''Get a blank slate'''
self.core.clearComponents()
- self.window.listWidget_componentList.clear()
+ self.listWidget_componentList.clear()
for widget in self.pages:
- self.window.stackedWidget.removeWidget(widget)
+ self.stackedWidget.removeWidget(widget)
self.pages = []
for field in (
- self.window.lineEdit_audioFile,
- self.window.lineEdit_outputFile
+ self.lineEdit_audioFile,
+ self.lineEdit_outputFile
):
with blockSignals(field):
field.setText('')
@@ -906,7 +917,7 @@ class MainWindow(QtWidgets.QMainWindow):
def saveCurrentProject(self):
if self.currentProject:
- self.core.createProjectFile(self.currentProject, self.window)
+ self.core.createProjectFile(self.currentProject, self)
try:
os.remove(self.autosavePath)
except FileNotFoundError:
@@ -933,7 +944,7 @@ class MainWindow(QtWidgets.QMainWindow):
def openSaveProjectDialog(self):
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
- self.window, "Create Project File",
+ self, "Create Project File",
self.settings.value("projectDir"),
"Project Files (*.avp)")
if not filename:
@@ -943,13 +954,13 @@ 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.window)
+ self.core.createProjectFile(filename, self)
self.updateWindowTitle()
@disableWhenEncoding
def openOpenProjectDialog(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
- self.window, "Open Project File",
+ self, "Open Project File",
self.settings.value("projectDir"),
"Project Files (*.avp)")
self.openProject(filename)
@@ -973,7 +984,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.updateWindowTitle()
def showMessage(self, **kwargs):
- parent = kwargs['parent'] if 'parent' in kwargs else self.window
+ parent = kwargs['parent'] if 'parent' in kwargs else self
msg = QtWidgets.QMessageBox(parent)
msg.setModal(True)
msg.setText(kwargs['msg'])
@@ -995,8 +1006,8 @@ class MainWindow(QtWidgets.QMainWindow):
@disableWhenEncoding
def componentContextMenu(self, QPos):
'''Appears when right-clicking the component list'''
- componentList = self.window.listWidget_componentList
- self.menu = QMenu()
+ componentList = self.listWidget_componentList
+ self.menu = QtWidgets.QMenu()
parentPosition = componentList.mapToGlobal(QtCore.QPoint(0, 0))
index = self.getComponentListMousePos(QPos)
@@ -1013,7 +1024,7 @@ class MainWindow(QtWidgets.QMainWindow):
presets = self.presetManager.presets[
str(self.core.selectedComponents[index])
]
- self.presetSubmenu = QMenu("Open Preset")
+ self.presetSubmenu = QtWidgets.QMenu("Open Preset")
self.menu.addMenu(self.presetSubmenu)
for version, presetName in presets:
@@ -1033,7 +1044,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.menu.addSeparator()
# "Add Component" submenu
- self.submenu = QMenu("Add")
+ self.submenu = QtWidgets.QMenu("Add")
self.menu.addMenu(self.submenu)
insertCompAtTop = self.settings.value("pref_insertCompAtTop")
for i, comp in enumerate(self.core.modules):
diff --git a/src/gui/presetmanager.py b/src/gui/presetmanager.py
index 1e47a7f..9cf95b4 100644
--- a/src/gui/presetmanager.py
+++ b/src/gui/presetmanager.py
@@ -2,7 +2,7 @@
Preset manager object handles all interactions with presets, including
the context menu accessed from MainWindow.
'''
-from PyQt5 import QtCore, QtWidgets
+from PyQt5 import QtCore, QtWidgets, uic
import string
import os
import logging
@@ -16,8 +16,10 @@ log = logging.getLogger('AVP.Gui.PresetManager')
class PresetManager(QtWidgets.QDialog):
- def __init__(self, window, parent):
- super().__init__(parent.window)
+ def __init__(self, parent):
+ super().__init__()
+ uic.loadUi(
+ os.path.join(Core.wd, 'gui', 'presetmanager.ui'), self)
self.parent = parent
self.core = parent.core
self.settings = parent.settings
@@ -32,32 +34,31 @@ class PresetManager(QtWidgets.QDialog):
# window
self.lastFilter = '*'
self.presetRows = [] # list of (comp, vers, name) tuples
- self.window = window
- self.window.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
+ self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
# connect button signals
- self.window.pushButton_delete.clicked.connect(
+ self.pushButton_delete.clicked.connect(
self.openDeletePresetDialog
)
- self.window.pushButton_rename.clicked.connect(
+ self.pushButton_rename.clicked.connect(
self.openRenamePresetDialog
)
- self.window.pushButton_import.clicked.connect(
+ self.pushButton_import.clicked.connect(
self.openImportDialog
)
- self.window.pushButton_export.clicked.connect(
+ self.pushButton_export.clicked.connect(
self.openExportDialog
)
- self.window.pushButton_close.clicked.connect(
- self.window.close
+ self.pushButton_close.clicked.connect(
+ self.close
)
# create filter box and preset list
self.drawFilterList()
- self.window.comboBox_filter.currentIndexChanged.connect(
+ self.comboBox_filter.currentIndexChanged.connect(
lambda: self.drawPresetList(
- self.window.comboBox_filter.currentText(),
- self.window.lineEdit_search.text()
+ self.comboBox_filter.currentText(),
+ self.lineEdit_search.text()
)
)
@@ -65,23 +66,24 @@ class PresetManager(QtWidgets.QDialog):
self.autocomplete = QtCore.QStringListModel()
completer = QtWidgets.QCompleter()
completer.setModel(self.autocomplete)
- self.window.lineEdit_search.setCompleter(completer)
- self.window.lineEdit_search.textChanged.connect(
+ self.lineEdit_search.setCompleter(completer)
+ self.lineEdit_search.textChanged.connect(
lambda: self.drawPresetList(
- self.window.comboBox_filter.currentText(),
- self.window.lineEdit_search.text()
+ self.comboBox_filter.currentText(),
+ self.lineEdit_search.text()
)
)
self.drawPresetList('*')
- def show(self):
+ def show_(self):
'''Open a new preset manager window from the mainwindow'''
self.findPresets()
self.drawFilterList()
self.drawPresetList('*')
- self.window.show()
+ self.show()
def findPresets(self):
+ log.debug("Searching %s for presets", self.presetDir)
parseList = []
for dirpath, dirnames, filenames in os.walk(self.presetDir):
# anything without a subdirectory must be a preset folder
@@ -106,7 +108,7 @@ class PresetManager(QtWidgets.QDialog):
}
def drawPresetList(self, compFilter=None, presetFilter=''):
- self.window.listWidget_presets.clear()
+ self.listWidget_presets.clear()
if compFilter:
self.lastFilter = str(compFilter)
else:
@@ -118,7 +120,7 @@ class PresetManager(QtWidgets.QDialog):
continue
for vers, preset in presets:
if not presetFilter or presetFilter in preset:
- self.window.listWidget_presets.addItem(
+ self.listWidget_presets.addItem(
'%s: %s' % (component, preset)
)
self.presetRows.append((component, vers, preset))
@@ -127,22 +129,21 @@ class PresetManager(QtWidgets.QDialog):
self.autocomplete.setStringList(presetNames)
def drawFilterList(self):
- self.window.comboBox_filter.clear()
- self.window.comboBox_filter.addItem('*')
+ self.comboBox_filter.clear()
+ self.comboBox_filter.addItem('*')
for component in self.presets:
- self.window.comboBox_filter.addItem(component)
+ self.comboBox_filter.addItem(component)
def clearPreset(self, compI=None):
'''Functions on mainwindow level from the context menu'''
- compI = self.parent.window.listWidget_componentList.currentRow()
+ compI = self.parent.listWidget_componentList.currentRow()
action = ClearPreset(self.parent, compI)
self.parent.undoStack.push(action)
def openSavePresetDialog(self):
'''Functions on mainwindow level from the context menu'''
- window = self.parent.window
selectedComponents = self.core.selectedComponents
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
if componentList.currentRow() == -1:
return
@@ -150,7 +151,7 @@ class PresetManager(QtWidgets.QDialog):
index = componentList.currentRow()
currentPreset = selectedComponents[index].currentPreset
newName, OK = QtWidgets.QInputDialog.getText(
- self.parent.window,
+ self.parent,
'Audio Visualizer',
'New Preset Name:',
QtWidgets.QLineEdit.Normal,
@@ -158,7 +159,7 @@ class PresetManager(QtWidgets.QDialog):
)
if OK:
if badName(newName):
- self.warnMessage(self.parent.window)
+ self.warnMessage(self.parent)
continue
if newName:
if index != -1:
@@ -170,7 +171,7 @@ class PresetManager(QtWidgets.QDialog):
vers = selectedComponents[index].version
self.createNewPreset(
componentName, vers, newName,
- saveValueStore, window=self.parent.window)
+ saveValueStore, window=self.parent)
self.findPresets()
self.drawPresetList()
self.openPreset(newName, index)
@@ -185,8 +186,7 @@ class PresetManager(QtWidgets.QDialog):
def presetExists(self, path, **kwargs):
if os.path.exists(path):
- window = self.window \
- if 'window' not in kwargs else kwargs['window']
+ window = kwargs.get("window", self)
ch = self.parent.showMessage(
msg="%s already exists! Overwrite it?" %
os.path.basename(path),
@@ -200,7 +200,7 @@ class PresetManager(QtWidgets.QDialog):
return False
def openPreset(self, presetName, compPos=None):
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
index = compPos if compPos is not None else componentList.currentRow()
if index == -1:
return
@@ -228,7 +228,7 @@ class PresetManager(QtWidgets.QDialog):
msg='Really delete %s?' % name,
showCancel=True,
icon='Warning',
- parent=self.window
+ parent=self
)
if not ch:
return
@@ -242,15 +242,15 @@ class PresetManager(QtWidgets.QDialog):
self.parent.showMessage(
msg='Preset names must contain only letters, '
'numbers, and spaces.',
- parent=window if window else self.window)
+ parent=window if window else self)
def getPresetRow(self):
- row = self.window.listWidget_presets.currentRow()
+ row = self.listWidget_presets.currentRow()
if row > -1:
return row
# check if component selected in MainWindow has preset loaded
- componentList = self.parent.window.listWidget_componentList
+ componentList = self.parent.listWidget_componentList
compIndex = componentList.currentRow()
if compIndex == -1:
return compIndex
@@ -273,14 +273,14 @@ class PresetManager(QtWidgets.QDialog):
return index
def openRenamePresetDialog(self):
- presetList = self.window.listWidget_presets
+ presetList = self.listWidget_presets
index = self.getPresetRow()
if index == -1:
return
while True:
newName, OK = QtWidgets.QInputDialog.getText(
- self.window,
+ self,
'Preset Manager',
'Rename Preset:',
QtWidgets.QLineEdit.Normal,
@@ -319,7 +319,7 @@ class PresetManager(QtWidgets.QDialog):
def openImportDialog(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
- self.window, "Import Preset File",
+ self, "Import Preset File",
self.settings.value("presetDir"),
"Preset Files (*.avl)")
if filename:
@@ -345,7 +345,7 @@ class PresetManager(QtWidgets.QDialog):
if index == -1:
return
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
- self.window, "Export Preset",
+ self, "Export Preset",
self.settings.value("presetDir"),
"Preset Files (*.avl)")
if filename:
@@ -353,9 +353,9 @@ class PresetManager(QtWidgets.QDialog):
if not self.core.exportPreset(filename, comp, vers, name):
self.parent.showMessage(
msg='Couldn\'t export %s.' % filename,
- parent=self.window
+ parent=self
)
self.settings.setValue("presetDir", os.path.dirname(filename))
def clearPresetListSelection(self):
- self.window.listWidget_presets.setCurrentRow(-1)
+ self.listWidget_presets.setCurrentRow(-1)
diff --git a/src/gui/preview_win.py b/src/gui/preview_win.py
index 426ff66..d910456 100644
--- a/src/gui/preview_win.py
+++ b/src/gui/preview_win.py
@@ -37,7 +37,7 @@ class PreviewWindow(QtWidgets.QLabel):
if self.parent.encoding:
return
- i = self.parent.window.listWidget_componentList.currentRow()
+ i = self.parent.listWidget_componentList.currentRow()
if i >= 0:
component = self.parent.core.selectedComponents[i]
if not hasattr(component, 'previewClickEvent'):
diff --git a/src/main.py b/src/main.py
index ec4b8bc..709e5e7 100644
--- a/src/main.py
+++ b/src/main.py
@@ -42,21 +42,9 @@ def main():
if mode == 'GUI':
from .gui.mainwindow import MainWindow
- window = uic.loadUi(os.path.join(wd, "gui", "mainwindow.ui"))
- desc = QtWidgets.QDesktopWidget()
- dpi = desc.physicalDpiX()
- log.info("Detected screen DPI: %s", dpi)
-
- window.resize(
- int(window.width() *
- (dpi / 96)),
- int(window.height() *
- (dpi / 96))
- )
-
- main = MainWindow(window, proj)
- log.debug("Finished creating main window")
- window.raise_()
+ mainWindow = MainWindow(proj)
+ log.debug("Finished creating MainWindow")
+ mainWindow.raise_()
sys.exit(app.exec_())
--
cgit v1.2.3