Merge branch 'component-backgrounds' of github.com:IamDH4/audio-visualizer-python into feature-newgui
This commit is contained in:
commit
4920fcc034
BIN
background.jpg
BIN
background.jpg
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
|
@ -8,6 +8,13 @@ class Component:
|
||||||
# change this number to identify new versions of a component
|
# change this number to identify new versions of a component
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
# make sure your component responds to these variables in frameRender()
|
||||||
|
self.canceled = True
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.canceled = False
|
||||||
|
|
||||||
def preFrameRender(self, **kwargs):
|
def preFrameRender(self, **kwargs):
|
||||||
for var, value in kwargs.items():
|
for var, value in kwargs.items():
|
||||||
exec('self.%s = value' % var)
|
exec('self.%s = value' % var)
|
||||||
|
@ -66,4 +73,10 @@ class Component:
|
||||||
|
|
||||||
def savePreset(self):
|
def savePreset(self):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.canceled = True
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.canceled = False
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from PyQt4 import uic, QtGui, QtCore
|
||||||
|
from PyQt4.QtGui import QColor
|
||||||
|
import os
|
||||||
|
from . import __base__
|
||||||
|
|
||||||
|
class Component(__base__.Component):
|
||||||
|
'''Color'''
|
||||||
|
def widget(self, parent):
|
||||||
|
self.parent = parent
|
||||||
|
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'color.ui'))
|
||||||
|
|
||||||
|
self.color1 = (0,0,0)
|
||||||
|
self.color2 = (133,133,133)
|
||||||
|
self.x = 0
|
||||||
|
self.y = 0
|
||||||
|
|
||||||
|
page.lineEdit_color1.setText('%s,%s,%s' % self.color1)
|
||||||
|
page.lineEdit_color2.setText('%s,%s,%s' % self.color2)
|
||||||
|
page.pushButton_color1.clicked.connect(lambda: self.pickColor(1))
|
||||||
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*self.color1).name()
|
||||||
|
page.pushButton_color1.setStyleSheet(btnStyle)
|
||||||
|
page.pushButton_color2.clicked.connect(lambda: self.pickColor(2))
|
||||||
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*self.color2).name()
|
||||||
|
page.pushButton_color2.setStyleSheet(btnStyle)
|
||||||
|
# disable color #2 until non-default 'fill' option gets changed
|
||||||
|
page.lineEdit_color2.setDisabled(True)
|
||||||
|
page.pushButton_color2.setDisabled(True)
|
||||||
|
page.spinBox_x.setValue(self.x)
|
||||||
|
page.spinBox_x.setValue(self.y)
|
||||||
|
|
||||||
|
page.lineEdit_color1.textChanged.connect(self.update)
|
||||||
|
page.lineEdit_color2.textChanged.connect(self.update)
|
||||||
|
page.spinBox_x.valueChanged.connect(self.update)
|
||||||
|
page.spinBox_y.valueChanged.connect(self.update)
|
||||||
|
self.page = page
|
||||||
|
return page
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.color1 = self.RGBFromString(self.page.lineEdit_color1.text())
|
||||||
|
self.color2 = self.RGBFromString(self.page.lineEdit_color2.text())
|
||||||
|
self.x = self.page.spinBox_x.value()
|
||||||
|
self.y = self.page.spinBox_y.value()
|
||||||
|
self.parent.drawPreview()
|
||||||
|
|
||||||
|
def previewRender(self, previewWorker):
|
||||||
|
width = int(previewWorker.core.settings.value('outputWidth'))
|
||||||
|
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||||
|
return self.drawFrame(width, height)
|
||||||
|
|
||||||
|
def preFrameRender(self, **kwargs):
|
||||||
|
super().preFrameRender(**kwargs)
|
||||||
|
return ['static']
|
||||||
|
|
||||||
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||||
|
width = int(self.worker.core.settings.value('outputWidth'))
|
||||||
|
height = int(self.worker.core.settings.value('outputHeight'))
|
||||||
|
return self.drawFrame(width, height)
|
||||||
|
|
||||||
|
def drawFrame(self, width, height):
|
||||||
|
r,g,b = self.color1
|
||||||
|
return Image.new("RGBA", (width, height), (r, g, b, 255))
|
||||||
|
|
||||||
|
def loadPreset(self, pr):
|
||||||
|
self.page.lineEdit_color1.setText('%s,%s,%s' % pr['color1'])
|
||||||
|
self.page.lineEdit_color2.setText('%s,%s,%s' % pr['color2'])
|
||||||
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*pr['color1']).name()
|
||||||
|
self.page.pushButton_color1.setStyleSheet(btnStyle)
|
||||||
|
btnStyle = "QPushButton { background-color : %s; outline: none; }" % QColor(*pr['color2']).name()
|
||||||
|
self.page.pushButton_color2.setStyleSheet(btnStyle)
|
||||||
|
|
||||||
|
def savePreset(self):
|
||||||
|
return {
|
||||||
|
'color1' : self.color1,
|
||||||
|
'color2' : self.color2,
|
||||||
|
}
|
||||||
|
|
||||||
|
def pickColor(self, num):
|
||||||
|
RGBstring, btnStyle = super().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)
|
|
@ -0,0 +1,306 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>586</width>
|
||||||
|
<height>197</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_textColor">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>31</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color #1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_color1">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="MaximumSize" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_color1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_textColor_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>31</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Color #2</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_color2">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="MaximumSize" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_color2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_textLayout">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Fill </string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox_fill"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_6">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_xTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>X</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_x">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_7">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_yTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Y</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_y">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,64 @@
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from PyQt4 import uic, QtGui, QtCore
|
||||||
|
import os
|
||||||
|
from . import __base__
|
||||||
|
|
||||||
|
class Component(__base__.Component):
|
||||||
|
'''Image'''
|
||||||
|
def widget(self, parent):
|
||||||
|
self.parent = parent
|
||||||
|
self.settings = parent.settings
|
||||||
|
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'image.ui'))
|
||||||
|
self.imagePath = ''
|
||||||
|
self.x = 0
|
||||||
|
self.y = 0
|
||||||
|
|
||||||
|
page.lineEdit_image.textChanged.connect(self.update)
|
||||||
|
page.pushButton_image.clicked.connect(self.pickImage)
|
||||||
|
|
||||||
|
self.page = page
|
||||||
|
return page
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.imagePath = self.page.lineEdit_image.text()
|
||||||
|
self.parent.drawPreview()
|
||||||
|
|
||||||
|
def previewRender(self, previewWorker):
|
||||||
|
width = int(previewWorker.core.settings.value('outputWidth'))
|
||||||
|
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||||
|
return self.drawFrame(width, height)
|
||||||
|
|
||||||
|
def preFrameRender(self, **kwargs):
|
||||||
|
super().preFrameRender(**kwargs)
|
||||||
|
return ['static']
|
||||||
|
|
||||||
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||||
|
width = int(self.worker.core.settings.value('outputWidth'))
|
||||||
|
height = int(self.worker.core.settings.value('outputHeight'))
|
||||||
|
return self.drawFrame(width, height)
|
||||||
|
|
||||||
|
def drawFrame(self, width, height):
|
||||||
|
frame = Image.new("RGBA", (width, height), (0,0,0,0))
|
||||||
|
if self.imagePath and os.path.exists(self.imagePath):
|
||||||
|
image = Image.open(self.imagePath)
|
||||||
|
if image.size != (width, height):
|
||||||
|
image = image.resize((width, height), Image.ANTIALIAS)
|
||||||
|
frame.paste(image)
|
||||||
|
return frame
|
||||||
|
|
||||||
|
def loadPreset(self, pr):
|
||||||
|
self.page.lineEdit_image.setText(pr['image'])
|
||||||
|
|
||||||
|
def savePreset(self):
|
||||||
|
return {
|
||||||
|
'image' : self.imagePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
def pickImage(self):
|
||||||
|
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
|
||||||
|
filename = QtGui.QFileDialog.getOpenFileName(self.page,
|
||||||
|
"Choose Image", imgDir, "Image Files (*.jpg *.png)")
|
||||||
|
if filename:
|
||||||
|
self.settings.setValue("backgroundDir", os.path.dirname(filename))
|
||||||
|
self.page.lineEdit_image.setText(filename)
|
||||||
|
self.update()
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>586</width>
|
||||||
|
<height>197</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_textColor">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>31</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Image</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_image">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_image">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="MaximumSize" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_xTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>X</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_x">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_yTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Y</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_y">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -58,6 +58,8 @@ class Component(__base__.Component):
|
||||||
self.smoothConstantUp = 0.8
|
self.smoothConstantUp = 0.8
|
||||||
self.lastSpectrum = None
|
self.lastSpectrum = None
|
||||||
self.spectrumArray = {}
|
self.spectrumArray = {}
|
||||||
|
self.width = int(self.worker.core.settings.value('outputWidth'))
|
||||||
|
self.height = int(self.worker.core.settings.value('outputHeight'))
|
||||||
|
|
||||||
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
||||||
if self.canceled:
|
if self.canceled:
|
||||||
|
@ -73,11 +75,8 @@ class Component(__base__.Component):
|
||||||
self.progressBarSetText.emit(pStr)
|
self.progressBarSetText.emit(pStr)
|
||||||
self.progressBarUpdate.emit(int(progress))
|
self.progressBarUpdate.emit(int(progress))
|
||||||
|
|
||||||
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||||
def frameRender(self, moduleNo, frameNo):
|
return self.drawBars(self.width, self.height, self.spectrumArray[arrayNo], self.visColor, self.layout)
|
||||||
width = int(self.worker.core.settings.value('outputWidth'))
|
|
||||||
height = int(self.worker.core.settings.value('outputHeight'))
|
|
||||||
return self.drawBars(width, height, self.spectrumArray[frameNo], self.visColor, self.layout)
|
|
||||||
|
|
||||||
def pickColor(self):
|
def pickColor(self):
|
||||||
RGBstring, btnStyle = super().pickColor()
|
RGBstring, btnStyle = super().pickColor()
|
||||||
|
@ -154,12 +153,3 @@ class Component(__base__.Component):
|
||||||
|
|
||||||
return im
|
return im
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
self.canceled = True
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.canceled = False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ class Component(__base__.Component):
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.textColor = (255,255,255)
|
self.textColor = (255,255,255)
|
||||||
self.title = 'Text'
|
self.title = 'Text'
|
||||||
self.titleFont = None
|
|
||||||
self.alignment = 1
|
self.alignment = 1
|
||||||
self.fontSize = height / 13.5
|
self.fontSize = height / 13.5
|
||||||
self.xPosition = width / 2
|
self.xPosition = width / 2
|
||||||
|
@ -35,8 +34,6 @@ class Component(__base__.Component):
|
||||||
page.pushButton_textColor.setStyleSheet(btnStyle)
|
page.pushButton_textColor.setStyleSheet(btnStyle)
|
||||||
|
|
||||||
page.lineEdit_title.setText(self.title)
|
page.lineEdit_title.setText(self.title)
|
||||||
#if self.titleFont:
|
|
||||||
# page.fontComboBox_titleFont.setCurrentFont(QFont(self.titleFont))
|
|
||||||
page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
|
page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
|
||||||
page.spinBox_fontSize.setValue(int(self.fontSize))
|
page.spinBox_fontSize.setValue(int(self.fontSize))
|
||||||
page.spinBox_xTextAlign.setValue(int(self.xPosition))
|
page.spinBox_xTextAlign.setValue(int(self.xPosition))
|
||||||
|
@ -109,7 +106,7 @@ class Component(__base__.Component):
|
||||||
super().preFrameRender(**kwargs)
|
super().preFrameRender(**kwargs)
|
||||||
return ['static']
|
return ['static']
|
||||||
|
|
||||||
def frameRender(self, moduleNo, frameNo):
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||||
width = int(self.worker.core.settings.value('outputWidth'))
|
width = int(self.worker.core.settings.value('outputWidth'))
|
||||||
height = int(self.worker.core.settings.value('outputHeight'))
|
height = int(self.worker.core.settings.value('outputHeight'))
|
||||||
return self.addText(width, height)
|
return self.addText(width, height)
|
||||||
|
@ -142,9 +139,3 @@ class Component(__base__.Component):
|
||||||
return
|
return
|
||||||
self.page.lineEdit_textColor.setText(RGBstring)
|
self.page.lineEdit_textColor.setText(RGBstring)
|
||||||
self.page.pushButton_textColor.setStyleSheet(btnStyle)
|
self.page.pushButton_textColor.setStyleSheet(btnStyle)
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
self.canceled = True
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
self.canceled = False
|
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
from PIL import Image, ImageDraw
|
||||||
|
from PyQt4 import uic, QtGui, QtCore
|
||||||
|
import os, subprocess, threading
|
||||||
|
from queue import PriorityQueue
|
||||||
|
from . import __base__
|
||||||
|
|
||||||
|
class Video:
|
||||||
|
'''Video Component Frame-Fetcher'''
|
||||||
|
def __init__(self, ffmpeg, videoPath, width, height, frameRate, chunkSize, parent, loopVideo):
|
||||||
|
self.parent = parent
|
||||||
|
self.chunkSize = chunkSize
|
||||||
|
self.size = (width, height)
|
||||||
|
self.frameNo = -1
|
||||||
|
self.currentFrame = 'None'
|
||||||
|
if loopVideo:
|
||||||
|
self.loopValue = '-1'
|
||||||
|
else:
|
||||||
|
self.loopValue = '0'
|
||||||
|
self.command = [
|
||||||
|
ffmpeg,
|
||||||
|
'-thread_queue_size', '512',
|
||||||
|
'-r', frameRate,
|
||||||
|
'-stream_loop', self.loopValue,
|
||||||
|
'-i', videoPath,
|
||||||
|
'-f', 'image2pipe',
|
||||||
|
'-pix_fmt', 'rgba',
|
||||||
|
'-filter:v', 'scale='+str(width)+':'+str(height),
|
||||||
|
'-vcodec', 'rawvideo', '-',
|
||||||
|
]
|
||||||
|
|
||||||
|
self.frameBuffer = PriorityQueue()
|
||||||
|
self.frameBuffer.maxsize = int(frameRate)
|
||||||
|
self.finishedFrames = {}
|
||||||
|
|
||||||
|
self.thread = threading.Thread(target=self.fillBuffer, name=self.__doc__)
|
||||||
|
self.thread.daemon = True
|
||||||
|
self.thread.start()
|
||||||
|
|
||||||
|
def frame(self, num):
|
||||||
|
while True:
|
||||||
|
if num in self.finishedFrames:
|
||||||
|
image = self.finishedFrames.pop(num)
|
||||||
|
return Image.frombytes('RGBA', self.size, image)
|
||||||
|
i, image = self.frameBuffer.get()
|
||||||
|
self.finishedFrames[i] = image
|
||||||
|
self.frameBuffer.task_done()
|
||||||
|
|
||||||
|
def fillBuffer(self):
|
||||||
|
self.pipe = subprocess.Popen(self.command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, bufsize=10**8)
|
||||||
|
while True:
|
||||||
|
if self.parent.canceled:
|
||||||
|
break
|
||||||
|
self.frameNo += 1
|
||||||
|
|
||||||
|
# If we run out of frames, use the last good frame and loop.
|
||||||
|
if len(self.currentFrame) == 0:
|
||||||
|
self.frameBuffer.put((self.frameNo-1, self.lastFrame))
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.currentFrame = self.pipe.stdout.read(self.chunkSize)
|
||||||
|
#print('creating frame #%s' % str(self.frameNo))
|
||||||
|
if len(self.currentFrame) != 0:
|
||||||
|
self.frameBuffer.put((self.frameNo, self.currentFrame))
|
||||||
|
self.lastFrame = self.currentFrame
|
||||||
|
|
||||||
|
class Component(__base__.Component):
|
||||||
|
'''Video'''
|
||||||
|
def widget(self, parent):
|
||||||
|
self.parent = parent
|
||||||
|
self.settings = parent.settings
|
||||||
|
page = uic.loadUi(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'video.ui'))
|
||||||
|
self.videoPath = ''
|
||||||
|
self.x = 0
|
||||||
|
self.y = 0
|
||||||
|
self.loopVideo = False
|
||||||
|
|
||||||
|
page.lineEdit_video.textChanged.connect(self.update)
|
||||||
|
page.pushButton_video.clicked.connect(self.pickVideo)
|
||||||
|
page.checkBox_loop.stateChanged.connect(self.update)
|
||||||
|
|
||||||
|
self.page = page
|
||||||
|
return page
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.videoPath = self.page.lineEdit_video.text()
|
||||||
|
self.loopVideo = self.page.checkBox_loop.isChecked()
|
||||||
|
self.parent.drawPreview()
|
||||||
|
|
||||||
|
def previewRender(self, previewWorker):
|
||||||
|
width = int(previewWorker.core.settings.value('outputWidth'))
|
||||||
|
height = int(previewWorker.core.settings.value('outputHeight'))
|
||||||
|
self.chunkSize = 4*width*height
|
||||||
|
return self.getPreviewFrame(width, height)
|
||||||
|
|
||||||
|
def preFrameRender(self, **kwargs):
|
||||||
|
super().preFrameRender(**kwargs)
|
||||||
|
width = int(self.worker.core.settings.value('outputWidth'))
|
||||||
|
height = int(self.worker.core.settings.value('outputHeight'))
|
||||||
|
self.chunkSize = 4*width*height
|
||||||
|
self.video = Video(self.parent.core.FFMPEG_BIN, self.videoPath,
|
||||||
|
width, height, self.settings.value("outputFrameRate"),
|
||||||
|
self.chunkSize, self.parent, self.loopVideo)
|
||||||
|
|
||||||
|
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||||
|
return self.video.frame(frameNo)
|
||||||
|
|
||||||
|
def loadPreset(self, pr):
|
||||||
|
self.page.lineEdit_video.setText(pr['video'])
|
||||||
|
|
||||||
|
def savePreset(self):
|
||||||
|
return {
|
||||||
|
'video' : self.videoPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
def pickVideo(self):
|
||||||
|
imgDir = self.settings.value("backgroundDir", os.path.expanduser("~"))
|
||||||
|
filename = QtGui.QFileDialog.getOpenFileName(self.page,
|
||||||
|
"Choose Video", imgDir, "Video Files (*.mp4 *.mov)")
|
||||||
|
if filename:
|
||||||
|
self.settings.setValue("backgroundDir", os.path.dirname(filename))
|
||||||
|
self.page.lineEdit_video.setText(filename)
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def getPreviewFrame(self, width, height):
|
||||||
|
command = [
|
||||||
|
self.parent.core.FFMPEG_BIN,
|
||||||
|
'-thread_queue_size', '512',
|
||||||
|
'-i', self.videoPath,
|
||||||
|
'-f', 'image2pipe',
|
||||||
|
'-pix_fmt', 'rgba',
|
||||||
|
'-filter:v', 'scale='+str(width)+':'+str(height),
|
||||||
|
'-vcodec', 'rawvideo', '-',
|
||||||
|
'-ss', '90',
|
||||||
|
'-vframes', '1',
|
||||||
|
]
|
||||||
|
pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, bufsize=10**8)
|
||||||
|
byteFrame = pipe.stdout.read(self.chunkSize)
|
||||||
|
image = Image.frombytes('RGBA', (width, height), byteFrame)
|
||||||
|
pipe.stdout.close()
|
||||||
|
pipe.kill()
|
||||||
|
return image
|
|
@ -0,0 +1,224 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>586</width>
|
||||||
|
<height>197</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_textColor">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>31</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Video</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_video">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_video">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>1</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="MaximumSize" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>32</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_9">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_xTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>X</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_x_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_yTitleAlign">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Y</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBox_y">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBox_loop">
|
||||||
|
<property name="text">
|
||||||
|
<string>Loop</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_10">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>5</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
60
core.py
60
core.py
|
@ -13,11 +13,10 @@ from collections import OrderedDict
|
||||||
class Core():
|
class Core():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.lastBackgroundImage = ""
|
|
||||||
self._image = None
|
|
||||||
|
|
||||||
self.FFMPEG_BIN = self.findFfmpeg()
|
self.FFMPEG_BIN = self.findFfmpeg()
|
||||||
self.tempDir = None
|
self.tempDir = os.path.join(tempfile.gettempdir(), 'audio-visualizer-python-data')
|
||||||
|
if not os.path.exists(self.tempDir):
|
||||||
|
os.makedirs(self.tempDir)
|
||||||
atexit.register(self.deleteTempDir)
|
atexit.register(self.deleteTempDir)
|
||||||
|
|
||||||
def findFfmpeg(self):
|
def findFfmpeg(self):
|
||||||
|
@ -31,31 +30,6 @@ class Core():
|
||||||
except:
|
except:
|
||||||
return "avconv"
|
return "avconv"
|
||||||
|
|
||||||
def parseBaseImage(self, backgroundImage, preview=False):
|
|
||||||
''' determines if the base image is a single frame or list of frames '''
|
|
||||||
if backgroundImage == "":
|
|
||||||
return ['']
|
|
||||||
else:
|
|
||||||
_, bgExt = os.path.splitext(backgroundImage)
|
|
||||||
if not bgExt == '.mp4':
|
|
||||||
return [backgroundImage]
|
|
||||||
else:
|
|
||||||
return self.getVideoFrames(backgroundImage, preview)
|
|
||||||
|
|
||||||
def drawBaseImage(self, backgroundFile):
|
|
||||||
if backgroundFile == '':
|
|
||||||
im = Image.new("RGB", (int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))), "black")
|
|
||||||
else:
|
|
||||||
im = Image.open(backgroundFile)
|
|
||||||
|
|
||||||
if self._image == None or not self.lastBackgroundImage == backgroundFile:
|
|
||||||
self.lastBackgroundImage = backgroundFile
|
|
||||||
# resize if necessary
|
|
||||||
if not im.size == (int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))):
|
|
||||||
im = im.resize((int(self.settings.value('outputWidth')), int(self.settings.value('outputHeight'))), Image.ANTIALIAS)
|
|
||||||
|
|
||||||
return im
|
|
||||||
|
|
||||||
def readAudioFile(self, filename, parent):
|
def readAudioFile(self, filename, parent):
|
||||||
command = [ self.FFMPEG_BIN,
|
command = [ self.FFMPEG_BIN,
|
||||||
'-i', filename]
|
'-i', filename]
|
||||||
|
@ -121,30 +95,10 @@ class Core():
|
||||||
return completeAudioArray
|
return completeAudioArray
|
||||||
|
|
||||||
def deleteTempDir(self):
|
def deleteTempDir(self):
|
||||||
if self.tempDir and os.path.exists(self.tempDir):
|
try:
|
||||||
rmtree(self.tempDir)
|
rmtree(self.tempDir)
|
||||||
|
except FileNotFoundError:
|
||||||
def getVideoFrames(self, videoPath, firstOnly=False):
|
pass
|
||||||
self.tempDir = os.path.join(tempfile.gettempdir(), 'audio-visualizer-python-data')
|
|
||||||
# recreate the temporary directory so it is empty
|
|
||||||
self.deleteTempDir()
|
|
||||||
os.mkdir(self.tempDir)
|
|
||||||
if firstOnly:
|
|
||||||
filename = 'preview%s.jpg' % os.path.basename(videoPath).split('.', 1)[0]
|
|
||||||
options = '-ss 10 -vframes 1'
|
|
||||||
else:
|
|
||||||
filename = '$frame%05d.jpg'
|
|
||||||
options = ''
|
|
||||||
sp.call( \
|
|
||||||
'%s -i "%s" -y %s "%s"' % ( \
|
|
||||||
self.FFMPEG_BIN,
|
|
||||||
videoPath,
|
|
||||||
options,
|
|
||||||
os.path.join(self.tempDir, filename)
|
|
||||||
),
|
|
||||||
shell=True
|
|
||||||
)
|
|
||||||
return sorted([os.path.join(self.tempDir, f) for f in os.listdir(self.tempDir)])
|
|
||||||
|
|
||||||
def cancel(self):
|
def cancel(self):
|
||||||
self.canceled = True
|
self.canceled = True
|
||||||
|
@ -153,6 +107,6 @@ class Core():
|
||||||
self.canceled = False
|
self.canceled = False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sortedStringDict(dictionary):
|
def stringOrderedDict(dictionary):
|
||||||
sorted_ = OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
|
sorted_ = OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
|
||||||
return repr(sorted_)
|
return repr(sorted_)
|
||||||
|
|
61
main.py
61
main.py
|
@ -1,4 +1,4 @@
|
||||||
import sys, io, os, shutil, atexit, string, signal, filecmp
|
import sys, io, os, shutil, atexit, string, signal, filecmp, time
|
||||||
from os.path import expanduser
|
from os.path import expanduser
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
@ -133,9 +133,9 @@ class PreviewWindow(QtGui.QLabel):
|
||||||
|
|
||||||
class Main(QtCore.QObject):
|
class Main(QtCore.QObject):
|
||||||
|
|
||||||
newTask = QtCore.pyqtSignal(str, list)
|
newTask = QtCore.pyqtSignal(list)
|
||||||
processTask = QtCore.pyqtSignal()
|
processTask = QtCore.pyqtSignal()
|
||||||
videoTask = QtCore.pyqtSignal(str, str, str, list)
|
videoTask = QtCore.pyqtSignal(str, str, list)
|
||||||
|
|
||||||
def __init__(self, window):
|
def __init__(self, window):
|
||||||
QtCore.QObject.__init__(self)
|
QtCore.QObject.__init__(self)
|
||||||
|
@ -145,6 +145,7 @@ class Main(QtCore.QObject):
|
||||||
self.core = core.Core()
|
self.core = core.Core()
|
||||||
self.pages = []
|
self.pages = []
|
||||||
self.selectedComponents = []
|
self.selectedComponents = []
|
||||||
|
self.lastAutosave = time.time()
|
||||||
|
|
||||||
# create data directory, load/create settings
|
# create data directory, load/create settings
|
||||||
self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation)
|
self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation)
|
||||||
|
@ -172,14 +173,13 @@ class Main(QtCore.QObject):
|
||||||
|
|
||||||
# begin decorating the window and connecting events
|
# begin decorating the window and connecting events
|
||||||
window.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog)
|
window.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog)
|
||||||
window.toolButton_selectBackground.clicked.connect(self.openBackgroundFileDialog)
|
|
||||||
window.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog)
|
window.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog)
|
||||||
window.progressBar_createVideo.setValue(0)
|
window.progressBar_createVideo.setValue(0)
|
||||||
window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation)
|
window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation)
|
||||||
window.pushButton_Cancel.clicked.connect(self.stopVideo)
|
window.pushButton_Cancel.clicked.connect(self.stopVideo)
|
||||||
window.setWindowTitle("Audio Visualizer")
|
window.setWindowTitle("Audio Visualizer")
|
||||||
|
|
||||||
self.previewWindow = PreviewWindow(self, os.path.join(os.path.dirname(os.path.realpath(__file__)), "background.jpg"))
|
self.previewWindow = PreviewWindow(self, os.path.join(os.path.dirname(os.path.realpath(__file__)), "background.png"))
|
||||||
window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
|
window.verticalLayout_previewWrapper.addWidget(self.previewWindow)
|
||||||
|
|
||||||
self.modules = self.findComponents()
|
self.modules = self.findComponents()
|
||||||
|
@ -236,15 +236,17 @@ class Main(QtCore.QObject):
|
||||||
self.autosave()
|
self.autosave()
|
||||||
|
|
||||||
def autosave(self):
|
def autosave(self):
|
||||||
|
if time.time() - self.lastAutosave >= 1.0:
|
||||||
if os.path.exists(self.autosavePath):
|
if os.path.exists(self.autosavePath):
|
||||||
os.remove(self.autosavePath)
|
os.remove(self.autosavePath)
|
||||||
self.createProjectFile(self.autosavePath)
|
self.createProjectFile(self.autosavePath)
|
||||||
|
self.lastAutosave = time.time()
|
||||||
|
|
||||||
def openInputFileDialog(self):
|
def openInputFileDialog(self):
|
||||||
inputDir = self.settings.value("inputDir", expanduser("~"))
|
inputDir = self.settings.value("inputDir", expanduser("~"))
|
||||||
|
|
||||||
fileName = QtGui.QFileDialog.getOpenFileName(self.window,
|
fileName = QtGui.QFileDialog.getOpenFileName(self.window,
|
||||||
"Open Music File", inputDir, "Music Files (*.mp3 *.wav *.ogg *.flac)");
|
"Open Music File", inputDir, "Music Files (*.mp3 *.wav *.ogg *.fla *.aac)");
|
||||||
|
|
||||||
if not fileName == "":
|
if not fileName == "":
|
||||||
self.settings.setValue("inputDir", os.path.dirname(fileName))
|
self.settings.setValue("inputDir", os.path.dirname(fileName))
|
||||||
|
@ -254,23 +256,12 @@ class Main(QtCore.QObject):
|
||||||
outputDir = self.settings.value("outputDir", expanduser("~"))
|
outputDir = self.settings.value("outputDir", expanduser("~"))
|
||||||
|
|
||||||
fileName = QtGui.QFileDialog.getSaveFileName(self.window,
|
fileName = QtGui.QFileDialog.getSaveFileName(self.window,
|
||||||
"Set Output Video File", outputDir, "Video Files (*.mkv)");
|
"Set Output Video File", outputDir, "Video Files (*.mp4 *.mov *.mkv *.avi *.webm *.flv)");
|
||||||
|
|
||||||
if not fileName == "":
|
if not fileName == "":
|
||||||
self.settings.setValue("outputDir", os.path.dirname(fileName))
|
self.settings.setValue("outputDir", os.path.dirname(fileName))
|
||||||
self.window.lineEdit_outputFile.setText(fileName)
|
self.window.lineEdit_outputFile.setText(fileName)
|
||||||
|
|
||||||
def openBackgroundFileDialog(self):
|
|
||||||
backgroundDir = self.settings.value("backgroundDir", expanduser("~"))
|
|
||||||
|
|
||||||
fileName = QtGui.QFileDialog.getOpenFileName(self.window,
|
|
||||||
"Open Background Image", backgroundDir, "Image Files (*.jpg *.png);; Video Files (*.mp4)");
|
|
||||||
|
|
||||||
if not fileName == "":
|
|
||||||
self.settings.setValue("backgroundDir", os.path.dirname(fileName))
|
|
||||||
self.window.lineEdit_background.setText(fileName)
|
|
||||||
self.drawPreview()
|
|
||||||
|
|
||||||
def stopVideo(self):
|
def stopVideo(self):
|
||||||
print('stop')
|
print('stop')
|
||||||
self.videoWorker.cancel()
|
self.videoWorker.cancel()
|
||||||
|
@ -291,8 +282,7 @@ class Main(QtCore.QObject):
|
||||||
self.videoWorker.imageCreated.connect(self.showPreviewImage)
|
self.videoWorker.imageCreated.connect(self.showPreviewImage)
|
||||||
self.videoWorker.encoding.connect(self.changeEncodingStatus)
|
self.videoWorker.encoding.connect(self.changeEncodingStatus)
|
||||||
self.videoThread.start()
|
self.videoThread.start()
|
||||||
self.videoTask.emit(self.window.lineEdit_background.text(),
|
self.videoTask.emit(self.window.lineEdit_audioFile.text(),
|
||||||
self.window.lineEdit_audioFile.text(),
|
|
||||||
self.window.lineEdit_outputFile.text(),
|
self.window.lineEdit_outputFile.text(),
|
||||||
self.selectedComponents)
|
self.selectedComponents)
|
||||||
else:
|
else:
|
||||||
|
@ -323,10 +313,6 @@ class Main(QtCore.QObject):
|
||||||
self.window.pushButton_savePreset.setEnabled(False)
|
self.window.pushButton_savePreset.setEnabled(False)
|
||||||
self.window.pushButton_openProject.setEnabled(False)
|
self.window.pushButton_openProject.setEnabled(False)
|
||||||
self.window.listWidget_componentList.setEnabled(False)
|
self.window.listWidget_componentList.setEnabled(False)
|
||||||
|
|
||||||
self.window.label_background.setEnabled(False)
|
|
||||||
self.window.lineEdit_background.setEnabled(False)
|
|
||||||
self.window.toolButton_selectBackground.setEnabled(False)
|
|
||||||
else:
|
else:
|
||||||
self.window.pushButton_createVideo.setEnabled(True)
|
self.window.pushButton_createVideo.setEnabled(True)
|
||||||
self.window.pushButton_Cancel.setEnabled(False)
|
self.window.pushButton_Cancel.setEnabled(False)
|
||||||
|
@ -349,12 +335,6 @@ class Main(QtCore.QObject):
|
||||||
self.window.pushButton_openProject.setEnabled(True)
|
self.window.pushButton_openProject.setEnabled(True)
|
||||||
self.window.listWidget_componentList.setEnabled(True)
|
self.window.listWidget_componentList.setEnabled(True)
|
||||||
|
|
||||||
self.window.label_background.setEnabled(True)
|
|
||||||
self.window.lineEdit_background.setEnabled(True)
|
|
||||||
self.window.toolButton_selectBackground.setEnabled(True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def progressBarSetText(self, value):
|
def progressBarSetText(self, value):
|
||||||
self.window.progressBar_createVideo.setFormat(value)
|
self.window.progressBar_createVideo.setFormat(value)
|
||||||
|
|
||||||
|
@ -370,7 +350,7 @@ class Main(QtCore.QObject):
|
||||||
self.drawPreview()
|
self.drawPreview()
|
||||||
|
|
||||||
def drawPreview(self):
|
def drawPreview(self):
|
||||||
self.newTask.emit(self.window.lineEdit_background.text(), self.selectedComponents)
|
self.newTask.emit(self.selectedComponents)
|
||||||
# self.processTask.emit()
|
# self.processTask.emit()
|
||||||
self.autosave()
|
self.autosave()
|
||||||
|
|
||||||
|
@ -381,7 +361,7 @@ class Main(QtCore.QObject):
|
||||||
def findComponents():
|
def findComponents():
|
||||||
srcPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'components')
|
srcPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'components')
|
||||||
if os.path.exists(srcPath):
|
if os.path.exists(srcPath):
|
||||||
for f in os.listdir(srcPath):
|
for f in sorted(os.listdir(srcPath)):
|
||||||
name, ext = os.path.splitext(f)
|
name, ext = os.path.splitext(f)
|
||||||
if name.startswith("__"):
|
if name.startswith("__"):
|
||||||
continue
|
continue
|
||||||
|
@ -446,7 +426,7 @@ class Main(QtCore.QObject):
|
||||||
|
|
||||||
def moveComponentDown(self):
|
def moveComponentDown(self):
|
||||||
row = self.window.listWidget_componentList.currentRow()
|
row = self.window.listWidget_componentList.currentRow()
|
||||||
if row < len(self.pages) + 1:
|
if row != -1 and row < len(self.pages)+1:
|
||||||
module = self.selectedComponents[row]
|
module = self.selectedComponents[row]
|
||||||
self.selectedComponents.pop(row)
|
self.selectedComponents.pop(row)
|
||||||
self.selectedComponents.insert(row + 1,module)
|
self.selectedComponents.insert(row + 1,module)
|
||||||
|
@ -507,7 +487,7 @@ class Main(QtCore.QObject):
|
||||||
if self.window.comboBox_openPreset.itemText(i) == filename:
|
if self.window.comboBox_openPreset.itemText(i) == filename:
|
||||||
self.window.comboBox_openPreset.removeItem(i)
|
self.window.comboBox_openPreset.removeItem(i)
|
||||||
with open(filepath, 'w') as f:
|
with open(filepath, 'w') as f:
|
||||||
f.write(core.Core.sortedStringDict(saveValueStore))
|
f.write(core.Core.stringOrderedDict(saveValueStore))
|
||||||
self.window.comboBox_openPreset.addItem(filename)
|
self.window.comboBox_openPreset.addItem(filename)
|
||||||
self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1)
|
self.window.comboBox_openPreset.setCurrentIndex(self.window.comboBox_openPreset.count()-1)
|
||||||
|
|
||||||
|
@ -550,12 +530,13 @@ class Main(QtCore.QObject):
|
||||||
if not filepath.endswith(".avp"):
|
if not filepath.endswith(".avp"):
|
||||||
filepath += '.avp'
|
filepath += '.avp'
|
||||||
with open(filepath, 'w') as f:
|
with open(filepath, 'w') as f:
|
||||||
|
print('creating %s' % filepath)
|
||||||
f.write('[Components]\n')
|
f.write('[Components]\n')
|
||||||
for comp in self.selectedComponents:
|
for comp in self.selectedComponents:
|
||||||
saveValueStore = comp.savePreset()
|
saveValueStore = comp.savePreset()
|
||||||
f.write('%s\n' % str(comp))
|
f.write('%s\n' % str(comp))
|
||||||
f.write('%s\n' % str(comp.version()))
|
f.write('%s\n' % str(comp.version()))
|
||||||
f.write('%s\n' % core.Core.sortedStringDict(saveValueStore))
|
f.write('%s\n' % core.Core.stringOrderedDict(saveValueStore))
|
||||||
if filepath != self.autosavePath:
|
if filepath != self.autosavePath:
|
||||||
self.settings.setValue("projectDir", os.path.dirname(filepath))
|
self.settings.setValue("projectDir", os.path.dirname(filepath))
|
||||||
self.settings.setValue("currentProject", filepath)
|
self.settings.setValue("currentProject", filepath)
|
||||||
|
@ -604,14 +585,18 @@ class Main(QtCore.QObject):
|
||||||
saveValueStore = dict(eval(line))
|
saveValueStore = dict(eval(line))
|
||||||
self.selectedComponents[-1].loadPreset(saveValueStore)
|
self.selectedComponents[-1].loadPreset(saveValueStore)
|
||||||
i = 0
|
i = 0
|
||||||
except:
|
except (IndexError, ValueError, KeyError, NameError, SyntaxError, AttributeError, TypeError) as e:
|
||||||
self.clear()
|
self.clear()
|
||||||
self.showMessage("Project file '%s' is corrupted." % filepath)
|
typ, value, _ = sys.exc_info()
|
||||||
|
msg = '%s: %s' % (typ.__name__, value)
|
||||||
|
self.showMessage("Project file '%s' is corrupted." % filepath, False,
|
||||||
|
QtGui.QMessageBox.Warning, msg)
|
||||||
|
|
||||||
def showMessage(self, string, showCancel=False, icon=QtGui.QMessageBox.Information):
|
def showMessage(self, string, showCancel=False, icon=QtGui.QMessageBox.Information, detail=None):
|
||||||
msg = QtGui.QMessageBox()
|
msg = QtGui.QMessageBox()
|
||||||
msg.setIcon(icon)
|
msg.setIcon(icon)
|
||||||
msg.setText(string)
|
msg.setText(string)
|
||||||
|
msg.setDetailedText(detail)
|
||||||
if showCancel:
|
if showCancel:
|
||||||
msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
|
msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1008</width>
|
<width>1028</width>
|
||||||
<height>575</height>
|
<height>592</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -421,73 +421,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_background">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>85</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Background</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="lineEdit_background">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="toolButton_selectBackground">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||||
<item>
|
<item>
|
||||||
|
@ -621,7 +554,6 @@
|
||||||
</layout>
|
</layout>
|
||||||
<zorder></zorder>
|
<zorder></zorder>
|
||||||
<zorder></zorder>
|
<zorder></zorder>
|
||||||
<zorder></zorder>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab_encoderSettings">
|
<widget class="QWidget" name="tab_encoderSettings">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|
|
@ -22,10 +22,9 @@ class Worker(QtCore.QObject):
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(str, list)
|
@pyqtSlot(str, list)
|
||||||
def createPreviewImage(self, backgroundImage, components):
|
def createPreviewImage(self, components):
|
||||||
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
||||||
dic = {
|
dic = {
|
||||||
"backgroundImage": backgroundImage,
|
|
||||||
"components": components,
|
"components": components,
|
||||||
}
|
}
|
||||||
self.queue.put(dic)
|
self.queue.put(dic)
|
||||||
|
@ -40,25 +39,14 @@ class Worker(QtCore.QObject):
|
||||||
except Empty:
|
except Empty:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
bgImage = self.core.parseBaseImage(\
|
|
||||||
nextPreviewInformation["backgroundImage"],
|
|
||||||
preview=True
|
|
||||||
)
|
|
||||||
if bgImage == []:
|
|
||||||
bgImage = ''
|
|
||||||
else:
|
|
||||||
bgImage = bgImage[0]
|
|
||||||
|
|
||||||
im = self.core.drawBaseImage(bgImage)
|
|
||||||
width = int(self.core.settings.value('outputWidth'))
|
width = int(self.core.settings.value('outputWidth'))
|
||||||
height = int(self.core.settings.value('outputHeight'))
|
height = int(self.core.settings.value('outputHeight'))
|
||||||
frame = Image.new("RGBA", (width, height),(0,0,0,255))
|
frame = Image.new("RGBA", (width, height),(0,0,0,0))
|
||||||
frame.paste(im)
|
|
||||||
|
|
||||||
components = nextPreviewInformation["components"]
|
components = nextPreviewInformation["components"]
|
||||||
for component in reversed(components):
|
for component in reversed(components):
|
||||||
newFrame = Image.alpha_composite(frame,component.previewRender(self))
|
#newFrame = Image.alpha_composite(frame,)
|
||||||
frame = Image.alpha_composite(frame,newFrame)
|
frame = Image.alpha_composite(frame,component.previewRender(self))
|
||||||
|
|
||||||
self._image = ImageQt(frame)
|
self._image = ImageQt(frame)
|
||||||
self.imageCreated.emit(QtGui.QImage(self._image))
|
self.imageCreated.emit(QtGui.QImage(self._image))
|
||||||
|
|
|
@ -37,19 +37,19 @@ class Worker(QtCore.QObject):
|
||||||
def renderNode(self):
|
def renderNode(self):
|
||||||
while not self.stopped:
|
while not self.stopped:
|
||||||
i = self.compositeQueue.get()
|
i = self.compositeQueue.get()
|
||||||
|
frame = None
|
||||||
if self.imBackground is not None:
|
|
||||||
frame = self.imBackground
|
|
||||||
else:
|
|
||||||
frame = self.getBackgroundAtIndex(i[1])
|
|
||||||
|
|
||||||
for compNo, comp in reversed(list(enumerate(self.components))):
|
for compNo, comp in reversed(list(enumerate(self.components))):
|
||||||
if compNo in self.staticComponents and self.staticComponents[compNo] != None:
|
if compNo in self.staticComponents and self.staticComponents[compNo] != None:
|
||||||
|
if frame is None:
|
||||||
|
frame = self.staticComponents[compNo]
|
||||||
|
else:
|
||||||
frame = Image.alpha_composite(frame, self.staticComponents[compNo])
|
frame = Image.alpha_composite(frame, self.staticComponents[compNo])
|
||||||
else:
|
else:
|
||||||
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0]))
|
if frame is None:
|
||||||
|
frame = comp.frameRender(compNo, i[0], i[1])
|
||||||
# frame.paste(compFrame, mask=compFrame)
|
else:
|
||||||
|
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0], i[1]))
|
||||||
|
|
||||||
self.renderQueue.put([i[0], frame])
|
self.renderQueue.put([i[0], frame])
|
||||||
self.compositeQueue.task_done()
|
self.compositeQueue.task_done()
|
||||||
|
@ -59,9 +59,7 @@ class Worker(QtCore.QObject):
|
||||||
|
|
||||||
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
||||||
self.compositeQueue.put([i, self.bgI])
|
self.compositeQueue.put([i, self.bgI])
|
||||||
if not self.imBackground:
|
# increment tracked video frame for next iteration
|
||||||
# increment background video frame for next iteration
|
|
||||||
if self.bgI < len(self.backgroundFrames)-1:
|
|
||||||
self.bgI += 1
|
self.bgI += 1
|
||||||
|
|
||||||
def previewDispatch(self):
|
def previewDispatch(self):
|
||||||
|
@ -74,39 +72,18 @@ class Worker(QtCore.QObject):
|
||||||
|
|
||||||
self.previewQueue.task_done()
|
self.previewQueue.task_done()
|
||||||
|
|
||||||
def getBackgroundAtIndex(self, i):
|
@pyqtSlot(str, str, list)
|
||||||
background = Image.new(
|
def createVideo(self, inputFile, outputFile, components):
|
||||||
"RGBA",
|
|
||||||
(self.width, self.height),
|
|
||||||
(0, 0, 0, 255)
|
|
||||||
)
|
|
||||||
layer = self.core.drawBaseImage(self.backgroundFrames[i])
|
|
||||||
background.paste(layer)
|
|
||||||
return background
|
|
||||||
|
|
||||||
@pyqtSlot(str, str, str, list)
|
|
||||||
def createVideo(self, backgroundImage, inputFile, outputFile, components):
|
|
||||||
self.encoding.emit(True)
|
self.encoding.emit(True)
|
||||||
self.components = components
|
self.components = components
|
||||||
self.outputFile = outputFile
|
self.outputFile = outputFile
|
||||||
|
self.bgI = 0 # tracked video frame
|
||||||
self.reset()
|
self.reset()
|
||||||
self.width = int(self.core.settings.value('outputWidth'))
|
self.width = int(self.core.settings.value('outputWidth'))
|
||||||
self.height = int(self.core.settings.value('outputHeight'))
|
self.height = int(self.core.settings.value('outputHeight'))
|
||||||
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
||||||
progressBarValue = 0
|
progressBarValue = 0
|
||||||
self.progressBarUpdate.emit(progressBarValue)
|
self.progressBarUpdate.emit(progressBarValue)
|
||||||
self.progressBarSetText.emit('Loading background image…')
|
|
||||||
|
|
||||||
self.backgroundImage = backgroundImage
|
|
||||||
|
|
||||||
self.backgroundFrames = self.core.parseBaseImage(backgroundImage)
|
|
||||||
if len(self.backgroundFrames) < 2:
|
|
||||||
# the base image is not a video so we can draw it now
|
|
||||||
self.imBackground = self.getBackgroundAtIndex(0)
|
|
||||||
else:
|
|
||||||
# base images will be drawn while drawing the audio bars
|
|
||||||
self.imBackground = None
|
|
||||||
self.bgI = 0
|
|
||||||
|
|
||||||
self.progressBarSetText.emit('Loading audio file...')
|
self.progressBarSetText.emit('Loading audio file...')
|
||||||
self.completeAudioArray = self.core.readAudioFile(inputFile, self)
|
self.completeAudioArray = self.core.readAudioFile(inputFile, self)
|
||||||
|
@ -120,6 +97,7 @@ class Worker(QtCore.QObject):
|
||||||
|
|
||||||
ffmpegCommand = [
|
ffmpegCommand = [
|
||||||
self.core.FFMPEG_BIN,
|
self.core.FFMPEG_BIN,
|
||||||
|
'-thread_queue_size', '512',
|
||||||
'-y', # (optional) means overwrite the output file if it already exists.
|
'-y', # (optional) means overwrite the output file if it already exists.
|
||||||
'-f', 'rawvideo',
|
'-f', 'rawvideo',
|
||||||
'-vcodec', 'rawvideo',
|
'-vcodec', 'rawvideo',
|
||||||
|
@ -165,7 +143,7 @@ class Worker(QtCore.QObject):
|
||||||
)
|
)
|
||||||
|
|
||||||
if properties and 'static' in properties:
|
if properties and 'static' in properties:
|
||||||
self.staticComponents[compNo] = copy(comp.frameRender(compNo, 0))
|
self.staticComponents[compNo] = copy(comp.frameRender(compNo, 0, 0))
|
||||||
self.progressBarUpdate.emit(100)
|
self.progressBarUpdate.emit(100)
|
||||||
|
|
||||||
self.compositeQueue = Queue()
|
self.compositeQueue = Queue()
|
||||||
|
@ -250,7 +228,6 @@ class Worker(QtCore.QObject):
|
||||||
self.error = False
|
self.error = False
|
||||||
self.canceled = False
|
self.canceled = False
|
||||||
self.parent.drawPreview()
|
self.parent.drawPreview()
|
||||||
self.core.deleteTempDir()
|
|
||||||
self.stopped = True
|
self.stopped = True
|
||||||
self.encoding.emit(False)
|
self.encoding.emit(False)
|
||||||
self.videoCreated.emit()
|
self.videoCreated.emit()
|
||||||
|
|
Reference in New Issue