moved functions into toolkit, fixed CMD appearing on Windows

This commit is contained in:
tassaron 2017-07-04 19:52:52 -04:00
parent 3a6d7ae421
commit ba0409829d
9 changed files with 120 additions and 86 deletions

View File

@ -5,7 +5,7 @@ import sys
import core
import video_thread
from main import LoadDefaultSettings
from toolkit import LoadDefaultSettings
class Command(QtCore.QObject):

View File

@ -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
)

View File

@ -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

BIN
src/core.pyc Normal file

Binary file not shown.

View File

@ -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:

View File

@ -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):

View File

@ -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:

85
src/toolkit.py Normal file
View File

@ -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)

View File

@ -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