Commit 8a53d42d by Stephen

init checkin for ChromecastConverter

parents
File added
import os, time
from PyQt4 import QtGui, QtCore
import ChromecastConverter
from Widgets import *
class Actions(QtCore.QObject):
def __init__(self, parent = None):
super(Actions, self).__init__(parent)
self.mainWidget = parent
@QtCore.pyqtSlot(list)
def updateOutputsListAction(self,fileList=[]):
if fileList == []:
widget = self.mainWidget.inputsPane.fileListWidget
for i in range(0,widget.count()):
item = widget.item(i)
fileList.append(str(item.text()))
self.mainWidget.outputsPane.fileListWidget.clear()
fullPathBox = self.mainWidget.outputsPane.filePathCheckbox.isChecked()
for fileName in fileList:
outputPathLocation = self.mainWidget.outputsPane.outputLocationTextbox.text()
if fullPathBox:
outputFileName = '/'.join([str(outputPathLocation),str(fileName)]).replace('//','/')
else:
outputFileName = str(fileName).split('/')[-1]
outputListWigetItem = OutputListWidgetItem(outputFileName)
self.mainWidget.outputsPane.fileListWidget.addItem(outputListWigetItem)
if not fileList:
self.mainWidget.outputsPane.fileListWidget.clear()
@QtCore.pyqtSlot(int)
def updateFullPath(self,state):
fileList = []
widget = self.mainWidget.inputsPane.fileListWidget
for i in range(0,widget.count()):
item = widget.item(i)
fileList.append(str(item.text()))
self.mainWidget.outputsPane.fileListWidget.clear()
fullPathBox = self.mainWidget.outputsPane.filePathCheckbox.isChecked()
for fileName in fileList:
outputPathLocation = self.mainWidget.outputsPane.outputLocationTextbox.text()
if fullPathBox:
outputFileName = '/'.join([str(outputPathLocation),str(fileName).split('/')[-1]]).replace('//','/')
else:
outputFileName = str(fileName).split('/')[-1]
outputListWigetItem = OutputListWidgetItem(outputFileName)
self.mainWidget.outputsPane.fileListWidget.addItem(outputListWigetItem)
if not fileList:
self.mainWidget.outputsPane.fileListWidget.clear()
@QtCore.pyqtSlot(QtCore.QString)
def updatePathLocation(self,path):
fileList = []
widget = self.mainWidget.inputsPane.fileListWidget
for i in range(0,widget.count()):
item = widget.item(i)
fileList.append(str(item.text()))
self.mainWidget.outputsPane.fileListWidget.clear()
fullPathBox = self.mainWidget.outputsPane.filePathCheckbox.isChecked()
for fileName in fileList:
outputPathLocation = self.mainWidget.outputsPane.outputLocationTextbox.text()
if fullPathBox:
outputFileName = '/'.join([str(outputPathLocation),str(fileName).split('/')[-1]]).replace('//','/')
else:
outputFileName = str(fileName).split('/')[-1]
outputListWigetItem = OutputListWidgetItem(outputFileName)
self.mainWidget.outputsPane.fileListWidget.addItem(outputListWigetItem)
if not fileList:
self.mainWidget.outputsPane.fileListWidget.clear()
def getFileList(self):
fileList = []
rowCount = self.mainWidget.inputsPane.fileListWidget.count()
checkBoxValue = self.mainWidget.outputsPane.filePathCheckbox.isChecked()
aQual = self.mainWidget.dockPane.audioGroupBox.getOptions()
vQual,fileExt = self.mainWidget.dockPane.videoGroupBox.getOptions()
for i in range(rowCount):
inputRowItem = str(self.mainWidget.inputsPane.fileListWidget.item(i).text())
outputRowItem = str(self.mainWidget.outputsPane.fileListWidget.item(i).text())
if not checkBoxValue:
path = str(self.mainWidget.outputsPane.outputLocationTextbox.text())
outputFileName = '/'.join([path,outputRowItem]).replace('//','/')
outputFileName = os.path.splitext(outputFileName)[0]+'.'+fileExt
else:
outputFileName = outputRowItem
outputFileName = os.path.splitext(outputFileName)[0]+'.'+fileExt
fileList.append((inputRowItem,outputFileName))
totalFileCount = len(fileList)
self.mainWidget.progressBar.reset()
self.mainWidget.progressBar.setRange(1,totalFileCount)
self.convertFiles(fileList)
def convertFiles(self,fileList):
aQual = self.mainWidget.dockPane.audioGroupBox.getOptions()
vQual,fileExt = self.mainWidget.dockPane.videoGroupBox.getOptions()
kwargs = {
"fileList" : fileList,
"audioQuality" : aQual,
"videoQuality" : vQual,
}
self.convertThread = ConverterThread(**kwargs)
self.convertThread.updateProgressbar.connect(self.updateProgressbar)
self.convertThread.updateStatusbar.connect(self.updateStatusbar)
self.convertThread.finished.connect(self.enableWidgets)
# self.convertThread.run(**kwargs)
self.convertThread.start()
self.disableWidgets()
# items = (self.mainWidget.main_layout.itemAt(i) for i in range(self.mainWidget.main_layout.count()))
# for w in items:
# print w
def updateProgressbar(self,value):
self.mainWidget.progressBar.setValue(value)
QtGui.QApplication.processEvents()
def updateStatusbar(self,message):
self.mainWidget.messageBar.showMessage(message)
QtGui.QApplication.processEvents()
def skippedProcess(self):
self.convertThread.terminate()
msg = "Process Skipped!"
self.mainWidget.messageBar.showMessage(msg)
self.enableWidgets()
def disableWidgets(self):
self.mainWidget.inputsPane.setEnabled(False)
self.mainWidget.outputsPane.setEnabled(False)
self.mainWidget.dockPane.setEnabled(False)
self.mainWidget.processButton.setText('Abort!')
self.mainWidget.processButton.released.connect(self.skippedProcess)
def enableWidgets(self):
self.mainWidget.inputsPane.setEnabled(True)
self.mainWidget.outputsPane.setEnabled(True)
self.mainWidget.dockPane.setEnabled(True)
self.mainWidget.processButton.setText('Process')
self.mainWidget.processButton.released.connect(self.getFileList)
class ConverterThread(QtCore.QThread):
updateProgressbar = QtCore.pyqtSignal(int)
updateStatusbar = QtCore.pyqtSignal(str)
def __init__(self, parent=None,*args,**kwargs):
super(ConverterThread, self).__init__(parent)
self.Converter = ChromecastConverter.Converter(listeners=[self.updateStatus])
self.fileList = kwargs['fileList']
self.aQual = kwargs['audioQuality']
self.vQual = kwargs['videoQuality']
def run(self,*args,**kwargs):
for i, files in enumerate(self.fileList):
inFile,outFile = files
self.Converter.convertFile(inFile,outFile,self.aQual,self.vQual)
self.updateProgressbar.emit(i+1)
msg = "Complete: %s"%outFile
self.updateStatusbar.emit(msg)
self.updateProgressbar.emit(len(self.fileList))
self.updateStatusbar.emit('Converstion Complete')
# self.finished.emit()
pass
def updateStatus(self,message):
self.updateStatusbar.emit(message)
def terminate(self):
self.Converter.childProcess.kill()
self.quit()
File added
import sys, os, re, json, subprocess, datetime
CWD = os.path.dirname(os.path.realpath(__file__))
LOGPATH = os.path.join(CWD,'logs')
class Converter(object):
def __init__(self, *args,**kwargs):
self.loadConfig()
if kwargs.has_key('listeners'):
self.listeners = kwargs['listeners']
else:
self.listeners = []
if kwargs.has_key('logPath'):
self.logPath = kwargs['logPath']
else: self.logPath = LOGPATH
if not os.path.isdir(self.logPath):
os.mkdir(self.logPath)
def loadConfig(self):
f = open(os.path.join(CWD,'config'),'r')
self.config = json.loads(f.read())
f.close()
def checkFile(self,fileName):
return os.path.isfile(fileName)
def preprocessCheck(self,inFile,outFile):
if os.path.isfile(inFile):
outFileDir = '/'.join(str(outFile).split('/')[:-1])
if not os.path.isdir(outFileDir):
msg = "Output directory does not exist: %s" %outFileDir
raise PreprocessError(message=msg)
else:
msg = "File does not exist: %s" %inFile
raise PreprocessError(message=msg)
def convertFile(self,inFile,outFile,aQual,vQual):
try:
self.preprocessCheck(inFile,outFile)
except PreprocessError as e:
print e.message
else:
acodec = self.config['codec']['audio']['default']
vcodec = self.config['codec']['video']['default']
vQuality = self.config['quality']['video'][vQual]
aQuality = self.config['quality']['audio'][aQual]
cmd = 'ffmpeg -i "%s" -y %s %s %s %s "%s"' %(inFile, vcodec,vQuality,acodec,aQuality,outFile)
self.runListeners(cmd)
print cmd
try:
output = self.execute(cmd)
except ProcessError as e:
print e.command
def execute(self,command):
self.childProcess = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
logFileName = datetime.datetime.now().strftime('%F_%I%M%S%f').replace('-','')+'.log'
logFilePath = os.path.join(self.logPath,logFileName)
outMessage = "Processing..."
out = ''
outputBuffer = ''
while True:
output = self.childProcess.stderr.read(128)
outputBuffer = outputBuffer + output
with open(logFilePath, "a") as logFile:
logFile.write(output)
if self.childProcess.poll() != None:
break
if outputBuffer.split('\r'):
out = outputBuffer.split('\r')
outputBuffer = out.pop(-1)
if out: outMessage = ' '.join(str(out[-1]).split()).replace('= ','=')
self.runListeners(outMessage)
def runListeners(self, info):
for func in self.listeners:
func(info)
class PreprocessError(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
class ProcessError(Exception):
def __init__(self, command, exitCode, output):
self.command = command
self.output = output
self.exitCode = exitCode
def __str__(self):
return repr(self.command,self.output,self.exitCode)
import sys,os
from PyQt4 import QtGui, QtCore, Qt
import Actions
from Widgets import *
class ChromecastConverterApp(QtGui.QMainWindow):
def __init__(self, parent = None):
super(ChromecastConverterApp, self).__init__(parent)
self.main_layout = QtGui.QVBoxLayout()
centralWidget = QtGui.QWidget()
centralWidgetLayout = QtGui.QVBoxLayout()
self.inputsPane = InputsPane('File Inputs:')
self.outputsPane = OutputsPane('File Outputs:')
self.dockPane = OptionsPane("Options:")
progressLayout = QtGui.QHBoxLayout()
self.processButton = QtGui.QPushButton("Process")
self.progressBar = QtGui.QProgressBar()
progressLayout.addWidget(self.progressBar)
progressLayout.addWidget(self.processButton)
self.messageBar = self.statusBar()
centralWidgetLayout.addWidget(self.inputsPane)
centralWidgetLayout.addWidget(self.outputsPane)
# centralWidgetLayout.addWidget(self.processButton)
centralWidgetLayout.addLayout(progressLayout)
centralWidget.setLayout(centralWidgetLayout)
self.main_layout.addWidget(centralWidget)
self.setCentralWidget(centralWidget)
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dockPane)
self.setWindowTitle('ChromecastConverterApp')
self.resize(800,600)
self.setGUIActions()
def setGUIActions(self):
actions = Actions.Actions(parent=self)
self.inputsPane.updateOutputsList.connect(actions.updateOutputsListAction)
self.outputsPane.filePathCheckbox.stateChanged.connect(actions.updateFullPath)
self.outputsPane.outputLocationTextbox.textChanged.connect(actions.updatePathLocation)
self.processButton.released.connect(actions.getFileList)
actions.updateStatusbar("Welcome to ChromecastConverter 1.0")
import sys, os
from PyQt4 import QtGui, QtCore, Qt
USER = os.getenv("USER")
class InputsPane(QtGui.QGroupBox):
updateOutputsList = QtCore.pyqtSignal(list)
def __init__(self, parent=None):
super(InputsPane, self).__init__(parent)
main_layout = QtGui.QVBoxLayout()
self.fileListWidget = QtGui.QListWidget()
self.clearButton = QtGui.QPushButton("Clear All")
self.removeSelectedButton = QtGui.QPushButton("Remove Selected")
self.browseButton = QtGui.QPushButton('Browse')
buttonLayout = QtGui.QHBoxLayout()
buttonLayout.addWidget(self.clearButton)
buttonLayout.addWidget(self.removeSelectedButton)
buttonLayout.addWidget(self.browseButton)
self.clearButton.released.connect(self.clearAction)
self.removeSelectedButton.released.connect(self.removeSelectedAction)
self.browseButton.released.connect(self.showFileDialog)
main_layout.addWidget(self.fileListWidget)
main_layout.addLayout(buttonLayout)
self.setLayout(main_layout)
def showFileDialog(self):
userPath = '/Users/%s/Desktop'%USER
dialog = QtGui.QFileDialog.getOpenFileNames(self, "Select movie files to convert",userPath)
outputFiles = []
for fname in dialog:
fileName = str(fname).split('/')[-1]
listWidgetItem = QtGui.QListWidgetItem(fname)
self.fileListWidget.addItem(listWidgetItem)
outputFiles.append(str(fname))
self.updateOutputsList.emit(outputFiles)
def clearAction(self):
self.fileListWidget.clear()
self.updateOutputsList.emit([])
def removeSelectedAction(self):
removeItemList = []
for item in self.fileListWidget.selectedItems():
index = self.fileListWidget.indexFromItem(item).row()
i = self.fileListWidget.takeItem(index)
self.updateOutputsList.emit([])
class OutputsPane(QtGui.QGroupBox):
def __init__(self, parent=None):
super(OutputsPane, self).__init__(parent)
main_layout = QtGui.QVBoxLayout()
self.filePathCheckbox = QtGui.QCheckBox("View Full Path")
# self.fileListWidget = QtGui.QListWidget()
self.fileListWidget = OutputListWidget()
outputLocationLayout = QtGui.QHBoxLayout()
outputLocationLabel = QtGui.QLabel("Output Location:")
self.outputLocationTextbox = QtGui.QLineEdit('/Users/%s/Desktop/'%USER)
self.outputLocationButton = QtGui.QPushButton("Browse")
self.outputLocationButton.released.connect(self.showFileDialog)
outputLocationLayout.addWidget(outputLocationLabel)
outputLocationLayout.addWidget(self.outputLocationTextbox)
outputLocationLayout.addWidget(self.outputLocationButton)
main_layout.addWidget(self.filePathCheckbox)
main_layout.addWidget(self.fileListWidget)
main_layout.addLayout(outputLocationLayout)
self.setLayout(main_layout)
def showFileDialog(self):
userPath = '/Users/%s/Desktop'%USER
dialog = QtGui.QFileDialog.getExistingDirectory(self, "Select movie files to convert",userPath,QtGui.QFileDialog.ShowDirsOnly)
self.outputLocationTextbox.setText(dialog)
class OptionsPane(QtGui.QDockWidget):
def __init__(self, parent=None):
super(OptionsPane, self).__init__(parent)
self.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea)
self.setFeatures(QtGui.QDockWidget.DockWidgetMovable)
main_layout = QtGui.QVBoxLayout()
self.mainWidget = QtGui.QWidget(self)
self.audioGroupBox = AudioOptions()
self.videoGroupBox = VideoOptions()
main_layout.addWidget(self.videoGroupBox)
main_layout.addWidget(self.audioGroupBox)
self.mainWidget.setLayout(main_layout)
self.setWidget(self.mainWidget)
self.setMinimumWidth(300)
# self.setLayout(main_layout)
class AudioOptions(QtGui.QGroupBox):
def __init__(self, parent=None):
super(AudioOptions, self).__init__(parent)
self.qualDropDown = QtGui.QComboBox()
self.populateDropDown()
main_layout = QtGui.QVBoxLayout()
main_layout.addWidget(self.qualDropDown)
main_layout.addStretch(0)
self.setLayout(main_layout)
self.setTitle("Audio Options")
def populateDropDown(self):
self.qualDropDown.addItem('Highest')
self.qualDropDown.addItem('Higher')
self.qualDropDown.addItem('High')
self.qualDropDown.addItem('Medium')
self.qualDropDown.addItem('Low')
def getOptions(self):
return str(self.qualDropDown.currentText()).lower()
class VideoOptions(QtGui.QGroupBox):
def __init__(self, parent=None):
super(VideoOptions, self).__init__(parent)
self.qualDropDown = QtGui.QComboBox()
self.extDropDown = QtGui.QComboBox()
self.populateDropDown()
main_layout = QtGui.QVBoxLayout()
qualLayout = QtGui.QHBoxLayout()
qualLabel = QtGui.QLabel('Quality:')
qualLayout.addWidget(qualLabel)
qualLayout.addWidget(self.qualDropDown)
extLayout = QtGui.QHBoxLayout()
extLabel = QtGui.QLabel('Container:')
extLayout.addWidget(extLabel)
extLayout.addWidget(self.extDropDown)
main_layout.addLayout(qualLayout)
main_layout.addLayout(extLayout)
main_layout.addStretch(0)
self.setLayout(main_layout)
self.setTitle("Video Options")
def populateDropDown(self):
self.qualDropDown.addItem('Highest')
self.qualDropDown.addItem('Higher')
self.qualDropDown.addItem('High')
self.qualDropDown.addItem('Medium')
self.qualDropDown.addItem('Low')
self.extDropDown.addItem('mp4')
self.extDropDown.addItem('mkv')
def getOptions(self):
return (str(self.qualDropDown.currentText()).lower(),str(self.extDropDown.currentText()).lower())
class OutputListWidgetItem(QtGui.QListWidgetItem):
def __init__(self, parent=None):
super(OutputListWidgetItem, self).__init__(parent)
def contextMenuEvent(self, event):
menu = QtGui.QMenu(self)
Action = menu.addAction("I am a " + self.name + " Action")
Action.triggered.connect(self.printName)
menu.exec_(event.globalPos())
def printName(self):
print "Action triggered from " + self.name
class OutputListWidget(QtGui.QListWidget):
def __init__(self, parent=None):
super(OutputListWidget, self).__init__(parent)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.customContextMenu)
def customContextMenu(self, pos):
# menu = QtGui.QMenu(self)
# Action = menu.addAction("I am a " + self.name + " Action")
# Action.triggered.connect(self.printName)
# menu.exec_(event.globalPos())
item = self.itemAt(pos)
if item is not None:
menu = QtGui.QMenu("Context Menu", self)
menu.addAction("Rename", self.renameDialog)
ret = menu.exec_(self.mapToGlobal(pos))
def renameDialog(self):
newName, ok = QtGui.QInputDialog.getText(self, 'Input Dialog',
'Enter your name:')
if ok:
# self.le.setText(str(text))
print ok,newName
items = self.selectedItems()
for item in items:
item.setText(newName)
# cursor = QtGui.QCursor()
# print cursor
# pos = cursor.pos()
# print pos
# widgetItem = self.itemAt(pos)
# print self, self.itemAt(pos)
# widgetItem.setText(newName)
def getNewName(self):
print "GET NEW NAME"
pass
class RenameOutputWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(RenameOutputWidget, self).__init__(parent)
dialogLayout = QtGui.QVBoxLayout()
renameLabel = QtGui.QLabel("Rename:")
self.renameLine = QtGui.QLineEdit()
self.okayButton = QtGui.QPushButton("Ok")
# okayButton.released.connect(self.getNewName)
dialogLayout.addWidget(renameLabel)
dialogLayout.addWidget(self.renameLine)
dialogLayout.addWidget(self.okayButton)
self.setLayout(dialogLayout)
class RenameFileInput(QtGui.QWidget):
def __init__(self):
super(RenameFileInput, self).__init__()
self.initUI()
def initUI(self):
self.btn = QtGui.QPushButton('Dialog', self)
self.btn.move(20, 20)
self.btn.clicked.connect(self.showDialog)
self.le = QtGui.QLineEdit(self)
self.le.move(130, 22)
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Input dialog')
# self.show()
def showDialog(self):
text, ok = QtGui.QInputDialog.getText(self, 'Input Dialog',
'Enter your name:')
if ok:
self.le.setText(str(text))
File added
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui
from ChromecastConverterApp import *
def main():
app = QtGui.QApplication(sys.argv)
cca = ChromecastConverterApp()
cca.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
\ No newline at end of file
File added
{"quality": {"audio": {"high": "-q:a 900", "medium": "-q:a 700", "highest": "-q:a 1300", "low": "-qscale:a 400", "higher": "-qscale:a 1000"}, "video": {"high": "-preset slow -crf 23", "medium": "-preset slow -crf 23", "highest": "-preset veryslow -crf 18", "low": "-preset medium -crf 23", "higher": "-preset slow -crf 20"}}, "codec": {"audio": {"default": "-c:a libfaac"}, "video": {"default": "-c:v libx264"}}}
\ No newline at end of file
File added
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment