moved functions into toolkit, fixed CMD appearing on Windows
This commit is contained in:
parent
3a6d7ae421
commit
ba0409829d
|
@ -5,7 +5,7 @@ import sys
|
|||
|
||||
import core
|
||||
import video_thread
|
||||
from main import LoadDefaultSettings
|
||||
from toolkit import LoadDefaultSettings
|
||||
|
||||
|
||||
class Command(QtCore.QObject):
|
||||
|
|
|
@ -8,6 +8,7 @@ from queue import PriorityQueue
|
|||
|
||||
from component import Component, BadComponentInit
|
||||
from frame import BlankFrame
|
||||
from toolkit import openPipe
|
||||
|
||||
|
||||
class Video:
|
||||
|
@ -72,7 +73,7 @@ class Video:
|
|||
self.frameBuffer.task_done()
|
||||
|
||||
def fillBuffer(self):
|
||||
pipe = subprocess.Popen(
|
||||
pipe = openPipe(
|
||||
self.command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, bufsize=10**8
|
||||
)
|
||||
|
@ -217,7 +218,7 @@ class Component(Component):
|
|||
'-ss', '90',
|
||||
'-vframes', '1',
|
||||
]
|
||||
pipe = subprocess.Popen(
|
||||
pipe = openPipe(
|
||||
command, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, bufsize=10**8
|
||||
)
|
||||
|
|
67
src/core.py
67
src/core.py
|
@ -1,21 +1,24 @@
|
|||
'''
|
||||
Home to the Core class which tracks the program state
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
from PyQt5 import QtCore, QtGui, uic
|
||||
from os.path import expanduser
|
||||
import subprocess as sp
|
||||
import numpy
|
||||
from PIL import Image
|
||||
from shutil import rmtree
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
from importlib import import_module
|
||||
from PyQt5.QtCore import QStandardPaths
|
||||
import string
|
||||
|
||||
import toolkit
|
||||
|
||||
|
||||
class Core():
|
||||
|
||||
class Core:
|
||||
'''
|
||||
MainWindow and Command module both use an instance of this class
|
||||
to store the program state. This object tracks the components,
|
||||
opens projects and presets, and stores settings/paths to data.
|
||||
'''
|
||||
def __init__(self):
|
||||
self.dataDir = QStandardPaths.writableLocation(
|
||||
QStandardPaths.AppConfigLocation
|
||||
|
@ -34,7 +37,7 @@ class Core():
|
|||
)
|
||||
|
||||
self.loadEncoderOptions()
|
||||
self.videoFormats = Core.appendUppercase([
|
||||
self.videoFormats = toolkit.appendUppercase([
|
||||
'*.mp4',
|
||||
'*.mov',
|
||||
'*.mkv',
|
||||
|
@ -42,7 +45,7 @@ class Core():
|
|||
'*.webm',
|
||||
'*.flv',
|
||||
])
|
||||
self.audioFormats = Core.appendUppercase([
|
||||
self.audioFormats = toolkit.appendUppercase([
|
||||
'*.mp3',
|
||||
'*.wav',
|
||||
'*.ogg',
|
||||
|
@ -50,7 +53,7 @@ class Core():
|
|||
'*.flac',
|
||||
'*.aac',
|
||||
])
|
||||
self.imageFormats = Core.appendUppercase([
|
||||
self.imageFormats = toolkit.appendUppercase([
|
||||
'*.png',
|
||||
'*.jpg',
|
||||
'*.tif',
|
||||
|
@ -175,7 +178,7 @@ class Core():
|
|||
return False
|
||||
with open(filepath, 'r') as f:
|
||||
for line in f:
|
||||
saveValueStore = Core.presetFromString(line.strip())
|
||||
saveValueStore = toolkit.presetFromString(line.strip())
|
||||
break
|
||||
return saveValueStore
|
||||
|
||||
|
@ -307,7 +310,7 @@ class Core():
|
|||
lastCompVers = str(line)
|
||||
i += 1
|
||||
elif i == 2:
|
||||
lastCompPreset = Core.presetFromString(line)
|
||||
lastCompPreset = toolkit.presetFromString(line)
|
||||
data[section].append((
|
||||
lastCompName,
|
||||
lastCompVers,
|
||||
|
@ -357,7 +360,7 @@ class Core():
|
|||
with open(internalPath, 'r') as f:
|
||||
internalData = [line for line in f]
|
||||
try:
|
||||
saveValueStore = Core.presetFromString(internalData[0].strip())
|
||||
saveValueStore = toolkit.presetFromString(internalData[0].strip())
|
||||
self.createPresetFile(
|
||||
compName, vers,
|
||||
origName, saveValueStore,
|
||||
|
@ -387,7 +390,7 @@ class Core():
|
|||
f.write('[Components]\n')
|
||||
f.write('%s\n' % compName)
|
||||
f.write('%s\n' % str(vers))
|
||||
f.write(Core.presetToString(saveValueStore))
|
||||
f.write(toolkit.presetToString(saveValueStore))
|
||||
|
||||
def createProjectFile(self, filepath, window=None):
|
||||
'''Create a project file (.avp) using the current program state'''
|
||||
|
@ -411,7 +414,7 @@ class Core():
|
|||
saveValueStore = comp.savePreset()
|
||||
f.write('%s\n' % str(comp))
|
||||
f.write('%s\n' % str(comp.version()))
|
||||
f.write('%s\n' % Core.presetToString(saveValueStore))
|
||||
f.write('%s\n' % toolkit.presetToString(saveValueStore))
|
||||
|
||||
f.write('\n[Settings]\n')
|
||||
for key in self.settings.allKeys():
|
||||
|
@ -450,7 +453,9 @@ class Core():
|
|||
else:
|
||||
try:
|
||||
with open(os.devnull, "w") as f:
|
||||
sp.check_call(['ffmpeg', '-version'], stdout=f, stderr=f)
|
||||
sp.check_call(
|
||||
['ffmpeg', '-version'], stdout=f, stderr=f
|
||||
)
|
||||
return "ffmpeg"
|
||||
except:
|
||||
return "avconv"
|
||||
|
@ -459,10 +464,9 @@ class Core():
|
|||
command = [self.FFMPEG_BIN, '-i', filename]
|
||||
|
||||
try:
|
||||
fileInfo = sp.check_output(command, stderr=sp.STDOUT, shell=False)
|
||||
fileInfo = toolkit.checkOutput(command, stderr=sp.STDOUT)
|
||||
except sp.CalledProcessError as ex:
|
||||
fileInfo = ex.output
|
||||
pass
|
||||
|
||||
info = fileInfo.decode("utf-8").split('\n')
|
||||
for line in info:
|
||||
|
@ -480,7 +484,7 @@ class Core():
|
|||
'-ar', '44100', # ouput will have 44100 Hz
|
||||
'-ac', '1', # mono (set to '2' for stereo)
|
||||
'-']
|
||||
in_pipe = sp.Popen(
|
||||
in_pipe = toolkit.openPipe(
|
||||
command, stdout=sp.PIPE, stderr=sp.DEVNULL, bufsize=10**8)
|
||||
|
||||
completeAudioArray = numpy.empty(0, dtype="int16")
|
||||
|
@ -525,26 +529,3 @@ class Core():
|
|||
|
||||
def reset(self):
|
||||
self.canceled = False
|
||||
|
||||
@staticmethod
|
||||
def badName(name):
|
||||
'''Returns whether a name contains non-alphanumeric chars'''
|
||||
return any([letter in string.punctuation for letter in name])
|
||||
|
||||
@staticmethod
|
||||
def presetToString(dictionary):
|
||||
'''Alphabetizes a dict into OrderedDict & returns string repr'''
|
||||
return repr(
|
||||
OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def presetFromString(string):
|
||||
'''Turns a string repr of OrderedDict into a regular dict'''
|
||||
return dict(eval(string))
|
||||
|
||||
@staticmethod
|
||||
def appendUppercase(lst):
|
||||
for form, i in zip(lst, range(len(lst))):
|
||||
lst.append(form.upper())
|
||||
return lst
|
||||
|
|
Binary file not shown.
35
src/main.py
35
src/main.py
|
@ -7,41 +7,6 @@ import preview_thread
|
|||
import video_thread
|
||||
|
||||
|
||||
def disableWhenEncoding(func):
|
||||
def decorator(*args, **kwargs):
|
||||
if args[0].encoding:
|
||||
return
|
||||
else:
|
||||
return func(*args, **kwargs)
|
||||
return decorator
|
||||
|
||||
|
||||
def LoadDefaultSettings(self):
|
||||
self.resolutions = [
|
||||
'1920x1080',
|
||||
'1280x720',
|
||||
'854x480'
|
||||
]
|
||||
|
||||
default = {
|
||||
"outputWidth": 1280,
|
||||
"outputHeight": 720,
|
||||
"outputFrameRate": 30,
|
||||
"outputAudioCodec": "AAC",
|
||||
"outputAudioBitrate": "192",
|
||||
"outputVideoCodec": "H264",
|
||||
"outputVideoBitrate": "2500",
|
||||
"outputVideoFormat": "yuv420p",
|
||||
"outputPreset": "medium",
|
||||
"outputFormat": "mp4",
|
||||
"outputContainer": "MP4",
|
||||
"projectDir": os.path.join(self.dataDir, 'projects'),
|
||||
}
|
||||
|
||||
for parm, value in default.items():
|
||||
if self.settings.value(parm) is None:
|
||||
self.settings.setValue(parm, value)
|
||||
|
||||
if __name__ == "__main__":
|
||||
mode = 'gui'
|
||||
if len(sys.argv) > 2:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from queue import Queue
|
||||
from PyQt5 import QtCore, QtGui, uic, QtWidgets
|
||||
from PyQt5.QtWidgets import QMenu, QShortcut
|
||||
from queue import Queue
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
|
@ -11,7 +11,7 @@ import core
|
|||
import preview_thread
|
||||
import video_thread
|
||||
from presetmanager import PresetManager
|
||||
from main import LoadDefaultSettings, disableWhenEncoding
|
||||
from toolkit import LoadDefaultSettings, disableWhenEncoding
|
||||
|
||||
|
||||
class PreviewWindow(QtWidgets.QLabel):
|
||||
|
|
|
@ -3,6 +3,7 @@ import string
|
|||
import os
|
||||
|
||||
import core
|
||||
import toolkit
|
||||
|
||||
|
||||
class PresetManager(QtWidgets.QDialog):
|
||||
|
@ -147,7 +148,7 @@ class PresetManager(QtWidgets.QDialog):
|
|||
currentPreset
|
||||
)
|
||||
if OK:
|
||||
if core.Core.badName(newName):
|
||||
if toolkit.badName(newName):
|
||||
self.warnMessage(self.parent.window)
|
||||
continue
|
||||
if newName:
|
||||
|
@ -252,7 +253,7 @@ class PresetManager(QtWidgets.QDialog):
|
|||
self.presetRows[index][2]
|
||||
)
|
||||
if OK:
|
||||
if core.Core.badName(newName):
|
||||
if toolkit.badName(newName):
|
||||
self.warnMessage()
|
||||
continue
|
||||
if newName:
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
'''
|
||||
Common functions
|
||||
'''
|
||||
import string
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
def badName(name):
|
||||
'''Returns whether a name contains non-alphanumeric chars'''
|
||||
return any([letter in string.punctuation for letter in name])
|
||||
|
||||
|
||||
def presetToString(dictionary):
|
||||
'''Alphabetizes a dict into OrderedDict & returns string repr'''
|
||||
return repr(
|
||||
OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
|
||||
)
|
||||
|
||||
|
||||
def presetFromString(string):
|
||||
'''Turns a string repr of OrderedDict into a regular dict'''
|
||||
return dict(eval(string))
|
||||
|
||||
|
||||
def appendUppercase(lst):
|
||||
for form, i in zip(lst, range(len(lst))):
|
||||
lst.append(form.upper())
|
||||
return lst
|
||||
|
||||
|
||||
def checkOutput(commandList, **kwargs):
|
||||
_subprocess(subprocess.check_output)
|
||||
|
||||
|
||||
def openPipe(commandList, **kwargs):
|
||||
_subprocess(subprocess.Popen)
|
||||
|
||||
|
||||
def _subprocess(func, commandList, **kwargs):
|
||||
if not sys.platform == 'win32':
|
||||
# Stop CMD window from appearing on Windows
|
||||
# http://code.activestate.com/recipes/409002/
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
kwargs['startupinfo'] = startupinfo
|
||||
return func(commandList, shell=False, **kwargs)
|
||||
|
||||
|
||||
def disableWhenEncoding(func):
|
||||
def decorator(*args, **kwargs):
|
||||
if args[0].encoding:
|
||||
return
|
||||
else:
|
||||
return func(*args, **kwargs)
|
||||
return decorator
|
||||
|
||||
|
||||
def LoadDefaultSettings(self):
|
||||
self.resolutions = [
|
||||
'1920x1080',
|
||||
'1280x720',
|
||||
'854x480'
|
||||
]
|
||||
|
||||
default = {
|
||||
"outputWidth": 1280,
|
||||
"outputHeight": 720,
|
||||
"outputFrameRate": 30,
|
||||
"outputAudioCodec": "AAC",
|
||||
"outputAudioBitrate": "192",
|
||||
"outputVideoCodec": "H264",
|
||||
"outputVideoBitrate": "2500",
|
||||
"outputVideoFormat": "yuv420p",
|
||||
"outputPreset": "medium",
|
||||
"outputFormat": "mp4",
|
||||
"outputContainer": "MP4",
|
||||
"projectDir": os.path.join(self.dataDir, 'projects'),
|
||||
}
|
||||
|
||||
for parm, value in default.items():
|
||||
if self.settings.value(parm) is None:
|
||||
self.settings.setValue(parm, value)
|
|
@ -13,6 +13,7 @@ from copy import copy
|
|||
import signal
|
||||
|
||||
import core
|
||||
from toolkit import openPipe
|
||||
|
||||
|
||||
class Worker(QtCore.QObject):
|
||||
|
@ -191,7 +192,7 @@ class Worker(QtCore.QObject):
|
|||
self.progressBarUpdate.emit(100)
|
||||
|
||||
# Create ffmpeg pipe and queues for frames
|
||||
self.out_pipe = sp.Popen(
|
||||
self.out_pipe = openPipe(
|
||||
ffmpegCommand, stdin=sp.PIPE, stdout=sys.stdout, stderr=sys.stdout)
|
||||
self.compositeQueue = Queue()
|
||||
self.compositeQueue.maxsize = 20
|
||||
|
|
Reference in New Issue