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
|
||||
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):
|
||||
for var, value in kwargs.items():
|
||||
exec('self.%s = value' % var)
|
||||
|
@ -66,4 +73,10 @@ class Component:
|
|||
|
||||
def savePreset(self):
|
||||
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.lastSpectrum = None
|
||||
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):
|
||||
if self.canceled:
|
||||
|
@ -73,11 +75,8 @@ class Component(__base__.Component):
|
|||
self.progressBarSetText.emit(pStr)
|
||||
self.progressBarUpdate.emit(int(progress))
|
||||
|
||||
|
||||
def frameRender(self, moduleNo, frameNo):
|
||||
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 frameRender(self, moduleNo, arrayNo, frameNo):
|
||||
return self.drawBars(self.width, self.height, self.spectrumArray[arrayNo], self.visColor, self.layout)
|
||||
|
||||
def pickColor(self):
|
||||
RGBstring, btnStyle = super().pickColor()
|
||||
|
@ -154,12 +153,3 @@ class Component(__base__.Component):
|
|||
|
||||
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.textColor = (255,255,255)
|
||||
self.title = 'Text'
|
||||
self.titleFont = None
|
||||
self.alignment = 1
|
||||
self.fontSize = height / 13.5
|
||||
self.xPosition = width / 2
|
||||
|
@ -35,8 +34,6 @@ class Component(__base__.Component):
|
|||
page.pushButton_textColor.setStyleSheet(btnStyle)
|
||||
|
||||
page.lineEdit_title.setText(self.title)
|
||||
#if self.titleFont:
|
||||
# page.fontComboBox_titleFont.setCurrentFont(QFont(self.titleFont))
|
||||
page.comboBox_textAlign.setCurrentIndex(int(self.alignment))
|
||||
page.spinBox_fontSize.setValue(int(self.fontSize))
|
||||
page.spinBox_xTextAlign.setValue(int(self.xPosition))
|
||||
|
@ -109,7 +106,7 @@ class Component(__base__.Component):
|
|||
super().preFrameRender(**kwargs)
|
||||
return ['static']
|
||||
|
||||
def frameRender(self, moduleNo, frameNo):
|
||||
def frameRender(self, moduleNo, arrayNo, frameNo):
|
||||
width = int(self.worker.core.settings.value('outputWidth'))
|
||||
height = int(self.worker.core.settings.value('outputHeight'))
|
||||
return self.addText(width, height)
|
||||
|
@ -142,9 +139,3 @@ class Component(__base__.Component):
|
|||
return
|
||||
self.page.lineEdit_textColor.setText(RGBstring)
|
||||
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():
|
||||
|
||||
def __init__(self):
|
||||
self.lastBackgroundImage = ""
|
||||
self._image = None
|
||||
|
||||
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)
|
||||
|
||||
def findFfmpeg(self):
|
||||
|
@ -31,31 +30,6 @@ class Core():
|
|||
except:
|
||||
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):
|
||||
command = [ self.FFMPEG_BIN,
|
||||
'-i', filename]
|
||||
|
@ -121,30 +95,10 @@ class Core():
|
|||
return completeAudioArray
|
||||
|
||||
def deleteTempDir(self):
|
||||
if self.tempDir and os.path.exists(self.tempDir):
|
||||
try:
|
||||
rmtree(self.tempDir)
|
||||
|
||||
def getVideoFrames(self, videoPath, firstOnly=False):
|
||||
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)])
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def cancel(self):
|
||||
self.canceled = True
|
||||
|
@ -153,6 +107,6 @@ class Core():
|
|||
self.canceled = False
|
||||
|
||||
@staticmethod
|
||||
def sortedStringDict(dictionary):
|
||||
def stringOrderedDict(dictionary):
|
||||
sorted_ = OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
|
||||
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 queue import Queue
|
||||
from importlib import import_module
|
||||
|
@ -133,9 +133,9 @@ class PreviewWindow(QtGui.QLabel):
|
|||
|
||||
class Main(QtCore.QObject):
|
||||
|
||||
newTask = QtCore.pyqtSignal(str, list)
|
||||
newTask = QtCore.pyqtSignal(list)
|
||||
processTask = QtCore.pyqtSignal()
|
||||
videoTask = QtCore.pyqtSignal(str, str, str, list)
|
||||
videoTask = QtCore.pyqtSignal(str, str, list)
|
||||
|
||||
def __init__(self, window):
|
||||
QtCore.QObject.__init__(self)
|
||||
|
@ -145,6 +145,7 @@ class Main(QtCore.QObject):
|
|||
self.core = core.Core()
|
||||
self.pages = []
|
||||
self.selectedComponents = []
|
||||
self.lastAutosave = time.time()
|
||||
|
||||
# create data directory, load/create settings
|
||||
self.dataDir = QDesktopServices.storageLocation(QDesktopServices.DataLocation)
|
||||
|
@ -172,14 +173,13 @@ class Main(QtCore.QObject):
|
|||
|
||||
# begin decorating the window and connecting events
|
||||
window.toolButton_selectAudioFile.clicked.connect(self.openInputFileDialog)
|
||||
window.toolButton_selectBackground.clicked.connect(self.openBackgroundFileDialog)
|
||||
window.toolButton_selectOutputFile.clicked.connect(self.openOutputFileDialog)
|
||||
window.progressBar_createVideo.setValue(0)
|
||||
window.pushButton_createVideo.clicked.connect(self.createAudioVisualisation)
|
||||
window.pushButton_Cancel.clicked.connect(self.stopVideo)
|
||||
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)
|
||||
|
||||
self.modules = self.findComponents()
|
||||
|
@ -236,15 +236,17 @@ class Main(QtCore.QObject):
|
|||
self.autosave()
|
||||
|
||||
def autosave(self):
|
||||
if time.time() - self.lastAutosave >= 1.0:
|
||||
if os.path.exists(self.autosavePath):
|
||||
os.remove(self.autosavePath)
|
||||
self.createProjectFile(self.autosavePath)
|
||||
self.lastAutosave = time.time()
|
||||
|
||||
def openInputFileDialog(self):
|
||||
inputDir = self.settings.value("inputDir", expanduser("~"))
|
||||
|
||||
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 == "":
|
||||
self.settings.setValue("inputDir", os.path.dirname(fileName))
|
||||
|
@ -254,23 +256,12 @@ class Main(QtCore.QObject):
|
|||
outputDir = self.settings.value("outputDir", expanduser("~"))
|
||||
|
||||
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 == "":
|
||||
self.settings.setValue("outputDir", os.path.dirname(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):
|
||||
print('stop')
|
||||
self.videoWorker.cancel()
|
||||
|
@ -291,8 +282,7 @@ class Main(QtCore.QObject):
|
|||
self.videoWorker.imageCreated.connect(self.showPreviewImage)
|
||||
self.videoWorker.encoding.connect(self.changeEncodingStatus)
|
||||
self.videoThread.start()
|
||||
self.videoTask.emit(self.window.lineEdit_background.text(),
|
||||
self.window.lineEdit_audioFile.text(),
|
||||
self.videoTask.emit(self.window.lineEdit_audioFile.text(),
|
||||
self.window.lineEdit_outputFile.text(),
|
||||
self.selectedComponents)
|
||||
else:
|
||||
|
@ -323,10 +313,6 @@ class Main(QtCore.QObject):
|
|||
self.window.pushButton_savePreset.setEnabled(False)
|
||||
self.window.pushButton_openProject.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:
|
||||
self.window.pushButton_createVideo.setEnabled(True)
|
||||
self.window.pushButton_Cancel.setEnabled(False)
|
||||
|
@ -349,12 +335,6 @@ class Main(QtCore.QObject):
|
|||
self.window.pushButton_openProject.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):
|
||||
self.window.progressBar_createVideo.setFormat(value)
|
||||
|
||||
|
@ -370,7 +350,7 @@ class Main(QtCore.QObject):
|
|||
self.drawPreview()
|
||||
|
||||
def drawPreview(self):
|
||||
self.newTask.emit(self.window.lineEdit_background.text(), self.selectedComponents)
|
||||
self.newTask.emit(self.selectedComponents)
|
||||
# self.processTask.emit()
|
||||
self.autosave()
|
||||
|
||||
|
@ -381,7 +361,7 @@ class Main(QtCore.QObject):
|
|||
def findComponents():
|
||||
srcPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'components')
|
||||
if os.path.exists(srcPath):
|
||||
for f in os.listdir(srcPath):
|
||||
for f in sorted(os.listdir(srcPath)):
|
||||
name, ext = os.path.splitext(f)
|
||||
if name.startswith("__"):
|
||||
continue
|
||||
|
@ -446,7 +426,7 @@ class Main(QtCore.QObject):
|
|||
|
||||
def moveComponentDown(self):
|
||||
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]
|
||||
self.selectedComponents.pop(row)
|
||||
self.selectedComponents.insert(row + 1,module)
|
||||
|
@ -507,7 +487,7 @@ class Main(QtCore.QObject):
|
|||
if self.window.comboBox_openPreset.itemText(i) == filename:
|
||||
self.window.comboBox_openPreset.removeItem(i)
|
||||
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.setCurrentIndex(self.window.comboBox_openPreset.count()-1)
|
||||
|
||||
|
@ -550,12 +530,13 @@ class Main(QtCore.QObject):
|
|||
if not filepath.endswith(".avp"):
|
||||
filepath += '.avp'
|
||||
with open(filepath, 'w') as f:
|
||||
print('creating %s' % filepath)
|
||||
f.write('[Components]\n')
|
||||
for comp in self.selectedComponents:
|
||||
saveValueStore = comp.savePreset()
|
||||
f.write('%s\n' % str(comp))
|
||||
f.write('%s\n' % str(comp.version()))
|
||||
f.write('%s\n' % core.Core.sortedStringDict(saveValueStore))
|
||||
f.write('%s\n' % core.Core.stringOrderedDict(saveValueStore))
|
||||
if filepath != self.autosavePath:
|
||||
self.settings.setValue("projectDir", os.path.dirname(filepath))
|
||||
self.settings.setValue("currentProject", filepath)
|
||||
|
@ -604,14 +585,18 @@ class Main(QtCore.QObject):
|
|||
saveValueStore = dict(eval(line))
|
||||
self.selectedComponents[-1].loadPreset(saveValueStore)
|
||||
i = 0
|
||||
except:
|
||||
except (IndexError, ValueError, KeyError, NameError, SyntaxError, AttributeError, TypeError) as e:
|
||||
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.setIcon(icon)
|
||||
msg.setText(string)
|
||||
msg.setDetailedText(detail)
|
||||
if showCancel:
|
||||
msg.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
|
||||
else:
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1008</width>
|
||||
<height>575</height>
|
||||
<width>1028</width>
|
||||
<height>592</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -421,73 +421,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
|
@ -621,7 +554,6 @@
|
|||
</layout>
|
||||
<zorder></zorder>
|
||||
<zorder></zorder>
|
||||
<zorder></zorder>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_encoderSettings">
|
||||
<attribute name="title">
|
||||
|
|
|
@ -22,10 +22,9 @@ class Worker(QtCore.QObject):
|
|||
|
||||
|
||||
@pyqtSlot(str, list)
|
||||
def createPreviewImage(self, backgroundImage, components):
|
||||
def createPreviewImage(self, components):
|
||||
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
||||
dic = {
|
||||
"backgroundImage": backgroundImage,
|
||||
"components": components,
|
||||
}
|
||||
self.queue.put(dic)
|
||||
|
@ -40,25 +39,14 @@ class Worker(QtCore.QObject):
|
|||
except Empty:
|
||||
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'))
|
||||
height = int(self.core.settings.value('outputHeight'))
|
||||
frame = Image.new("RGBA", (width, height),(0,0,0,255))
|
||||
frame.paste(im)
|
||||
frame = Image.new("RGBA", (width, height),(0,0,0,0))
|
||||
|
||||
components = nextPreviewInformation["components"]
|
||||
for component in reversed(components):
|
||||
newFrame = Image.alpha_composite(frame,component.previewRender(self))
|
||||
frame = Image.alpha_composite(frame,newFrame)
|
||||
#newFrame = Image.alpha_composite(frame,)
|
||||
frame = Image.alpha_composite(frame,component.previewRender(self))
|
||||
|
||||
self._image = ImageQt(frame)
|
||||
self.imageCreated.emit(QtGui.QImage(self._image))
|
||||
|
|
|
@ -37,19 +37,19 @@ class Worker(QtCore.QObject):
|
|||
def renderNode(self):
|
||||
while not self.stopped:
|
||||
i = self.compositeQueue.get()
|
||||
|
||||
if self.imBackground is not None:
|
||||
frame = self.imBackground
|
||||
else:
|
||||
frame = self.getBackgroundAtIndex(i[1])
|
||||
frame = None
|
||||
|
||||
for compNo, comp in reversed(list(enumerate(self.components))):
|
||||
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])
|
||||
else:
|
||||
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0]))
|
||||
|
||||
# frame.paste(compFrame, mask=compFrame)
|
||||
if frame is None:
|
||||
frame = comp.frameRender(compNo, i[0], i[1])
|
||||
else:
|
||||
frame = Image.alpha_composite(frame, comp.frameRender(compNo, i[0], i[1]))
|
||||
|
||||
self.renderQueue.put([i[0], frame])
|
||||
self.compositeQueue.task_done()
|
||||
|
@ -59,9 +59,7 @@ class Worker(QtCore.QObject):
|
|||
|
||||
for i in range(0, len(self.completeAudioArray), self.sampleSize):
|
||||
self.compositeQueue.put([i, self.bgI])
|
||||
if not self.imBackground:
|
||||
# increment background video frame for next iteration
|
||||
if self.bgI < len(self.backgroundFrames)-1:
|
||||
# increment tracked video frame for next iteration
|
||||
self.bgI += 1
|
||||
|
||||
def previewDispatch(self):
|
||||
|
@ -74,39 +72,18 @@ class Worker(QtCore.QObject):
|
|||
|
||||
self.previewQueue.task_done()
|
||||
|
||||
def getBackgroundAtIndex(self, i):
|
||||
background = Image.new(
|
||||
"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):
|
||||
@pyqtSlot(str, str, list)
|
||||
def createVideo(self, inputFile, outputFile, components):
|
||||
self.encoding.emit(True)
|
||||
self.components = components
|
||||
self.outputFile = outputFile
|
||||
self.bgI = 0 # tracked video frame
|
||||
self.reset()
|
||||
self.width = int(self.core.settings.value('outputWidth'))
|
||||
self.height = int(self.core.settings.value('outputHeight'))
|
||||
# print('worker thread id: {}'.format(QtCore.QThread.currentThreadId()))
|
||||
progressBarValue = 0
|
||||
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.completeAudioArray = self.core.readAudioFile(inputFile, self)
|
||||
|
@ -120,6 +97,7 @@ class Worker(QtCore.QObject):
|
|||
|
||||
ffmpegCommand = [
|
||||
self.core.FFMPEG_BIN,
|
||||
'-thread_queue_size', '512',
|
||||
'-y', # (optional) means overwrite the output file if it already exists.
|
||||
'-f', 'rawvideo',
|
||||
'-vcodec', 'rawvideo',
|
||||
|
@ -165,7 +143,7 @@ class Worker(QtCore.QObject):
|
|||
)
|
||||
|
||||
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.compositeQueue = Queue()
|
||||
|
@ -250,7 +228,6 @@ class Worker(QtCore.QObject):
|
|||
self.error = False
|
||||
self.canceled = False
|
||||
self.parent.drawPreview()
|
||||
self.core.deleteTempDir()
|
||||
self.stopped = True
|
||||
self.encoding.emit(False)
|
||||
self.videoCreated.emit()
|
||||
|
|
Reference in New Issue