mirror of
https://github.com/ciromattia/kcc
synced 2025-12-22 22:22:21 +00:00
Moved MOBI creation to main code (close #111)
This commit is contained in:
@@ -67,6 +67,8 @@ After completed conversion you should find ready file alongside the original inp
|
|||||||
|
|
||||||
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
|
Please check [our wiki](https://github.com/ciromattia/kcc/wiki/) for more details.
|
||||||
|
|
||||||
|
CLI version of KCC is intended for power users. It is not idiot-proof like GUI :-)
|
||||||
|
|
||||||
### Standalone `kcc-c2e.py` usage:
|
### Standalone `kcc-c2e.py` usage:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -75,7 +77,9 @@ Usage: kcc-c2e [options] comic_file|comic_folder
|
|||||||
Options:
|
Options:
|
||||||
MAIN:
|
MAIN:
|
||||||
-p PROFILE, --profile=PROFILE
|
-p PROFILE, --profile=PROFILE
|
||||||
Device profile (Choose one among K1, K2, K345, KDX, KPW, KV, KFHD, KFHDX, KFHDX8, KFA, KoMT, KoG, KoA, KoAHD, KoAH2O) [Default=KV]
|
Device profile (Available options: K1, K2, K345, KDX,
|
||||||
|
KPW, KV, KFHD, KFHDX, KFHDX8, KFA, KoMT, KoG, KoA,
|
||||||
|
KoAHD, KoAH2O) [Default=KV]
|
||||||
-q QUALITY, --quality=QUALITY
|
-q QUALITY, --quality=QUALITY
|
||||||
Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
|
Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]
|
||||||
-m, --manga-style Manga style (Right-to-left reading and splitting)
|
-m, --manga-style Manga style (Right-to-left reading and splitting)
|
||||||
@@ -86,7 +90,8 @@ Options:
|
|||||||
Output generated file to specified directory or file
|
Output generated file to specified directory or file
|
||||||
-t TITLE, --title=TITLE
|
-t TITLE, --title=TITLE
|
||||||
Comic title [Default=filename or directory name]
|
Comic title [Default=filename or directory name]
|
||||||
--cbz-output Outputs a CBZ archive and does not generate EPUB
|
-f FORMAT, --format=FORMAT
|
||||||
|
Output format (Available options: Auto, MOBI, EPUB, CBZ) [Default=Auto]
|
||||||
--batchsplit Split output into multiple files
|
--batchsplit Split output into multiple files
|
||||||
|
|
||||||
PROCESSING:
|
PROCESSING:
|
||||||
|
|||||||
106
kcc/KCC_gui.py
106
kcc/KCC_gui.py
@@ -36,12 +36,10 @@ from subprocess import STDOUT, PIPE
|
|||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
from xml.dom.minidom import parse
|
from xml.dom.minidom import parse
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
from psutil import virtual_memory, Popen, Process
|
from psutil import Popen, Process
|
||||||
from uuid import uuid4
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from .shared import md5Checksum
|
from .shared import md5Checksum
|
||||||
from . import comic2ebook
|
from . import comic2ebook
|
||||||
from . import dualmetafix
|
|
||||||
from . import KCC_rc_web
|
from . import KCC_rc_web
|
||||||
if sys.platform.startswith('darwin'):
|
if sys.platform.startswith('darwin'):
|
||||||
from . import KCC_ui_osx as KCC_ui
|
from . import KCC_ui_osx as KCC_ui
|
||||||
@@ -265,84 +263,14 @@ class ProgressThread(QtCore.QThread):
|
|||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
class WorkerSignals(QtCore.QObject):
|
|
||||||
result = QtCore.pyqtSignal(list)
|
|
||||||
|
|
||||||
|
|
||||||
class KindleGenThread(QtCore.QRunnable):
|
|
||||||
def __init__(self, batch):
|
|
||||||
super(KindleGenThread, self).__init__()
|
|
||||||
self.signals = WorkerSignals()
|
|
||||||
self.work = batch
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
kindlegenErrorCode = 0
|
|
||||||
kindlegenError = ''
|
|
||||||
try:
|
|
||||||
if os.path.getsize(self.work) < 629145600:
|
|
||||||
output = Popen('kindlegen -dont_append_source -locale en "' + self.work + '"', stdout=PIPE,
|
|
||||||
stderr=STDOUT, shell=True)
|
|
||||||
for line in output.stdout:
|
|
||||||
line = line.decode('utf-8')
|
|
||||||
# ERROR: Generic error
|
|
||||||
if "Error(" in line:
|
|
||||||
kindlegenErrorCode = 1
|
|
||||||
kindlegenError = line
|
|
||||||
# ERROR: EPUB too big
|
|
||||||
if ":E23026:" in line:
|
|
||||||
kindlegenErrorCode = 23026
|
|
||||||
if kindlegenErrorCode > 0:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# ERROR: EPUB too big
|
|
||||||
kindlegenErrorCode = 23026
|
|
||||||
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
|
|
||||||
except Exception as err:
|
|
||||||
# ERROR: KCC unknown generic error
|
|
||||||
kindlegenErrorCode = 1
|
|
||||||
kindlegenError = format(err)
|
|
||||||
self.signals.result.emit([kindlegenErrorCode, kindlegenError, self.work])
|
|
||||||
|
|
||||||
|
|
||||||
class DualMetaFixThread(QtCore.QRunnable):
|
|
||||||
def __init__(self, batch):
|
|
||||||
super(DualMetaFixThread, self).__init__()
|
|
||||||
self.signals = WorkerSignals()
|
|
||||||
self.work = batch
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
item = self.work
|
|
||||||
os.remove(item)
|
|
||||||
mobiPath = item.replace('.epub', '.mobi')
|
|
||||||
move(mobiPath, mobiPath + '_toclean')
|
|
||||||
try:
|
|
||||||
# noinspection PyArgumentList
|
|
||||||
dualmetafix.DualMobiMetaFix(mobiPath + '_toclean', mobiPath, bytes(str(uuid4()), 'UTF-8'))
|
|
||||||
self.signals.result.emit([True])
|
|
||||||
except Exception as err:
|
|
||||||
self.signals.result.emit([False, format(err)])
|
|
||||||
|
|
||||||
|
|
||||||
class WorkerThread(QtCore.QThread):
|
class WorkerThread(QtCore.QThread):
|
||||||
#noinspection PyArgumentList
|
#noinspection PyArgumentList
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QtCore.QThread.__init__(self)
|
QtCore.QThread.__init__(self)
|
||||||
self.pool = QtCore.QThreadPool()
|
|
||||||
self.conversionAlive = False
|
self.conversionAlive = False
|
||||||
self.errors = False
|
self.errors = False
|
||||||
self.kindlegenErrorCode = [0]
|
self.kindlegenErrorCode = [0]
|
||||||
self.workerOutput = []
|
self.workerOutput = []
|
||||||
# Let's make sure that we don't fill the memory
|
|
||||||
availableMemory = virtual_memory().total/1000000000
|
|
||||||
if availableMemory <= 2:
|
|
||||||
self.threadNumber = 1
|
|
||||||
elif 2 < availableMemory <= 4:
|
|
||||||
self.threadNumber = 2
|
|
||||||
else:
|
|
||||||
self.threadNumber = 4
|
|
||||||
# Let's make sure that we don't use too many threads
|
|
||||||
if self.threadNumber > QtCore.QThread.idealThreadCount():
|
|
||||||
self.threadNumber = QtCore.QThread.idealThreadCount()
|
|
||||||
self.progressBarTick = MW.progressBarTick
|
self.progressBarTick = MW.progressBarTick
|
||||||
self.addMessage = MW.addMessage
|
self.addMessage = MW.addMessage
|
||||||
|
|
||||||
@@ -361,10 +289,6 @@ class WorkerThread(QtCore.QThread):
|
|||||||
MW.addTrayMessage.emit('Conversion interrupted.', 'Critical')
|
MW.addTrayMessage.emit('Conversion interrupted.', 'Critical')
|
||||||
MW.modeConvert.emit(1)
|
MW.modeConvert.emit(1)
|
||||||
|
|
||||||
def addResult(self, output):
|
|
||||||
MW.progressBarTick.emit('tick')
|
|
||||||
self.workerOutput.append(output)
|
|
||||||
|
|
||||||
def sanitizeTrace(self, traceback):
|
def sanitizeTrace(self, traceback):
|
||||||
return ''.join(format_tb(traceback))\
|
return ''.join(format_tb(traceback))\
|
||||||
.replace('C:\\Users\\AcidWeb\\Documents\\Projekty\\KCC\\', '')\
|
.replace('C:\\Users\\AcidWeb\\Documents\\Projekty\\KCC\\', '')\
|
||||||
@@ -391,8 +315,7 @@ class WorkerThread(QtCore.QThread):
|
|||||||
options.quality = 1
|
options.quality = 1
|
||||||
elif GUI.QualityBox.checkState() == 2:
|
elif GUI.QualityBox.checkState() == 2:
|
||||||
options.quality = 2
|
options.quality = 2
|
||||||
if str(GUI.FormatBox.currentText()) == 'CBZ':
|
options.format = str(GUI.FormatBox.currentText())
|
||||||
options.cbzoutput = True
|
|
||||||
if GUI.currentMode == 1:
|
if GUI.currentMode == 1:
|
||||||
if 'KFH' in profile:
|
if 'KFH' in profile:
|
||||||
options.upscale = True
|
options.upscale = True
|
||||||
@@ -416,10 +339,7 @@ class WorkerThread(QtCore.QThread):
|
|||||||
if GUI.WebtoonBox.isChecked():
|
if GUI.WebtoonBox.isChecked():
|
||||||
options.webtoon = True
|
options.webtoon = True
|
||||||
if float(GUI.GammaValue) > 0.09:
|
if float(GUI.GammaValue) > 0.09:
|
||||||
# noinspection PyTypeChecker
|
|
||||||
options.gamma = float(GUI.GammaValue)
|
options.gamma = float(GUI.GammaValue)
|
||||||
if str(GUI.FormatBox.currentText()) == 'MOBI':
|
|
||||||
options.batchsplit = True
|
|
||||||
|
|
||||||
# Other/custom settings.
|
# Other/custom settings.
|
||||||
if GUI.currentMode > 2:
|
if GUI.currentMode > 2:
|
||||||
@@ -489,16 +409,10 @@ class WorkerThread(QtCore.QThread):
|
|||||||
MW.progressBarTick.emit('tick')
|
MW.progressBarTick.emit('tick')
|
||||||
MW.addMessage.emit('Creating MOBI files', 'info', False)
|
MW.addMessage.emit('Creating MOBI files', 'info', False)
|
||||||
GUI.progress.content = 'Creating MOBI files'
|
GUI.progress.content = 'Creating MOBI files'
|
||||||
self.workerOutput = []
|
work = []
|
||||||
# Number of KindleGen threads depends on the size of RAM
|
|
||||||
self.pool.setMaxThreadCount(self.threadNumber)
|
|
||||||
for item in outputPath:
|
for item in outputPath:
|
||||||
worker = KindleGenThread(item)
|
work.append([item])
|
||||||
worker.signals.result.connect(self.addResult)
|
self.workerOutput = comic2ebook.makeMOBI(work, self)
|
||||||
self.pool.start(worker)
|
|
||||||
self.pool.waitForDone()
|
|
||||||
while len(self.workerOutput) != len(outputPath):
|
|
||||||
sleep(0.1)
|
|
||||||
self.kindlegenErrorCode = [0]
|
self.kindlegenErrorCode = [0]
|
||||||
for errors in self.workerOutput:
|
for errors in self.workerOutput:
|
||||||
if errors[0] != 0:
|
if errors[0] != 0:
|
||||||
@@ -518,15 +432,9 @@ class WorkerThread(QtCore.QThread):
|
|||||||
MW.addMessage.emit('Processing MOBI files', 'info', False)
|
MW.addMessage.emit('Processing MOBI files', 'info', False)
|
||||||
GUI.progress.content = 'Processing MOBI files'
|
GUI.progress.content = 'Processing MOBI files'
|
||||||
self.workerOutput = []
|
self.workerOutput = []
|
||||||
# DualMetaFix is very fast and there is not reason to use multithreading.
|
|
||||||
self.pool.setMaxThreadCount(1)
|
|
||||||
for item in outputPath:
|
for item in outputPath:
|
||||||
worker = DualMetaFixThread(item)
|
self.workerOutput.append(comic2ebook.makeMOBIFix(item))
|
||||||
worker.signals.result.connect(self.addResult)
|
MW.progressBarTick.emit('tick')
|
||||||
self.pool.start(worker)
|
|
||||||
self.pool.waitForDone()
|
|
||||||
while len(self.workerOutput) != len(outputPath):
|
|
||||||
sleep(0.1)
|
|
||||||
for success in self.workerOutput:
|
for success in self.workerOutput:
|
||||||
if not success[0]:
|
if not success[0]:
|
||||||
self.errors = True
|
self.errors = True
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ from xml.dom.minidom import parse
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
from slugify import slugify as slugifyExt
|
from slugify import slugify as slugifyExt
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from subprocess import STDOUT, PIPE
|
||||||
|
from psutil import Popen, virtual_memory
|
||||||
try:
|
try:
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -47,6 +49,7 @@ from . import comic2panel
|
|||||||
from . import image
|
from . import image
|
||||||
from . import cbxarchive
|
from . import cbxarchive
|
||||||
from . import pdfjpgextract
|
from . import pdfjpgextract
|
||||||
|
from . import dualmetafix
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
@@ -955,8 +958,8 @@ def makeParser():
|
|||||||
otherOptions = OptionGroup(psr, "OTHER")
|
otherOptions = OptionGroup(psr, "OTHER")
|
||||||
|
|
||||||
mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KV",
|
mainOptions.add_option("-p", "--profile", action="store", dest="profile", default="KV",
|
||||||
help="Device profile (Choose one among K1, K2, K345, KDX, KPW, KV, KFHD, KFHDX, KFHDX8, KFA,"
|
help="Device profile (Available options: K1, K2, K345, KDX, KPW, KV, KFHD, KFHDX, KFHDX8,"
|
||||||
" KoMT, KoG, KoA, KoAHD, KoAH2O) [Default=KV]")
|
" KFA, KoMT, KoG, KoA, KoAHD, KoAH2O) [Default=KV]")
|
||||||
mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0",
|
mainOptions.add_option("-q", "--quality", type="int", dest="quality", default="0",
|
||||||
help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]")
|
help="Quality of Panel View. 0 - Normal 1 - High 2 - Ultra [Default=0]")
|
||||||
mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
mainOptions.add_option("-m", "--manga-style", action="store_true", dest="righttoleft", default=False,
|
||||||
@@ -968,8 +971,8 @@ def makeParser():
|
|||||||
help="Output generated file to specified directory or file")
|
help="Output generated file to specified directory or file")
|
||||||
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
||||||
help="Comic title [Default=filename or directory name]")
|
help="Comic title [Default=filename or directory name]")
|
||||||
outputOptions.add_option("--cbz-output", action="store_true", dest="cbzoutput", default=False,
|
outputOptions.add_option("-f", "--format", action="store", dest="format", default="Auto",
|
||||||
help="Outputs a CBZ archive and does not generate EPUB")
|
help="Output format (Available options: Auto, MOBI, EPUB, CBZ) [Default=Auto]")
|
||||||
outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
|
outputOptions.add_option("--batchsplit", action="store_true", dest="batchsplit", default=False,
|
||||||
help="Split output into multiple files"),
|
help="Split output into multiple files"),
|
||||||
|
|
||||||
@@ -1016,10 +1019,20 @@ def checkOptions():
|
|||||||
global options
|
global options
|
||||||
options.panelview = True
|
options.panelview = True
|
||||||
options.bordersColor = None
|
options.bordersColor = None
|
||||||
|
if options.format == 'Auto':
|
||||||
|
if options.profile in ['K1', 'K2', 'K345', 'KPW', 'KV', 'KFHD', 'KFHDX', 'KFHDX8', 'KFA']:
|
||||||
|
options.format = 'MOBI'
|
||||||
|
elif options.profile in ['Other']:
|
||||||
|
options.format = 'EPUB'
|
||||||
|
elif options.profile in ['KDX', 'KoMT', 'KoG', 'KoA', 'KoAHD', 'KoAH2O']:
|
||||||
|
options.format = 'CBZ'
|
||||||
if options.white_borders:
|
if options.white_borders:
|
||||||
options.bordersColor = "white"
|
options.bordersColor = 'white'
|
||||||
if options.black_borders:
|
if options.black_borders:
|
||||||
options.bordersColor = "black"
|
options.bordersColor = 'black'
|
||||||
|
# Splitting MOBI is not optional
|
||||||
|
if options.format == 'MOBI':
|
||||||
|
options.batchsplit = True
|
||||||
# Disabling grayscale conversion for Kindle Fire family.
|
# Disabling grayscale conversion for Kindle Fire family.
|
||||||
if 'KFH' in options.profile or options.forcecolor:
|
if 'KFH' in options.profile or options.forcecolor:
|
||||||
options.forcecolor = True
|
options.forcecolor = True
|
||||||
@@ -1048,10 +1061,10 @@ def checkOptions():
|
|||||||
print("ERROR: Kindle for Android profile require --customwidth and --customheight options!")
|
print("ERROR: Kindle for Android profile require --customwidth and --customheight options!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
# CBZ files on Kindle DX/DXG support higher resolution
|
# CBZ files on Kindle DX/DXG support higher resolution
|
||||||
if options.profile == 'KDX' and options.cbzoutput:
|
if options.profile == 'KDX' and options.format == 'CBZ':
|
||||||
options.customheight = 1200
|
options.customheight = 1200
|
||||||
# Ultra mode don't work with CBZ format
|
# Ultra mode don't work with CBZ format
|
||||||
if options.quality == 2 and options.cbzoutput:
|
if options.quality == 2 and options.format == 'CBZ':
|
||||||
options.quality = 1
|
options.quality = 1
|
||||||
# Override profile data
|
# Override profile data
|
||||||
if options.customwidth != 0 or options.customheight != 0:
|
if options.customwidth != 0 or options.customheight != 0:
|
||||||
@@ -1069,7 +1082,7 @@ def checkOptions():
|
|||||||
|
|
||||||
|
|
||||||
def makeBook(source, qtGUI=None):
|
def makeBook(source, qtGUI=None):
|
||||||
"""Generates EPUB/CBZ comic ebook from a bunch of images."""
|
"""Generates MOBI/EPUB/CBZ comic ebook from a bunch of images."""
|
||||||
global GUI
|
global GUI
|
||||||
GUI = qtGUI
|
GUI = qtGUI
|
||||||
if GUI:
|
if GUI:
|
||||||
@@ -1091,7 +1104,7 @@ def makeBook(source, qtGUI=None):
|
|||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('1')
|
GUI.progressBarTick.emit('1')
|
||||||
chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
chapterNames = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
||||||
if 'Ko' in options.profile and options.cbzoutput:
|
if 'Ko' in options.profile and options.format == 'CBZ':
|
||||||
sanitizeTreeKobo(os.path.join(path, 'OEBPS', 'Images'))
|
sanitizeTreeKobo(os.path.join(path, 'OEBPS', 'Images'))
|
||||||
if options.batchsplit:
|
if options.batchsplit:
|
||||||
tomes = splitDirectory(path)
|
tomes = splitDirectory(path)
|
||||||
@@ -1100,7 +1113,7 @@ def makeBook(source, qtGUI=None):
|
|||||||
filepath = []
|
filepath = []
|
||||||
tomeNumber = 0
|
tomeNumber = 0
|
||||||
if GUI:
|
if GUI:
|
||||||
if options.cbzoutput:
|
if options.format == 'CBZ':
|
||||||
GUI.progressBarTick.emit('Compressing CBZ files')
|
GUI.progressBarTick.emit('Compressing CBZ files')
|
||||||
else:
|
else:
|
||||||
GUI.progressBarTick.emit('Compressing EPUB files')
|
GUI.progressBarTick.emit('Compressing EPUB files')
|
||||||
@@ -1111,7 +1124,7 @@ def makeBook(source, qtGUI=None):
|
|||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
tomeNumber += 1
|
tomeNumber += 1
|
||||||
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
options.title = options.baseTitle + ' [' + str(tomeNumber) + '/' + str(len(tomes)) + ']'
|
||||||
if options.cbzoutput:
|
if options.format == 'CBZ':
|
||||||
# if CBZ output wanted, compress all images and return filepath
|
# if CBZ output wanted, compress all images and return filepath
|
||||||
print("\nCreating CBZ file...")
|
print("\nCreating CBZ file...")
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
@@ -1120,7 +1133,7 @@ def makeBook(source, qtGUI=None):
|
|||||||
filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
|
filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
|
||||||
makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"))
|
makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"))
|
||||||
else:
|
else:
|
||||||
print("\nCreating EPUB structure...")
|
print("\nCreating EPUB file...")
|
||||||
buildEPUB(tome, chapterNames, tomeNumber)
|
buildEPUB(tome, chapterNames, tomeNumber)
|
||||||
# actually zip the ePub
|
# actually zip the ePub
|
||||||
if len(tomes) > 1:
|
if len(tomes) > 1:
|
||||||
@@ -1132,4 +1145,92 @@ def makeBook(source, qtGUI=None):
|
|||||||
rmtree(tome, True)
|
rmtree(tome, True)
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('tick')
|
GUI.progressBarTick.emit('tick')
|
||||||
|
if not GUI and options.format == 'MOBI':
|
||||||
|
print("\nCreating MOBI file...")
|
||||||
|
work = []
|
||||||
|
for i in filepath:
|
||||||
|
work.append([i])
|
||||||
|
output = makeMOBI(work, GUI)
|
||||||
|
for errors in output:
|
||||||
|
if errors[0] != 0:
|
||||||
|
print('KINDLEGEN ERROR!')
|
||||||
|
print(errors)
|
||||||
return filepath
|
return filepath
|
||||||
|
for i in filepath:
|
||||||
|
output = makeMOBIFix(i)
|
||||||
|
if not output[0]:
|
||||||
|
print('DUALMETAFIX ERROR!')
|
||||||
|
return filepath
|
||||||
|
else:
|
||||||
|
os.remove(i.replace('.epub', '.mobi') + '_toclean')
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
|
||||||
|
def makeMOBIFix(item):
|
||||||
|
os.remove(item)
|
||||||
|
mobiPath = item.replace('.epub', '.mobi')
|
||||||
|
move(mobiPath, mobiPath + '_toclean')
|
||||||
|
try:
|
||||||
|
dualmetafix.DualMobiMetaFix(mobiPath + '_toclean', mobiPath, bytes(str(uuid4()), 'UTF-8'))
|
||||||
|
return [True]
|
||||||
|
except Exception as err:
|
||||||
|
return [False, format(err)]
|
||||||
|
|
||||||
|
|
||||||
|
def makeMOBIWorkerTick(output):
|
||||||
|
makeMOBIWorkerOutput.append(output)
|
||||||
|
if output[0] != 0:
|
||||||
|
makeMOBIWorkerPool.terminate()
|
||||||
|
if GUI:
|
||||||
|
GUI.progressBarTick.emit('tick')
|
||||||
|
if not GUI.conversionAlive:
|
||||||
|
makeMOBIWorkerPool.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
def makeMOBIWorker(item):
|
||||||
|
item = item[0]
|
||||||
|
kindlegenErrorCode = 0
|
||||||
|
kindlegenError = ''
|
||||||
|
try:
|
||||||
|
if os.path.getsize(item) < 629145600:
|
||||||
|
output = Popen('kindlegen -dont_append_source -locale en "' + item + '"',
|
||||||
|
stdout=PIPE, stderr=STDOUT, shell=True)
|
||||||
|
for line in output.stdout:
|
||||||
|
line = line.decode('utf-8')
|
||||||
|
# ERROR: Generic error
|
||||||
|
if "Error(" in line:
|
||||||
|
kindlegenErrorCode = 1
|
||||||
|
kindlegenError = line
|
||||||
|
# ERROR: EPUB too big
|
||||||
|
if ":E23026:" in line:
|
||||||
|
kindlegenErrorCode = 23026
|
||||||
|
if kindlegenErrorCode > 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# ERROR: EPUB too big
|
||||||
|
kindlegenErrorCode = 23026
|
||||||
|
return [kindlegenErrorCode, kindlegenError, item]
|
||||||
|
except Exception as err:
|
||||||
|
# ERROR: KCC unknown generic error
|
||||||
|
kindlegenErrorCode = 1
|
||||||
|
kindlegenError = format(err)
|
||||||
|
return [kindlegenErrorCode, kindlegenError, item]
|
||||||
|
|
||||||
|
|
||||||
|
def makeMOBI(work, qtGUI=None):
|
||||||
|
global GUI, makeMOBIWorkerPool, makeMOBIWorkerOutput
|
||||||
|
GUI = qtGUI
|
||||||
|
makeMOBIWorkerOutput = []
|
||||||
|
availableMemory = virtual_memory().total/1000000000
|
||||||
|
if availableMemory <= 2:
|
||||||
|
threadNumber = 1
|
||||||
|
elif 2 < availableMemory <= 4:
|
||||||
|
threadNumber = 2
|
||||||
|
else:
|
||||||
|
threadNumber = 4
|
||||||
|
makeMOBIWorkerPool = Pool(threadNumber)
|
||||||
|
for i in work:
|
||||||
|
makeMOBIWorkerPool.apply_async(func=makeMOBIWorker, args=(i, ), callback=makeMOBIWorkerTick)
|
||||||
|
makeMOBIWorkerPool.close()
|
||||||
|
makeMOBIWorkerPool.join()
|
||||||
|
return makeMOBIWorkerOutput
|
||||||
Reference in New Issue
Block a user