%PDF- %PDF-
Direktori : /usr/share/hplip/fax/ |
Current File : //usr/share/hplip/fax/fax.py |
# -*- coding: utf-8 -*- # # (c) Copyright 2015 HP Development Company, L.P. # # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Don Welch # # Std Lib import sys import os import threading import pickle import time import struct # Local from base.g import * from base.codes import * from base.ldif import LDIFParser from base import device, utils, vcard from prnt import cups from base.sixext import BytesIO from base.sixext import to_bytes_utf8, to_long, to_unicode try: from . import coverpages except ImportError: pass try: import dbus except ImportError: log.error("dbus is required for PC send fax.") import warnings # Ignore: .../dbus/connection.py:242: DeprecationWarning: object.__init__() takes no parameters # (occurring on Python 2.6/dBus 0.83/Ubuntu 9.04) warnings.simplefilter("ignore", DeprecationWarning) # Update queue values (Send thread ==> UI) STATUS_IDLE = 0 STATUS_PROCESSING_FILES = 1 STATUS_SENDING_TO_RECIPIENT = 2 STATUS_DIALING = 3 STATUS_CONNECTING = 4 STATUS_SENDING = 5 STATUS_COMPLETED = 6 STATUS_CREATING_COVER_PAGE = 7 STATUS_ERROR = 8 STATUS_BUSY = 9 STATUS_CLEANUP = 10 STATUS_ERROR_IN_CONNECTING = 11 STATUS_ERROR_IN_TRANSMITTING = 12 STATUS_ERROR_PROBLEM_IN_FAXLINE = 13 STATUS_JOB_CANCEL = 14 # Event queue values (UI ==> Send thread) EVENT_FAX_SEND_CANCELED = 1 # Other values in queue are: #EVENT_FAX_RENDER_COMPLETE_BEGIN = 8010 #EVENT_FAX_RENDER_COMPLETE_SENDDATA = 8011 #EVENT_FAX_RENDER_COMPLETE_END = 8012 # **************************************************************************** # # HPLIP G3 Fax File Format (big endian) # # #==============================================# # # File Header: Total 28 bytes # # #..............................................# # # Magic bytes: 8 bytes ("hplip_g3") # # # Format version: 8 bits (1) # # # Total pages in file(=p): 32 bits # # # Hort DPI: 16 bits (200 or 300) # # # Vert DPI: 16 bits (100, 200, or 300) # # # Page Size: 8 bits (0=Unk, 1=Letter, 2=A4, # # # 3=Legal) # # # Resolution: 8 bits (0=Unk, 1=Std, 2=Fine, # # # 3=300DPI) # # # Encoding: 8 bits (2=MH, 4=MMR, 7=JPEG) # # # Reserved1: 32 bits (0) # # # Reserved2: 32 bits (0) # # #----------------------------------------------# # # Page 1 Header: Total 24 bytes # # #..............................................# # # Page number: 32 bits (1 based) # # # Pixels per row: 32 bits # # # Rows this page: 32 bits # # # Image bytes this page(=x): 32 bits # # # Thumbnail bytes this page(=y): 32 bits # # # (thumbnail not present if y == 0) # # # (encoding?) # # # letter: 134 px wide x 173 px high # # # legal: 134 px wide x 221 px high # # # a4 : 134 px wide x 190 px high # # # Reserved3: 32 bits (0) # # #..............................................# # # Image data: x bytes # # #..............................................# # # Thumbnail data: y bytes (if present) # # #----------------------------------------------# # # Page 2 Header: Total 24 bytes # # #..............................................# # # Image Data # # #..............................................# # # Thumbnail data (if present) # # #----------------------------------------------# # # ... Pages 3 - (p-1) ... # # #----------------------------------------------# # # Page p Header: Total 24 bytes # # #..............................................# # # Image Data # # #..............................................# # # Thumbnail data (if present) # # #==============================================# # RESOLUTION_STD = 1 RESOLUTION_FINE = 2 RESOLUTION_300DPI = 3 FILE_HEADER_SIZE = 28 PAGE_HEADER_SIZE = 24 # **************************************************************************** # ##skip_dn = ["uid=foo,ou=People,dc=example,dc=com", ## "uid=bar,ou=People,dc=example,dc=com", "dc=example,dc=com"] class FaxLDIFParser(LDIFParser): def __init__(self, input, db): LDIFParser.__init__(self, input) self.db = db def handle(self, dn, entry): if dn: try: firstname = entry['givenName'][0] except KeyError: try: firstname = entry['firstname'][0] except KeyError: firstname = '' try: lastname = entry['sn'][0] except KeyError: try: lastname = entry['lastname'][0] except KeyError: lastname = '' try: nickname = entry['cn'][0] except KeyError: nickname = firstname + ' ' + lastname try: fax = entry['facsimiletelephonenumber'][0] # fax except KeyError: try: fax = entry['fax'][0] except KeyError: try: fax = entry['workphone'][0] except KeyError: fax = '' try: title = entry['title'][0] except KeyError: try: title = entry['department'][0] except KeyError: title = '' grps = [] try: grps = entry['ou'] except KeyError: pass grps.append(to_unicode('All')) groups = [g for g in grps if g] if nickname: log.debug("Import: name=%s, fax=%s, group(s)=%s, notes=%s" % ( nickname, fax, ','.join(groups), dn)) self.db.set(nickname, title, firstname, lastname, fax, groups, dn) # **************************************************************************** # class FaxAddressBook(object): # Pickle based address book def __init__(self): self._data = {} # # { 'name' : {'name': u'', # 'firstname' : u'', # NOT USED STARTING IN 2.8.9 # 'lastname': u', # NOT USED STARTING IN 2.8.9 # 'title' : u'', # NOT USED STARTING IN 2.8.9 # 'fax': u'', # 'groups' : [u'', u'', ...], # 'notes' : u'', } ... # } # self.load() def load(self): self._fab = "/dev/null" if prop.user_dir != None: self._fab = os.path.join(prop.user_dir, "fab.pickle") #old_fab = os.path.join(prop.user_dir, "fab.db") # Load the existing pickle if present if os.path.exists(self._fab): pickle_file = open(self._fab, "rb") self._data = pickle.load(pickle_file) pickle_file.close() else: self.save() # save the empty file to create the file def set(self, name, title, firstname, lastname, fax, groups, notes): # try: # grps = [to_unicode(s) for s in groups] # except UnicodeDecodeError: # grps = [to_unicode(s.decode('utf-8')) for s in groups] grps = [to_unicode(s) for s in groups] self._data[to_unicode(name)] = {'name' : to_unicode(name), 'title': to_unicode(title), # NOT USED STARTING IN 2.8.9 'firstname': to_unicode(firstname), # NOT USED STARTING IN 2.8.9 'lastname': to_unicode(lastname), # NOT USED STARTING IN 2.8.9 'fax': to_unicode(fax), 'notes': to_unicode(notes), 'groups': grps} self.save() insert = set def set_key_value(self, name, key, value): self._data[to_unicode(name)][key] = value self.save() def get(self, name): return self._data.get(name, None) select = get def rename(self, old_name, new_name): try: self._data[old_name] except KeyError: return else: try: self._data[new_name] except KeyError: self._data[new_name] = self._data[old_name].copy() self._data[new_name]['name'] = new_name del self._data[old_name] self.save() def get_all_groups(self): all_groups = [] for e, v in list(self._data.items()): for g in v['groups']: if g not in all_groups: all_groups.append(g) return all_groups def get_all_records(self): return self._data def get_all_names(self): return list(self._data.keys()) def save(self): try: pickle_file = open(self._fab, "wb") pickle.dump(self._data, pickle_file, protocol=2) pickle_file.close() except IOError: log.error("I/O error saving fab file.") def clear(self): self._data = {} self.save() def delete(self, name): if name in self._data: del self._data[name] self.save() return True return False def last_modification_time(self): try: return os.stat(self._fab).st_mtime except OSError: return 0 def update_groups(self, group, members): for e, v in list(self._data.items()): if v['name'] in members: # membership indicated if not group in v['groups']: v['groups'].append(to_unicode(group)) else: if group in v['groups']: v['groups'].remove(to_unicode(group)) self.save() def delete_group(self, group): for e, v in list(self._data.items()): if group in v['groups']: v['groups'].remove(to_unicode(group)) self.save() def group_members(self, group): members = [] for e, v in list(self._data.items()): if group in v['groups']: members.append(e) return members def add_to_group(self, group, members): group_members = self.group_members(group) new_group_members = [] for m in members: if m not in group_members: new_group_members.append(m) self.update_groups(group, group_members + new_group_members) def remove_from_group(self, group, remove_members): group_members = self.group_members(group) new_group_members = [] for m in group_members: if m not in remove_members: new_group_members.append(m) self.update_groups(group, new_group_members) def rename_group(self, old_group, new_group): members = self.group_members(old_group) self.update_groups(old_group, []) self.update_groups(new_group, members) def import_ldif(self, filename): try: data = open(filename, 'r').read() log.debug_block(filename, data) parser = FaxLDIFParser(open(filename, 'r'), self) parser.parse() self.save() return True, '' except ValueError as e: return False, e.message def import_vcard(self, filename): data = open(filename, 'r').read() log.debug_block(filename, data) for card in vcard.VCards(vcard.VFile(vcard.opentextfile(filename))): log.debug(card) if card['name']: fax = '' for x in range(1, 9999): if x == 1: s = 'phone' else: s = 'phone%d' % x try: card[s] except KeyError: break else: if 'fax' in card[s]['type']: fax = card[s]['number'] break org = card.get('organisation', '') if org: org = [org] else: org = card.get('categories', '').split(';') if not org: org = [] org.append(to_unicode('All')) groups = [o for o in org if o] name = card['name'] notes = card.get('notes', to_unicode('')) log.debug("Import: name=%s, fax=%s group(s)=%s notes=%s" % (name, fax, ','.join(groups), notes)) self.set(name, to_unicode(''), to_unicode(''), to_unicode(''), fax, groups, notes) return True, '' # **************************************************************************** # class FaxDevice(device.Device): def __init__(self, device_uri=None, printer_name=None, callback=None, fax_type=FAX_TYPE_NONE, disable_dbus=False): device.Device.__init__(self, device_uri, printer_name, None, callback, disable_dbus) self.send_fax_thread = None self.upload_log_thread = None self.fax_type = fax_type if not disable_dbus: session_bus = dbus.SessionBus() self.service = session_bus.get_object('com.hplip.StatusService', "/com/hplip/StatusService") else: self.service = None def setPhoneNum(self, num): raise AttributeError def getPhoneNum(self): raise AttributeError phone_num = property(getPhoneNum, setPhoneNum) def setStationName(self, name): raise AttributeError def getStationName(self): raise AttributeError station_name = property(getStationName, setStationName) def setDateAndTime(self): raise AttributeError def uploadLog(self): raise AttributeError def isUploadLogActive(self): raise AttributeError def waitForUploadLogThread(self): raise AttributeError def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='', cover_func=None, preserve_formatting=False, printer_name='', update_queue=None, event_queue=None): raise AttributeError def isSendFaxActive(self): if self.send_fax_thread is not None: return self.send_fax_thread.is_alive() else: return False def waitForSendFaxThread(self): if self.send_fax_thread is not None and \ self.send_fax_thread.is_alive(): try: self.send_fax_thread.join() except KeyboardInterrupt: pass # **************************************************************************** # def getFaxDevice(device_uri=None, printer_name=None, callback=None, fax_type=FAX_TYPE_NONE, disable_dbus=False): if fax_type == FAX_TYPE_NONE: if device_uri is None and printer_name is not None: printers = cups.getPrinters() for p in printers: if p.name.lower() == printer_name.lower(): device_uri = p.device_uri break else: raise Error(ERROR_DEVICE_NOT_FOUND) if device_uri is not None: mq = device.queryModelByURI(device_uri) fax_type = mq['fax-type'] log.debug("fax-type=%d" % fax_type) if fax_type in (FAX_TYPE_BLACK_SEND_EARLY_OPEN, FAX_TYPE_BLACK_SEND_LATE_OPEN): from .pmlfax import PMLFaxDevice return PMLFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) elif fax_type == FAX_TYPE_SOAP: from .soapfax import SOAPFaxDevice return SOAPFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) elif fax_type == FAX_TYPE_LEDMSOAP: from .ledmsoapfax import LEDMSOAPFaxDevice return LEDMSOAPFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) elif fax_type == FAX_TYPE_MARVELL: from .marvellfax import MarvellFaxDevice return MarvellFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) elif fax_type == FAX_TYPE_LEDM: from .ledmfax import LEDMFaxDevice return LEDMFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) elif fax_type == FAX_TYPE_CDM: from .cdmfax import CDMFaxDevice return CDMFaxDevice(device_uri, printer_name, callback, fax_type, disable_dbus) else: raise Error(ERROR_DEVICE_DOES_NOT_SUPPORT_OPERATION) # **************************************************************************** # # TODO: Define these in only 1 place! STATE_DONE = 0 STATE_ABORTED = 10 STATE_SUCCESS = 20 STATE_BUSY = 25 STATE_READ_SENDER_INFO = 30 STATE_PRERENDER = 40 STATE_COUNT_PAGES = 50 STATE_NEXT_RECIPIENT = 60 STATE_COVER_PAGE = 70 STATE_SINGLE_FILE = 80 STATE_MERGE_FILES = 90 STATE_SINGLE_FILE = 100 STATE_SEND_FAX = 110 STATE_CLEANUP = 120 STATE_ERROR = 130 class FaxSendThread(threading.Thread): def __init__(self, dev, service, phone_num_list, fax_file_list, cover_message='', cover_re='', cover_func=None, preserve_formatting=False, printer_name='', update_queue=None, event_queue=None): threading.Thread.__init__(self) self.dev = dev # device.Device self.service = service # dbus proxy to status server object self.phone_num_list = phone_num_list self.fax_file_list = fax_file_list self.update_queue = update_queue self.event_queue = event_queue self.cover_message = cover_message self.cover_re = cover_re self.cover_func = cover_func self.current_printer = printer_name self.stream = BytesIO() self.prev_update = '' self.remove_temp_file = False self.preserve_formatting = preserve_formatting self.results = {} # {'file' : error_code,...} self.cover_page_present = False self.recipient_file_list = [] self.f = None # final file of fax data to send (pages merged) self.job_hort_dpi = 0 self.job_hort_dpi = 0 self.job_vert_dpi = 0 self.job_page_size = 0 self.job_resolution = 0 self.job_encoding = 0 def pre_render(self, state): # pre-render each page that needs rendering # except for the cover page self.cover_page_present = False log.debug(self.fax_file_list) # sample fax_file_list #[(dbus.String('/tmp/hpfax-xw43tq9v'), 'application/hplip-fax', 'HPLIP Fax', dbus.String('test.pdf'), 4169580547)] #[('basic', 'application/hplip-fax-coverpage', 'HP Fax Coverpage: "basic"', 'Cover Page', 1)] for fax_file in self.fax_file_list: # (file, type, desc, title) fax_file_name, fax_file_type, fax_file_desc, \ fax_file_title, fax_file_pages = fax_file if fax_file_type == "application/hplip-fax-coverpage": # render later self.cover_page_present = True log.debug("Skipping coverpage") #if fax_file_type == "application/hplip-fax": # already rendered else: self.rendered_file_list.append((fax_file_name, "application/hplip-fax", "HP Fax", fax_file_title)) log.debug("Processing pre-rendered file: %s (%d pages)" % (fax_file_name, fax_file_pages)) if self.check_for_cancel(): state = STATE_ABORTED log.debug(self.rendered_file_list) if self.check_for_cancel(): state = STATE_ABORTED return state def count_pages(self, state): self.recipient_file_list = self.rendered_file_list[:] log.debug("Counting total pages...") self.job_total_pages = 0 log.debug(self.recipient_file_list) i = 0 for fax_file in self.recipient_file_list: # (file, type, desc, title) fax_file_name = fax_file[0] log.debug("Processing file (counting pages): %s..." % fax_file_name) #self.write_queue((STATUS_PROCESSING_FILES, self.job_total_pages, '')) if os.path.exists(fax_file_name): self.results[fax_file_name] = ERROR_SUCCESS fax_file_fd = open(fax_file_name, 'rb') header = fax_file_fd.read(FILE_HEADER_SIZE) magic, version, total_pages, hort_dpi, vert_dpi, page_size, \ resolution, encoding, reserved1, reserved2 = \ self.decode_fax_header(header) if magic != b'hplip_g3': log.error("Invalid file header. Bad magic.") self.results[fax_file_name] = ERROR_FAX_INVALID_FAX_FILE state = STATE_ERROR continue if not i: self.job_hort_dpi, self.job_vert_dpi, self.job_page_size, \ self.job_resolution, self.job_encoding = \ hort_dpi, vert_dpi, page_size, resolution, encoding i += 1 else: if self.job_hort_dpi != hort_dpi or \ self.job_vert_dpi != vert_dpi or \ self.job_page_size != page_size or \ self.job_resolution != resolution or \ self.job_encoding != encoding: log.error("Incompatible options for file: %s" % fax_file_name) self.results[fax_file_name] = ERROR_FAX_INCOMPATIBLE_OPTIONS state = STATE_ERROR log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" % (magic, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding)) self.job_total_pages += total_pages fax_file_fd.close() else: log.error("Unable to find HP Fax file: %s" % fax_file_name) self.results[fax_file_name] = ERROR_FAX_FILE_NOT_FOUND state = STATE_ERROR break if self.check_for_cancel(): state = STATE_ABORTED break if self.cover_page_present: self.job_total_pages += 1 # Cover pages are truncated to 1 page log.debug("Total fax pages=%d" % self.job_total_pages) return state def decode_fax_header(self, header): try: return struct.unpack(">8sBIHHBBBII", header) except struct.error: return -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 def decode_page_header(self, header): try: return struct.unpack(">IIIIII", header) except struct.error: return -1, -1, -1, -1, -1, -1 def cover_page(self, recipient): if self.job_total_pages > 1: state = STATE_MERGE_FILES else: state = STATE_SINGLE_FILE if self.cover_page_present: log.debug("Creating cover page for recipient: %s" % recipient['name']) fax_file, canceled = self.render_cover_page(recipient) if canceled: state = STATE_ABORTED elif not fax_file: state = STATE_ERROR # timeout else: self.recipient_file_list.insert(0, (fax_file, "application/hplip-fax", "HP Fax", 'Cover Page')) log.debug("Cover page G3 file: %s" % fax_file) self.results[fax_file] = ERROR_SUCCESS return state def single_file(self, state): state = STATE_SEND_FAX log.debug("Processing single file...") self.f = self.recipient_file_list[0][0] try: f_fd = open(self.f, 'rb') except IOError: log.error("Unable to open fax file: %s" % self.f) state = STATE_ERROR else: header = f_fd.read(FILE_HEADER_SIZE) magic, version, total_pages, hort_dpi, vert_dpi, page_size, \ resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header) self.results[self.f] = ERROR_SUCCESS if magic != b'hplip_g3': log.error("Invalid file header. Bad magic.") self.results[self.f] = ERROR_FAX_INVALID_FAX_FILE state = STATE_ERROR log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" % (magic, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding)) f_fd.close() return state def merge_cdm_fax_files(self,state): log.debug("%s State: Merge multiple CDM files" % ("*"*20)) log.debug(self.recipient_file_list) self.remove_temp_file = True HeaderSrtSessionAndOpenDataSrc = b'\xD1\xC8\x00\xC8\x00\xF8\x89\xC0\x00\xF8\x86\xC0\x03\xF8\x8F\xC0\x03\xF8\xB2\x41' FooterEndSessionAndCloseDataSrc = b'\x49\x42' job_page_num = 1 if self.job_total_pages: try: f_fd, self.f = utils.make_temp_file() os.write(f_fd, bytearray(HeaderSrtSessionAndOpenDataSrc)) for fax_file in self.recipient_file_list: fax_file_name = fax_file[0] log.debug("Processing file: %s..." % fax_file_name) self.job_total_pages = self.job_total_pages + 1 with open(fax_file_name,'rb') as infile: try: os.write(f_fd,infile.read()) except Exception as inst: log.debug(inst) if self.check_for_cancel(): state = STATE_ABORTED break log.debug("Writting to queues...") self.write_queue((STATUS_PROCESSING_FILES, job_page_num, '')) job_page_num = job_page_num + 1 log.debug("adding footer...") os.write(f_fd, bytearray(FooterEndSessionAndCloseDataSrc)) os.close(f_fd) log.debug("Total pages=%d" % self.job_total_pages) except: state = STATE_ERROR return state def merge_files(self, state): log.debug("%s State: Merge multiple files" % ("*"*20)) log.debug(self.recipient_file_list) log.debug("Merging g3 files...") self.remove_temp_file = True if self.job_total_pages: f_fd, self.f = utils.make_temp_file() log.debug("Temp file=%s" % self.f) data = struct.pack(">8sBIHHBBBII", b"hplip_g3", to_long(1), self.job_total_pages, self.job_hort_dpi, self.job_vert_dpi, self.job_page_size, self.job_resolution, self.job_encoding, to_long(0), to_long(0)) os.write(f_fd, data) job_page_num = 1 for fax_file in self.recipient_file_list: fax_file_name = fax_file[0] log.debug("Processing file: %s..." % fax_file_name) if self.results[fax_file_name] == ERROR_SUCCESS: fax_file_fd = open(fax_file_name, 'rb') header = fax_file_fd.read(FILE_HEADER_SIZE) magic, version, total_pages, hort_dpi, vert_dpi, page_size, \ resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header) if magic != b'hplip_g3': log.error("Invalid file header. Bad magic.") state = STATE_ERROR break log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" % (magic, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding)) for p in range(total_pages): header = fax_file_fd.read(PAGE_HEADER_SIZE) page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \ self.decode_page_header(header) if page_num == -1: log.error("Page header error") state - STATE_ERROR break header = struct.pack(">IIIIII", job_page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, to_long(0)) os.write(f_fd, header) self.write_queue((STATUS_PROCESSING_FILES, job_page_num, '')) log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%s" % (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes)) os.write(f_fd, fax_file_fd.read(bytes_to_read)) job_page_num += 1 fax_file_fd.close() if self.check_for_cancel(): state = STATE_ABORTED break else: log.error("Skipping file: %s" % fax_file_name) continue os.close(f_fd) log.debug("Total pages=%d" % self.job_total_pages) return state def next_recipient_gen(self): for a in self.phone_num_list: yield a def next_file_gen(self): for a in self.recipient_file_list: yield a def render_file(self, path, title, mime_type, force_single_page=False): all_pages = True page_range = '' page_set = 0 nup = 1 cups.resetOptions() if mime_type in ["application/x-cshell", "application/x-perl", "application/x-python", "application/x-shell", "application/x-sh", "text/plain",]: cups.addOption('prettyprint') if nup > 1: cups.addOption('number-up=%d' % nup) if force_single_page: cups.addOption('page-ranges=1') # Force coverpage to 1 page sent_job_id = cups.printFile(self.current_printer, path, title) cups.resetOptions() log.debug("Job ID=%d" % sent_job_id) job_id = 0 time.sleep(1) fax_file = '' complete = False end_time = time.time() + 300.0 # wait for 5 min. max while time.time() < end_time: log.debug("Waiting for fax... type =%s"%type(self.dev.device_uri)) result = list(self.service.CheckForWaitingFax(self.dev.device_uri, prop.username, sent_job_id)) fax_file = str(result[7]) log.debug("Fax file=%s" % fax_file) if fax_file: break if self.check_for_cancel(): log.error("Render canceled. Canceling job #%d..." % sent_job_id) cups.cancelJob(sent_job_id) return '', True time.sleep(1) else: log.error("Timeout waiting for rendering. Canceling job #%d..." % sent_job_id) cups.cancelJob(sent_job_id) return '', False return fax_file, False def check_for_cancel(self): canceled = False while self.event_queue.qsize(): try: event = self.event_queue.get(0) if event[0] == EVENT_FAX_SEND_CANCELED: canceled = True log.debug("Cancel pressed!") except Queue.Empty: break return canceled def render_cover_page(self, a): log.debug("Creating cover page...") #Read file again just before creating the coverpage, so that we get updated voice_phone and email_address from /hplip.conf file #hplip.conf file get updated, whenever user changes coverpage info from hp-faxsetup window. user_conf.read() pdf = self.cover_func(page_size=coverpages.PAGE_SIZE_LETTER, total_pages=self.job_total_pages, recipient_name=a['name'], recipient_phone='', # ??? recipient_fax=a['fax'], sender_name=self.sender_name, sender_phone=user_conf.get('fax', 'voice_phone'), sender_fax=self.sender_fax, sender_email=user_conf.get('fax', 'email_address'), regarding=self.cover_re, message=self.cover_message, preserve_formatting=self.preserve_formatting) log.debug("PDF File=%s" % pdf) fax_file, canceled = self.render_file(pdf, 'Cover Page', "application/pdf", force_single_page=True) try: os.remove(pdf) except IOError: pass return fax_file, canceled def write_queue(self, message): if self.update_queue is not None and message != self.prev_update: self.update_queue.put(message) time.sleep(0) self.prev_update = message def run(self): pass