diff --git a/setup.py b/setup.py index 9d826456cf..1bdba4b3f3 100644 --- a/setup.py +++ b/setup.py @@ -12,11 +12,11 @@ ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -#!/usr/bin/env python import sys, re, os, shutil sys.path.append('src') from libprs500 import __version__ as VERSION from libprs500 import __appname__ as APPNAME +from libprs500 import islinux entry_points = { 'console_scripts': [ \ @@ -33,10 +33,12 @@ entry_points = { 'web2lrf = libprs500.ebooks.lrf.web.convert_from:main', 'pdf2lrf = libprs500.ebooks.lrf.pdf.convert_from:main', 'any2lrf = libprs500.ebooks.lrf.any.convert_from:main', - 'lrf2lrs = libprs500.ebooks.lrf.parser:main', - 'lrfviewer = libprs500.gui2.lrf_renderer.main:main', + 'lrf2lrs = libprs500.ebooks.lrf.parser:main', ], - 'gui_scripts' : [ APPNAME+' = libprs500.gui2.main:main'] + 'gui_scripts' : [ + APPNAME+' = libprs500.gui2.main:main', + 'lrfviewer = libprs500.gui2.lrf_renderer.main:main', + ], } def _ep_to_script(ep, base='src'): @@ -125,5 +127,5 @@ if __name__ == '__main__': ] ) - if 'develop' in ' '.join(sys.argv): + if 'develop' in ' '.join(sys.argv) and islinux: subprocess.check_call('libprs500_postinstall', shell=True) \ No newline at end of file diff --git a/src/libprs500/ebooks/lrf/rtf/convert_from.py b/src/libprs500/ebooks/lrf/rtf/convert_from.py index c1863d4a76..b54e107a91 100644 --- a/src/libprs500/ebooks/lrf/rtf/convert_from.py +++ b/src/libprs500/ebooks/lrf/rtf/convert_from.py @@ -19,13 +19,11 @@ from libprs500.ebooks.metadata.meta import get_metadata from libprs500.ebooks.lrf.html.convert_from import process_file as html_process_file from libprs500.ebooks import ConversionError from libprs500 import isosx, setup_cli_handlers, __appname__ +from libprs500.libwand import convert, WandException UNRTF = 'unrtf' -CONVERT = 'convert' if isosx and hasattr(sys, 'frameworks_dir'): - UNRTF = os.path.join(sys.frameworks_dir, UNRTF) - CONVERT = os.path.join(sys.frameworks_dir, CONVERT) - + UNRTF = os.path.join(getattr(sys, 'frameworks_dir'), UNRTF) def option_parser(): return lrf_option_parser( @@ -38,9 +36,9 @@ def convert_images(html, logger): for wmf in wmfs: target = os.path.join(os.path.dirname(wmf), os.path.splitext(os.path.basename(wmf))[0]+'.jpg') try: - subprocess.check_call(CONVERT + ' ' + wmf + ' ' + target, shell=True) + convert(wmf, target) html = html.replace(os.path.basename(wmf), os.path.basename(target)) - except Exception, err: + except WandException, err: logger.warning(u'Unable to convert image %s with error: %s'%(wmf, unicode(err))) continue return html @@ -57,15 +55,16 @@ def generate_html(rtfpath, logger): cmd = ' '.join([UNRTF, '"'+rtfpath+'"']) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - file.write(convert_images(p.stdout.read(), logger)) + raw = p.stdout.read() ret = p.wait() if ret != 0: - if isosx and ret == -11: #unrtf segfaults on OSX but seems to convert most of the file. - file.write('\n') + if len(raw) > 1000: #unrtf crashes occassionally on OSX and windows but still convert correctly + raw += '\n' else: logger.critical(p.stderr.read()) raise ConversionError, 'unrtf failed with error code: %d'%(ret,) - file.close() + file.write(convert_images(raw, logger)) + file.close() return path finally: os.chdir(cwd) @@ -86,18 +85,16 @@ def process_file(path, options, logger=None): ext = '.lrs' if options.lrs else '.lrf' options.output = os.path.abspath(os.path.basename(os.path.splitext(path)[0]) + ext) options.output = os.path.abspath(os.path.expanduser(options.output)) - if (not options.title or options.title == 'Unknown') and mi.title: - sys.argv.append('-t') - sys.argv.append('"'+mi.title+'"') + if not mi.title: + mi.title = os.path.splitext(os.path.basename(rtf))[0] + if (not options.title or options.title == 'Unknown'): + options.title = mi.title if (not options.author or options.author == 'Unknown') and mi.author: - sys.argv.append('-a') - sys.argv.append('"'+mi.author+'"') + options.author = mi.author if (not options.category or options.category == 'Unknown') and mi.category: - sys.argv.append('--category') - sys.argv.append('"'+mi.category+'"') + options.category = mi.category if (not options.freetext or options.freetext == 'Unknown') and mi.comments: - sys.argv.append('--comment') - sys.argv.append('"'+mi.comments+'"') + options.freetext = mi.comments html_process_file(html, options, logger) finally: shutil.rmtree(tdir) diff --git a/src/libprs500/libwand.py b/src/libprs500/libwand.py new file mode 100644 index 0000000000..b791034d6c --- /dev/null +++ b/src/libprs500/libwand.py @@ -0,0 +1,67 @@ +## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import ctypes, os, sys + +from libprs500 import iswindows, isosx + +class WandException(Exception): + pass + +_lib_name = 'CORE_RL_wand_.dll' if iswindows else 'libWand.dylib' if isosx else 'libWand.so' +if iswindows and hasattr(sys, 'frozen'): + im_dir = os.path.join(os.path.dirname(sys.executable), 'ImageMagick') + os.putenv('PATH', im_dir + ';' + os.environ['PATH']) +_libwand = None +try: + _libwand = ctypes.cdll.LoadLibrary(_lib_name) +except: + pass + + + +class Severity(ctypes.c_long): + pass + +class String(ctypes.c_char_p): + + def __del__(self): + _libwand.MagickRelinquishMemory(self) + + def __str__(self): + return self.value + +if _libwand is not None: + _libwand.MagickGetException.argtypes = [ctypes.c_void_p, ctypes.POINTER(Severity)] + _libwand.MagickGetException.restype = String + +def get_exception(wand): + severity = Severity() + desc = _libwand.MagickGetException(wand, ctypes.byref(severity)) + return str(desc) + +def convert(source, dest): + if _libwand is None: + raise WandException('Could not find ImageMagick library') + if not _libwand.MagickWandGenesis(): + raise WandException('Unable to initialize Image Magick') + wand = _libwand.NewMagickWand() + if wand <= 0: + raise WandException('Unable to initialize Image Magick. Cannot create wand.') + if not _libwand.MagickReadImage(wand, source): + raise WandException('Cannot read image %s: %s'%(source, get_exception(wand))) + if not _libwand.MagickWriteImage(wand, dest): + raise WandException('Cannot write image to file %s: %s'%(source, get_exception(wand))) + _libwand.DestroyMagickWand(wand) + _libwand.MagickWandTerminus() \ No newline at end of file diff --git a/windows_installer.py b/windows_installer.py index ff3c5c1d4c..06759f78c6 100644 --- a/windows_installer.py +++ b/windows_installer.py @@ -59,6 +59,7 @@ Var MUI_TEMP !define CLIT "C:\clit\clit.exe" !define UNRTF "C:\unrtf\unrtf.exe" !define PDFTOHTML "C:\pdftohtml\pdftohtml.exe" +!define IMAGEMAGICK "C:\ImageMagick" ;------------------------------------------------------------------------------------------------------ ;General @@ -129,6 +130,10 @@ Section "Main" "secmain" File "${CLIT}" File "${UNRTF}" File "${PDFTOHTML}" + + SetOutPath "$INSTDIR\ImageMagick" + File /r "${IMAGEMAGICK}\*" + SetOutPath "$SYSDIR" File "${LIBUNRAR_DIR}\unrar.dll" @@ -151,6 +156,7 @@ Section "Main" "secmain" WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${WEBSITE}" CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\libprs500.lnk" "$INSTDIR\${PRODUCT_NAME}.exe" + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\lrfviewer.lnk" "$INSTDIR\lrfviewer.exe" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\libprs500.exe" @@ -424,17 +430,24 @@ console = [dict(dest_base=basenames['console'][i], script=scripts['console'][i]) setup( cmdclass = {'py2exe': BuildEXE}, - windows = [{'script' : scripts['gui'][0], + windows = [ + {'script' : scripts['gui'][0], 'dest_base' : APPNAME, 'icon_resources' : [(1, 'icons/library.ico')], 'other_resources' : [BuildEXE.manifest(APPNAME)], - },], + }, + {'script' : scripts['gui'][1], + 'dest_base' : 'lrfviewer', + 'icon_resources' : [(1, 'icons/viewer.ico')], + 'other_resources' : [BuildEXE.manifest('lrfviewer')], + }, + ], console = console, options = { 'py2exe' : {'compressed': 1, 'optimize' : 2, 'dist_dir' : PY2EXE_DIR, 'includes' : ['sip', 'pkg_resources', 'PyQt4.QtSvg', 'mechanize', 'ClientForm'], - 'packages' : ['PIL', 'WmfPlugin'], + 'packages' : ['PIL'], 'excludes' : ["Tkconstants", "Tkinter", "tcl", "_imagingtk", "ImageTk", "FixTk", 'pydoc'],