aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command.py215
-rw-r--r--core.py40
-rw-r--r--main.py54
-rw-r--r--mainwindow.py76
-rw-r--r--video_thread.py2
5 files changed, 196 insertions, 191 deletions
diff --git a/command.py b/command.py
index a610d8c..1b07afc 100644
--- a/command.py
+++ b/command.py
@@ -1,122 +1,97 @@
-# FIXME: commandline functionality broken until we decide how to implement it
-'''
+from PyQt4 import QtCore
+from PyQt4.QtCore import QSettings
+import argparse
+import os
+
+import core
+import video_thread
+from main import LoadDefaultSettings
+
+
class Command(QtCore.QObject):
- videoTask = QtCore.pyqtSignal(str, str, str, list)
-
- def __init__(self):
- QtCore.QObject.__init__(self)
- self.modules = []
- self.selectedComponents = []
-
- import argparse
- self.parser = argparse.ArgumentParser(
- description='Create a visualization for an audio file')
- self.parser.add_argument(
- '-i', '--input', dest='input', help='input audio file', required=True)
- self.parser.add_argument(
- '-o', '--output', dest='output',
- help='output video file', required=True)
- self.parser.add_argument(
- '-b', '--background', dest='bgimage',
- help='background image file', required=True)
- self.parser.add_argument(
- '-t', '--text', dest='text', help='title text', required=True)
- self.parser.add_argument(
- '-f', '--font', dest='font', help='title font', required=False)
- self.parser.add_argument(
- '-s', '--fontsize', dest='fontsize',
- help='title font size', required=False)
- self.parser.add_argument(
- '-c', '--textcolor', dest='textcolor',
- help='title text color in r,g,b format', required=False)
- self.parser.add_argument(
- '-C', '--viscolor', dest='viscolor',
- help='visualization color in r,g,b format', required=False)
- self.parser.add_argument(
- '-x', '--xposition', dest='xposition',
- help='x position', required=False)
- self.parser.add_argument(
- '-y', '--yposition', dest='yposition',
- help='y position', required=False)
- self.parser.add_argument(
- '-a', '--alignment', dest='alignment',
- help='title alignment', required=False,
- type=int, choices=[0, 1, 2])
- self.args = self.parser.parse_args()
-
- self.settings = QSettings('settings.ini', QSettings.IniFormat)
- LoadDefaultSettings(self)
-
- # load colours as tuples from comma-separated strings
- self.textColor = core.Core.RGBFromString(
- self.settings.value("textColor", '255, 255, 255'))
- self.visColor = core.Core.RGBFromString(
- self.settings.value("visColor", '255, 255, 255'))
- if self.args.textcolor:
- self.textColor = core.Core.RGBFromString(self.args.textcolor)
- if self.args.viscolor:
- self.visColor = core.Core.RGBFromString(self.args.viscolor)
-
- # font settings
- if self.args.font:
- self.font = QFont(self.args.font)
- else:
- self.font = QFont(self.settings.value("titleFont", QFont()))
-
- if self.args.fontsize:
- self.fontsize = int(self.args.fontsize)
- else:
- self.fontsize = int(self.settings.value("fontSize", 35))
- if self.args.alignment:
- self.alignment = int(self.args.alignment)
- else:
- self.alignment = int(self.settings.value("alignment", 0))
-
- if self.args.xposition:
- self.textX = int(self.args.xposition)
- else:
- self.textX = int(self.settings.value("xPosition", 70))
-
- if self.args.yposition:
- self.textY = int(self.args.yposition)
- else:
- self.textY = int(self.settings.value("yPosition", 375))
-
- ffmpeg_cmd = self.settings.value("ffmpeg_cmd", expanduser("~"))
-
- self.videoThread = QtCore.QThread(self)
- self.videoWorker = video_thread.Worker(self)
-
- self.videoWorker.moveToThread(self.videoThread)
- self.videoWorker.videoCreated.connect(self.videoCreated)
-
- self.videoThread.start()
- self.videoTask.emit(self.args.bgimage,
- self.args.text,
- self.font,
- self.fontsize,
- self.alignment,
- self.textX,
- self.textY,
- self.textColor,
- self.visColor,
- self.args.input,
- self.args.output,
- self.selectedComponents)
-
- def videoCreated(self):
- self.videoThread.quit()
- self.videoThread.wait()
- self.cleanUp()
-
- def cleanUp(self):
- self.settings.setValue("titleFont", self.font.toString())
- self.settings.setValue("alignment", str(self.alignment))
- self.settings.setValue("fontSize", str(self.fontsize))
- self.settings.setValue("xPosition", str(self.textX))
- self.settings.setValue("yPosition", str(self.textY))
- self.settings.setValue("visColor", '%s,%s,%s' % self.visColor)
- self.settings.setValue("textColor", '%s,%s,%s' % self.textColor)
- sys.exit(0)
-'''
+ videoTask = QtCore.pyqtSignal(str, str, list)
+
+ def __init__(self):
+ QtCore.QObject.__init__(self)
+ self.core = core.Core()
+ self.dataDir = self.core.dataDir
+
+ self.parser = argparse.ArgumentParser(
+ description='Create a visualization for an audio file')
+ self.parser.add_argument(
+ '-i', '--input', help='input audio file', required=True)
+ self.parser.add_argument(
+ '-o', '--output', help='output video file', required=True)
+
+ # optional arguments
+ self.parser.add_argument(
+ 'projpath', metavar='path-to-project',
+ help='open a project file (.avp)', nargs='?')
+
+ '''
+ self.parser.add_argument(
+ '-b', '--background', dest='bgimage',
+ help='background image file', required=True)
+ self.parser.add_argument(
+ '-t', '--text', dest='text', help='title text', required=True)
+ self.parser.add_argument(
+ '-f', '--font', dest='font', help='title font', required=False)
+ self.parser.add_argument(
+ '-s', '--fontsize', dest='fontsize',
+ help='title font size', required=False)
+ self.parser.add_argument(
+ '-c', '--textcolor', dest='textcolor',
+ help='title text color in r,g,b format', required=False)
+ self.parser.add_argument(
+ '-C', '--viscolor', dest='viscolor',
+ help='visualization color in r,g,b format', required=False)
+ self.parser.add_argument(
+ '-x', '--xposition', dest='xposition',
+ help='x position', required=False)
+ self.parser.add_argument(
+ '-y', '--yposition', dest='yposition',
+ help='y position', required=False)
+ self.parser.add_argument(
+ '-a', '--alignment', dest='alignment',
+ help='title alignment', required=False,
+ type=int, choices=[0, 1, 2])
+ '''
+
+ self.args = self.parser.parse_args()
+ self.settings = QSettings(
+ os.path.join(self.dataDir, 'settings.ini'), QSettings.IniFormat)
+ LoadDefaultSettings(self)
+
+ if self.args.projpath:
+ self.core.openProject(self, self.args.projpath)
+
+ self.createAudioVisualisation()
+
+ def createAudioVisualisation(self):
+ self.videoThread = QtCore.QThread(self)
+ self.videoWorker = video_thread.Worker(self)
+ self.videoWorker.moveToThread(self.videoThread)
+ self.videoWorker.videoCreated.connect(self.videoCreated)
+
+ self.videoThread.start()
+ self.videoTask.emit(
+ self.args.input,
+ self.args.output,
+ self.core.selectedComponents)
+
+ def videoCreated(self):
+ self.videoThread.quit()
+ self.videoThread.wait()
+ self.cleanUp()
+
+ def showMessage(self, **kwargs):
+ print(kwargs['msg'])
+ if 'detail' in kwargs:
+ print(kwargs['detail'])
+
+ def drawPreview(self, *args):
+ pass
+
+ def cleanUp(self, *args):
+ pass
diff --git a/core.py b/core.py
index e4a7a6c..5e4071a 100644
--- a/core.py
+++ b/core.py
@@ -37,6 +37,7 @@ class Core():
'*.wav',
'*.ogg',
'*.fla',
+ '*.flac',
'*.aac',
])
self.imageFormats = Core.appendUppercase([
@@ -76,9 +77,10 @@ class Core():
for i, component in enumerate(self.selectedComponents):
component.compPos = i
- def insertComponent(self, compPos, moduleIndex):
+ def insertComponent(self, compPos, moduleIndex, loader):
+ '''Creates a new component'''
if compPos < 0:
- compPos = len(self.selectedComponents) -1
+ compPos = len(self.selectedComponents)
if len(self.selectedComponents) > 50:
return None
@@ -87,8 +89,14 @@ class Core():
self.selectedComponents.insert(
compPos,
component)
-
self.componentListChanged()
+
+ # init component's widget for loading/saving presets
+ self.selectedComponents[compPos].widget(loader)
+ self.updateComponent(compPos)
+
+ if hasattr(loader, 'insertComponent'):
+ loader.insertComponent(compPos)
return compPos
def moveComponent(self, startI, endI):
@@ -115,11 +123,8 @@ class Core():
index = compNames.index(compName)
return self.moduleIndexes[index]
- def clearPreset(self, compIndex, loader=None):
- '''Clears a preset from a component'''
+ def clearPreset(self, compIndex):
self.selectedComponents[compIndex].currentPreset = None
- if loader:
- loader.updateComponentTitle(compIndex)
def openPreset(self, filepath, compIndex, presetName):
'''Applies a preset to a specific component'''
@@ -148,9 +153,10 @@ class Core():
return saveValueStore
def openProject(self, loader, filepath):
- '''loader is the object calling this method (mainwindow/command)
- which implements an insertComponent method'''
+ '''loader is the object calling this method which must have
+ its own showMessage(**kwargs) method for displaying errors'''
errcode, data = self.parseAvFile(filepath)
+ print(data)
if errcode == 0:
try:
for i, tup in enumerate(data['Components']):
@@ -169,10 +175,13 @@ class Core():
# saved preset was renamed or deleted
clearThis = True
- # insert component into the loader
- i = loader.insertComponent(
- self.moduleIndexFor(name), -1)
+ # create the actual component object & get its index
+ i = self.insertComponent(
+ -1,
+ self.moduleIndexFor(name),
+ loader)
if i == None:
+ loader.showMessage(msg="Too many components!")
break
try:
@@ -190,7 +199,9 @@ class Core():
(self.selectedComponents[i], e))
if clearThis:
- self.clearPreset(i, loader)
+ self.clearPreset(i)
+ if hasattr(loader, 'updateComponentTitle'):
+ loader.updateComponentTitle(i)
except:
errcode = 1
data = sys.exc_info()
@@ -202,7 +213,8 @@ class Core():
# probably just an old version, still loadable
print('file missing value: %s' % value)
return
- loader.createNewProject()
+ if hasattr(loader, 'createNewProject'):
+ loader.createNewProject()
msg = '%s: %s' % (typ.__name__, value)
loader.showMessage(
msg="Project file '%s' is corrupted." % filepath,
diff --git a/main.py b/main.py
index 7c0727b..140392c 100644
--- a/main.py
+++ b/main.py
@@ -1,8 +1,5 @@
-from importlib import import_module
from PyQt4 import QtGui, uic
-from PyQt4.QtCore import Qt
import sys
-import io
import os
import atexit
import signal
@@ -10,7 +7,6 @@ import signal
import core
import preview_thread
import video_thread
-from mainwindow import *
def LoadDefaultSettings(self):
@@ -36,34 +32,50 @@ def LoadDefaultSettings(self):
}
for parm, value in default.items():
+ print(parm, self.settings.value(parm))
if self.settings.value(parm) is None:
self.settings.setValue(parm, value)
if __name__ == "__main__":
- ''' FIXME commandline functionality broken until we decide how to implement
- if len(sys.argv) > 1:
- # command line mode
- app = QtGui.QApplication(sys.argv, False)
- command = Command()
- signal.signal(signal.SIGINT, command.cleanUp)
- sys.exit(app.exec_())
+ mode = 'gui'
+ if len(sys.argv) > 2:
+ mode = 'cmd'
+
+ elif len(sys.argv) == 2:
+ if sys.argv[1].startswith('-'):
+ mode = 'cmd'
+ else:
+ # opening a project file with gui
+ proj = sys.argv[1]
else:
- '''
+ # normal gui launch
+ proj = None
+
app = QtGui.QApplication(sys.argv)
app.setApplicationName("audio-visualizer")
app.setOrganizationName("audio-visualizer")
- window = uic.loadUi(os.path.join(
- os.path.dirname(os.path.realpath(__file__)), "mainwindow.ui"))
- # window.adjustSize()
- desc = QtGui.QDesktopWidget()
- dpi = desc.physicalDpiX()
- topMargin = 0 if (dpi == 96) else int(10 * (dpi / 96))
- window.resize(window.width() * (dpi / 96), window.height() * (dpi / 96))
- # window.verticalLayout_2.setContentsMargins(0, topMargin, 0, 0)
+ if mode == 'cmd':
+ from command import *
+
+ main = Command()
+
+ elif mode == 'gui':
+ from mainwindow import *
+
+ window = uic.loadUi(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)), "mainwindow.ui"))
+ # window.adjustSize()
+ desc = QtGui.QDesktopWidget()
+ dpi = desc.physicalDpiX()
+
+ topMargin = 0 if (dpi == 96) else int(10 * (dpi / 96))
+ window.resize(window.width() * (dpi / 96), window.height() * (dpi / 96))
+ # window.verticalLayout_2.setContentsMargins(0, topMargin, 0, 0)
- main = MainWindow(window)
+ main = MainWindow(window, proj)
+ # applicable to both modes
signal.signal(signal.SIGINT, main.cleanUp)
atexit.register(main.cleanUp)
diff --git a/mainwindow.py b/mainwindow.py
index f722158..2a8762d 100644
--- a/mainwindow.py
+++ b/mainwindow.py
@@ -45,7 +45,7 @@ class MainWindow(QtCore.QObject):
processTask = QtCore.pyqtSignal()
videoTask = QtCore.pyqtSignal(str, str, list)
- def __init__(self, window):
+ def __init__(self, window, project):
QtCore.QObject.__init__(self)
# print('main thread id: {}'.format(QtCore.QThread.currentThreadId()))
@@ -151,7 +151,7 @@ class MainWindow(QtCore.QObject):
for i, comp in enumerate(self.core.modules):
action = self.compMenu.addAction(comp.Component.__doc__)
action.triggered[()].connect(
- lambda item=i: self.insertComponent(item))
+ lambda item=i: self.core.insertComponent(0, item, self))
self.window.pushButton_addComponent.setMenu(self.compMenu)
@@ -211,24 +211,36 @@ class MainWindow(QtCore.QObject):
self.openPresetManager
)
- # Show the window and load current project
window.show()
- self.currentProject = self.settings.value("currentProject")
- if self.autosaveExists(identical=True):
- # delete autosave if it's identical to the project
- os.remove(self.autosavePath)
- if self.currentProject and os.path.exists(self.autosavePath):
- ch = self.showMessage(
- msg="Restore unsaved changes in project '%s'?"
- % os.path.basename(self.currentProject)[:-4],
- showCancel=True)
- if ch:
- self.saveProjectChanges()
- else:
+ if project and project != self.autosavePath:
+ # open a project from the commandline
+ if not os.path.dirname(project):
+ project = os.path.join(os.path.expanduser('~'), project)
+ self.currentProject = project
+ self.settings.setValue("currentProject", project)
+ if os.path.exists(self.autosavePath):
os.remove(self.autosavePath)
+ else:
+ # open the last currentProject from settings
+ self.currentProject = self.settings.value("currentProject")
+
+ # delete autosave if it's identical to this project
+ if self.autosaveExists(identical=True):
+ os.remove(self.autosavePath)
+
+ if self.currentProject and os.path.exists(self.autosavePath):
+ ch = self.showMessage(
+ msg="Restore unsaved changes in project '%s'?"
+ % os.path.basename(self.currentProject)[:-4],
+ showCancel=True)
+ if ch:
+ self.saveProjectChanges()
+ else:
+ os.remove(self.autosavePath)
+
self.openProject(self.currentProject, prompt=False)
- self.drawPreview()
+ self.drawPreview(True)
def cleanUp(self):
self.timer.stop()
@@ -240,7 +252,8 @@ class MainWindow(QtCore.QObject):
appName = 'Audio Visualizer'
if self.currentProject:
appName += ' - %s' % \
- os.path.basename(self.currentProject)[:-4]
+ os.path.splitext(
+ os.path.basename(self.currentProject))[0]
self.window.setWindowTitle(appName)
@QtCore.pyqtSlot(int, dict)
@@ -252,7 +265,6 @@ class MainWindow(QtCore.QObject):
else:
modified = (presetStore != self.core.savedPresets[name])
else:
- print(pos, presetStore)
modified = bool(presetStore)
if pos < 0:
pos = len(self.core.selectedComponents)-1
@@ -306,10 +318,14 @@ class MainWindow(QtCore.QObject):
self.lastAutosave = time.time()
def autosaveExists(self, identical=True):
- if self.currentProject and os.path.exists(self.autosavePath) \
- and filecmp.cmp(
- self.autosavePath, self.currentProject) == identical:
- return True
+ try:
+ if self.currentProject and os.path.exists(self.autosavePath) \
+ and filecmp.cmp(
+ self.autosavePath, self.currentProject) == identical:
+ return True
+ except FileNotFoundError:
+ print('project file couldn\'t be located:', self.currentProject)
+ return identical
return False
def saveProjectChanges(self):
@@ -411,6 +427,7 @@ class MainWindow(QtCore.QObject):
self.window.listWidget_componentList.setEnabled(True)
self.window.menuButton_newProject.setEnabled(True)
self.window.menuButton_openProject.setEnabled(True)
+ self.drawPreview(True)
def progressBarUpdated(self, value):
self.window.progressBar_createVideo.setValue(value)
@@ -437,19 +454,11 @@ class MainWindow(QtCore.QObject):
def showPreviewImage(self, image):
self.previewWindow.changePixmap(image)
- def insertComponent(self, moduleIndex, compPos=0):
+ def insertComponent(self, index):
componentList = self.window.listWidget_componentList
stackedWidget = self.window.stackedWidget
- if compPos < 0:
- compPos = componentList.count()
-
- index = self.core.insertComponent(
- compPos, moduleIndex)
- if index == None:
- self.showMessage(msg="Too many components!")
- return None
- row = componentList.insertItem(
+ componentList.insertItem(
index,
self.core.selectedComponents[index].__doc__)
componentList.setCurrentRow(index)
@@ -458,11 +467,10 @@ class MainWindow(QtCore.QObject):
self.core.selectedComponents[index].modified.connect(
self.updateComponentTitle)
- self.pages.insert(index, self.core.selectedComponents[index].widget(self))
+ self.pages.insert(index, self.core.selectedComponents[index].page)
stackedWidget.insertWidget(index, self.pages[index])
stackedWidget.setCurrentIndex(index)
- self.core.updateComponent(index)
return index
def removeComponent(self):
diff --git a/video_thread.py b/video_thread.py
index d7220f1..2255259 100644
--- a/video_thread.py
+++ b/video_thread.py
@@ -27,7 +27,6 @@ class Worker(QtCore.QObject):
self.core = core.Core()
self.core.settings = parent.settings
self.modules = parent.core.modules
- self.stackedWidget = parent.window.stackedWidget
self.parent = parent
parent.videoTask.connect(self.createVideo)
self.sampleSize = 1470
@@ -280,7 +279,6 @@ class Worker(QtCore.QObject):
self.error = False
self.canceled = False
- self.parent.drawPreview()
self.stopped = True
self.encoding.emit(False)
self.videoCreated.emit()