Replace 'tap' to 'spaces' to make gbs build succeed
[platform/upstream/hplip.git] / fax / pmlfax.py
1 # -*- coding: utf-8 -*-
2 #
3 # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # Author: Don Welch
20 #
21
22 # Std Lib
23 import sys
24 import os
25 import os.path
26 import struct
27 import time
28 import threading
29
30 # Local
31 from base.g import *
32 from base.codes import *
33 from base import device, utils, pml, codes
34 from prnt import cups
35 from fax import *
36
37
38 # **************************************************************************** #
39
40 # Page flags
41 PAGE_FLAG_NONE = 0x00
42 PAGE_FLAG_NEW_PAGE = 0x01
43 PAGE_FLAG_END_PAGE = 0x02
44 PAGE_FLAG_NEW_DOC = 0x04
45 PAGE_FLAG_END_DOC = 0x08
46 PAGE_FLAG_END_STREAM = 0x10
47
48 MAJOR_VER = 2
49 MINOR_VER = 0
50
51 MFPDTF_RASTER_BITMAP  = 0 # Not used
52 MFPDTF_RASTER_GRAYMAP = 1 # Not used
53 MFPDTF_RASTER_MH      = 2 # OfficeJets B&W Fax
54 MFPDTF_RASTER_MR      = 3 # Not used
55 MFPDTF_RASTER_MMR     = 4 # LaserJets B&W Fax
56 MFPDTF_RASTER_RGB     = 5 # Not used
57 MFPDTF_RASTER_YCC411  = 6 # Not used
58 MFPDTF_RASTER_JPEG    = 7 # Color Fax
59 MFPDTF_RASTER_PCL     = 8 # Not used
60 MFPDTF_RASTER_NOT     = 9 # Not used
61
62 # Data types for FH
63 DT_UNKNOWN       = 0
64 DT_FAX_IMAGES    = 1
65 DT_SCANNED_IMAGES= 2
66 DT_DIAL_STRINGS  = 3
67 DT_DEMO_PAGES    = 4
68 DT_SPEED_DIALS   = 5
69 DT_FAX_LOGS      = 6
70 DT_CFG_PARMS     = 7
71 DT_LANG_STRS     = 8
72 DT_JUNK_FAX_CSIDS= 9
73 DT_REPORT_STRS   = 10
74 DT_FONTS         = 11
75 DT_TTI_BITMAP    = 12
76 DT_COUNTERS      = 13
77 DT_DEF_PARMS     = 14
78 DT_SCAN_OPTIONS  = 15
79 DT_FW_JOB_TABLE  = 17
80
81 # Raster data record types
82 RT_START_PAGE = 0
83 RT_RASTER = 1
84 RT_END_PAGE = 2
85
86 # FH
87 FIXED_HEADER_SIZE = 8
88
89 # Variants
90 IMAGE_VARIANT_HEADER_SIZE = 10
91 DIAL_STRINGS_VARIANT_HEADER_SIZE = 6
92 FAX_IMAGE_VARIANT_HEADER_SIZE = 74
93
94 # Data records
95 SOP_RECORD_SIZE = 36
96 RASTER_RECORD_SIZE = 4
97 EOP_RECORD_SIZE = 12
98 DIAL_STRING_RECORD_SIZE = 51
99
100 # Page flags
101 PAGE_FLAG_NEW_PAGE = 0x01
102 PAGE_FLAG_END_PAGE = 0x02
103 PAGE_FLAG_NEW_DOC = 0x04
104 PAGE_FLAG_END_DOC = 0x08
105 PAGE_FLAG_END_STREAM = 0x10
106
107 # Fax data variant header data source
108 SRC_UNKNOWN = 0
109 SRC_HOST = 2
110 SRC_SCANNER = 5
111 SRC_HOST_THEN_SCANNER = 6
112 SRC_SCANNER_THEN_HOST = 7
113
114 # Fax data variant header TTI header control
115 TTI_NONE = 0
116 TTI_PREPENDED_TO_IMAGE = 1
117 TTI_OVERLAYED_ON_IMAGE = 2
118
119 RASTER_DATA_SIZE = 504
120
121
122
123 # **************************************************************************** #
124 class PMLFaxDevice(FaxDevice):
125
126     def __init__(self, device_uri=None, printer_name=None,
127                  callback=None,
128                  fax_type=FAX_TYPE_NONE,
129                  disable_dbus=False):
130
131         FaxDevice.__init__(self, device_uri,
132                            printer_name,
133                            callback, fax_type,
134                            disable_dbus)
135
136         self.send_fax_thread = None
137         self.upload_log_thread = None
138
139
140     def setPhoneNum(self, num):
141         return self.setPML(pml.OID_FAX_LOCAL_PHONE_NUM, str(num))
142
143     def getPhoneNum(self):
144         return utils.printable(str(self.getPML(pml.OID_FAX_LOCAL_PHONE_NUM)[1]))
145
146     phone_num = property(getPhoneNum, setPhoneNum, doc="OID_FAX_LOCAL_PHONE_NUM")
147
148
149     def setStationName(self, name):
150         return self.setPML(pml.OID_FAX_STATION_NAME, str(name))
151
152     def getStationName(self):
153         return utils.printable(str(self.getPML(pml.OID_FAX_STATION_NAME)[1]))
154
155     station_name = property(getStationName, setStationName, doc="OID_FAX_STATION_NAME")
156
157     def setDateAndTime(self):
158         t = time.localtime()
159         p = struct.pack("BBBBBBB", t[0]-2000, t[1], t[2], t[6]+1, t[3], t[4], t[5])
160         log.debug(repr(p))
161         return self.setPML(pml.OID_DATE_AND_TIME, p)
162
163     def uploadLog(self):
164         if not self.isUloadLogActive():
165             self.upload_log_thread = UploadLogThread(self)
166             self.upload_log_thread.start()
167             return True
168         else:
169             return False
170
171     def isUploadLogActive(self):
172         if self.upload_log_thread is not None:
173             return self.upload_log_thread.isAlive()
174         else:
175             return False
176
177     def waitForUploadLogThread(self):
178         if self.upload_log_thread is not None and \
179             self.upload_log_thread.isAlive():
180
181             self.upload_log_thread.join()
182
183     def sendFaxes(self, phone_num_list, fax_file_list, cover_message='', cover_re='',
184                   cover_func=None, preserve_formatting=False, printer_name='',
185                   update_queue=None, event_queue=None):
186
187         if not self.isSendFaxActive():
188
189             self.send_fax_thread = PMLFaxSendThread(self, self.service, phone_num_list, fax_file_list,
190                                                     cover_message, cover_re, cover_func,
191                                                     preserve_formatting,
192                                                     printer_name, update_queue,
193                                                     event_queue)
194
195             self.send_fax_thread.start()
196             return True
197         else:
198             return False
199
200
201
202 # **************************************************************************** #
203 class PMLUploadLogThread(threading.Thread):
204     def __init__(self, dev):
205         threading.Thread.__init__(self)
206         self.dev = dev
207
208
209     def run(self):
210         STATE_DONE = 0
211         STATE_ABORT = 10
212         STATE_SUCCESS = 20
213         STATE_BUSY = 25
214         STATE_DEVICE_OPEN = 28
215         STATE_CHECK_IDLE = 30
216         STATE_REQUEST_START = 40
217         STATE_WAIT_FOR_ACTIVE = 50
218         STATE_UPLOAD_DATA = 60
219         STATE_DEVICE_CLOSE = 70
220
221         state = STATE_CHECK_IDLE
222
223         while state != STATE_DONE: # --------------------------------- Log upload state machine
224             if state == STATE_ABORT:
225                 pass
226             elif state == STATE_SUCCESS:
227                 pass
228             elif state == STATE_BUSY:
229                 pass
230
231             elif state == STATE_DEVICE_OPEN: # --------------------------------- Open device (28)
232                 state = STATE_REQUEST_START
233                 try:
234                     self.dev.open()
235                 except Error, e:
236                     log.error("Unable to open device (%s)." % e.msg)
237                     state = STATE_ERROR
238                 else:
239                     try:
240                         dev.setPML(pml.OID_UPLOAD_TIMEOUT, pml.DEFAULT_UPLOAD_TIMEOUT)
241                     except Error:
242                         state = STATE_ERROR
243
244             elif state == STATE_CHECK_IDLE: # --------------------------------- Check idle (30)
245                 state = STATE_REQUEST_START
246                 ul_state = self.getCfgUploadState()
247
248                 if ul_state != pml.UPDN_STATE_IDLE:
249                     state = STATE_BUSY
250
251
252             elif state == STATE_REQUEST_START: # --------------------------------- Request start (40)
253                 state = STATE_WAIT_FOR_ACTIVE
254                 self.dev.setPML(pml.OID_FAX_CFG_UPLOAD_DATA_TYPE, pml.FAX_CFG_UPLOAD_DATA_TYPE_FAXLOGS)
255                 self.dev.setPML(pml.OID_DEVICE_CFG_UPLOAD, pml.UPDN_STATE_REQSTART)
256
257             elif state == STATE_WAIT_FOR_ACTIVE: # --------------------------------- Wait for active state (50)
258                 state = STATE_UPLOAD_DATA
259
260                 tries = 0
261                 while True:
262                     tries += 1
263                     ul_state = self.getCfgUploadState()
264
265                     if ul_state == pml.UPDN_STATE_XFERACTIVE:
266                         break
267
268                     if ul_state in (pml.UPDN_STATE_ERRORABORT, pml.UPDN_STATE_XFERDONE):
269                         log.error("Cfg upload aborted!")
270                         state = STATE_ERROR
271                         break
272
273                     if tries > 10:
274                         state = STATE_ERROR
275                         log.error("Unable to get into active state!")
276                         break
277
278                     time.sleep(0.5)
279
280             elif state == STATE_UPLOAD_DATA: # --------------------------------- Upload log data (60)
281                 pass
282
283             elif state == STATE_DEVICE_CLOSE: # --------------------------------- Close device (70)
284                 self.dev.close()
285
286
287
288 # **************************************************************************** #
289 class PMLFaxSendThread(FaxSendThread):
290     def __init__(self, dev, service, phone_num_list, fax_file_list,
291                  cover_message='', cover_re='', cover_func=None, preserve_formatting=False,
292                  printer_name='', update_queue=None, event_queue=None):
293
294         FaxSendThread.__init__(self, dev, service, phone_num_list, fax_file_list,
295              cover_message, cover_re, cover_func, preserve_formatting,
296              printer_name, update_queue, event_queue)
297
298
299     def run(self):
300         #results = {} # {'file' : error_code,...}
301
302         STATE_DONE = 0
303         STATE_ABORTED = 10
304         STATE_SUCCESS = 20
305         STATE_BUSY = 25
306         STATE_READ_SENDER_INFO = 30
307         STATE_PRERENDER = 40
308         STATE_COUNT_PAGES = 50
309         STATE_NEXT_RECIPIENT = 60
310         STATE_COVER_PAGE = 70
311         STATE_SINGLE_FILE = 80
312         STATE_MERGE_FILES = 90
313         STATE_SINGLE_FILE = 100
314         STATE_SEND_FAX = 110
315         STATE_CLEANUP = 120
316         STATE_ERROR = 130
317
318         next_recipient = self.next_recipient_gen()
319
320         state = STATE_READ_SENDER_INFO
321         self.rendered_file_list = []
322
323         while state != STATE_DONE: # --------------------------------- Fax state machine
324             if self.check_for_cancel():
325                 state = STATE_ABORTED
326
327             log.debug("STATE=(%d, 0, 0)" % state)
328
329             if state == STATE_ABORTED: # --------------------------------- Aborted (10, 0, 0)
330                 log.error("Aborted by user.")
331                 self.write_queue((STATUS_IDLE, 0, ''))
332                 state = STATE_CLEANUP
333
334
335             elif state == STATE_SUCCESS: # --------------------------------- Success (20, 0, 0)
336                 log.debug("Success.")
337                 self.write_queue((STATUS_COMPLETED, 0, ''))
338                 state = STATE_CLEANUP
339
340
341             elif state == STATE_ERROR: # --------------------------------- Error (130, 0, 0)
342                 log.error("Error, aborting.")
343                 self.write_queue((STATUS_ERROR, 0, ''))
344                 state = STATE_CLEANUP
345
346
347             elif state == STATE_BUSY: # --------------------------------- Busy (25, 0, 0)
348                 log.error("Device busy, aborting.")
349                 self.write_queue((STATUS_BUSY, 0, ''))
350                 state = STATE_CLEANUP
351
352
353             elif state == STATE_READ_SENDER_INFO: # --------------------------------- Get sender info (30, 0, 0)
354                 log.debug("%s State: Get sender info" % ("*"*20))
355                 state = STATE_PRERENDER
356                 try:
357                     try:
358                         self.dev.open()
359                     except Error, e:
360                         log.error("Unable to open device (%s)." % e.msg)
361                         state = STATE_ERROR
362                     else:
363                         try:
364                             self.sender_name = self.dev.station_name
365                             log.debug("Sender name=%s" % self.sender_name)
366                             self.sender_fax = self.dev.phone_num
367                             log.debug("Sender fax=%s" % self.sender_fax)
368                         except Error:
369                             log.error("PML get failed!")
370                             state = STATE_ERROR
371
372                 finally:
373                     self.dev.close()
374
375
376             elif state == STATE_PRERENDER: # --------------------------------- Pre-render non-G3 files (40, 0, 0)
377                 log.debug("%s State: Pre-render non-G3 files" % ("*"*20))
378                 state = self.pre_render(STATE_COUNT_PAGES)
379
380
381             elif state == STATE_COUNT_PAGES: # --------------------------------- Get total page count (50, 0, 0)
382                 log.debug("%s State: Get total page count" % ("*"*20))
383                 state = self.count_pages(STATE_NEXT_RECIPIENT)
384
385
386             elif state == STATE_NEXT_RECIPIENT: # --------------------------------- Loop for multiple recipients (60, 0, 0)
387                 log.debug("%s State: Next recipient" % ("*"*20))
388                 state = STATE_COVER_PAGE
389
390                 try:
391                     recipient = next_recipient.next()
392                     #print recipient
393                     log.debug("Processing for recipient %s" % recipient['name'])
394
395                     self.write_queue((STATUS_SENDING_TO_RECIPIENT, 0, recipient['name']))
396
397                 except StopIteration:
398                     state = STATE_SUCCESS
399                     log.debug("Last recipient.")
400                     continue
401
402                 self.recipient_file_list = self.rendered_file_list[:]
403
404
405             elif state == STATE_COVER_PAGE: # --------------------------------- Create cover page (70, 0, 0)
406                 log.debug("%s State: Render cover page" % ("*"*20))
407                 state = self.cover_page(recipient)
408
409
410             elif state == STATE_SINGLE_FILE: # --------------------------------- Special case for single file (no merge) (80, 0, 0)
411                 log.debug("%s State: Handle single file" % ("*"*20))
412                 state = self.single_file(STATE_SEND_FAX)
413
414             elif state == STATE_MERGE_FILES: # --------------------------------- Merge multiple G3 files (90, 0, 0)
415                 log.debug("%s State: Merge multiple files" % ("*"*20))
416                 state = self.merge_files(STATE_SEND_FAX)
417
418             elif state == STATE_SEND_FAX: # --------------------------------- Send fax state machine (110, 0, 0)
419                 log.debug("%s State: Send fax" % ("*"*20))
420                 state = STATE_NEXT_RECIPIENT
421
422                 FAX_SEND_STATE_DONE = 0
423                 FAX_SEND_STATE_ABORT = 10
424                 FAX_SEND_STATE_ERROR = 20
425                 FAX_SEND_STATE_BUSY = 25
426                 FAX_SEND_STATE_SUCCESS = 30
427                 FAX_SEND_STATE_DEVICE_OPEN = 40
428                 FAX_SEND_STATE_SET_TOKEN = 50
429                 FAX_SEND_STATE_EARLY_OPEN = 60
430                 FAX_SEND_STATE_SET_PARAMS = 70
431                 FAX_SEND_STATE_CHECK_IDLE = 80
432                 FAX_SEND_STATE_START_REQUEST = 90
433                 FAX_SEND_STATE_LATE_OPEN = 100
434                 FAX_SEND_STATE_SEND_DIAL_STRINGS = 110
435                 FAX_SEND_STATE_SEND_FAX_HEADER = 120
436                 FAX_SEND_STATE_SEND_PAGES = 130
437                 FAX_SEND_STATE_SEND_END_OF_STREAM = 140
438                 FAX_SEND_STATE_WAIT_FOR_COMPLETE = 150
439                 FAX_SEND_STATE_RESET_TOKEN = 160
440                 FAX_SEND_STATE_CLOSE_SESSION = 170
441
442                 monitor_state = False
443                 error_state = pml.DN_ERROR_NONE
444                 fax_send_state = FAX_SEND_STATE_DEVICE_OPEN
445
446                 while fax_send_state != FAX_SEND_STATE_DONE:
447
448                     if self.check_for_cancel():
449                         log.error("Fax send aborted.")
450                         fax_send_state = FAX_SEND_STATE_ABORT
451
452                     if monitor_state:
453                         fax_state = self.getFaxDownloadState()
454                         if not fax_state in (pml.UPDN_STATE_XFERACTIVE, pml.UPDN_STATE_XFERDONE):
455                             log.error("D/L error state=%d" % fax_state)
456                             fax_send_state = FAX_SEND_STATE_ERROR
457                             state = STATE_ERROR
458
459                     log.debug("STATE=(%d, %d, 0)" % (STATE_SEND_FAX, fax_send_state))
460
461                     if fax_send_state == FAX_SEND_STATE_ABORT: # -------------- Abort (110, 10, 0)
462                         # TODO: Set D/L state to ???
463                         monitor_state = False
464                         fax_send_state = FAX_SEND_STATE_RESET_TOKEN
465                         state = STATE_ABORTED
466
467                     elif fax_send_state == FAX_SEND_STATE_ERROR: # -------------- Error (110, 20, 0)
468                         log.error("Fax send error.")
469                         error_state = self.getFaxDownloadError()
470                         log.debug("Error State=%d (%s)" % (error_state, pml.DN_ERROR_STR.get(error_state, "Unknown")))
471                         monitor_state = False
472
473                         fax_send_state = FAX_SEND_STATE_RESET_TOKEN
474                         state = STATE_ERROR
475
476                     elif fax_send_state == FAX_SEND_STATE_BUSY: # -------------- Busy (110, 25, 0)
477                         log.error("Fax device busy.")
478                         monitor_state = False
479                         fax_send_state = FAX_SEND_STATE_RESET_TOKEN
480                         state = STATE_BUSY
481
482                     elif fax_send_state == FAX_SEND_STATE_SUCCESS: # -------------- Success (110, 30, 0)
483                         log.debug("Fax send success.")
484                         monitor_state = False
485                         fax_send_state = FAX_SEND_STATE_RESET_TOKEN
486                         state = STATE_NEXT_RECIPIENT
487
488                     elif fax_send_state == FAX_SEND_STATE_DEVICE_OPEN: # -------------- Device open (110, 40, 0)
489                         log.debug("%s State: Open device" % ("*"*20))
490                         fax_send_state = FAX_SEND_STATE_SET_TOKEN
491                         try:
492                             self.dev.open()
493                         except Error, e:
494                             log.error("Unable to open device (%s)." % e.msg)
495                             fax_send_state = FAX_SEND_STATE_ERROR
496                         else:
497                             if self.dev.device_state == DEVICE_STATE_NOT_FOUND:
498                                 fax_send_state = FAX_SEND_STATE_ERROR
499
500                     elif fax_send_state == FAX_SEND_STATE_SET_TOKEN: # -------------- Acquire fax token (110, 50, 0)
501                         log.debug("%s State: Acquire fax token" % ("*"*20))
502                         try:
503                             result_code, token = self.dev.getPML(pml.OID_FAX_TOKEN)
504                         except Error:
505                             log.debug("Unable to acquire fax token (1).")
506                             fax_send_state = FAX_SEND_STATE_EARLY_OPEN
507                         else:
508                             if result_code > pml.ERROR_MAX_OK:
509                                 fax_send_state = FAX_SEND_STATE_EARLY_OPEN
510                                 log.debug("Skipping token acquisition.")
511                             else:
512                                 token = time.strftime("%d%m%Y%H:%M:%S", time.gmtime())
513                                 log.debug("Setting token: %s" % token)
514                                 try:
515                                     self.dev.setPML(pml.OID_FAX_TOKEN, token)
516                                 except Error:
517                                     log.error("Unable to acquire fax token (2).")
518                                     fax_send_state = FAX_SEND_STATE_ERROR
519                                 else:
520                                     result_code, check_token = self.dev.getPML(pml.OID_FAX_TOKEN)
521
522                                     if check_token == token:
523                                         fax_send_state = FAX_SEND_STATE_EARLY_OPEN
524                                     else:
525                                         log.error("Unable to acquire fax token (3).")
526                                         fax_send_state = FAX_SEND_STATE_ERROR
527
528
529                     elif fax_send_state == FAX_SEND_STATE_EARLY_OPEN: # -------------- Early open (newer models) (110, 60, 0)
530                         log.debug("%s State: Early open" % ("*"*20))
531                         fax_send_state = FAX_SEND_STATE_CHECK_IDLE
532
533                         if self.dev.fax_type == FAX_TYPE_BLACK_SEND_EARLY_OPEN: # newer
534                             log.debug("Opening fax channel.")
535                             try:
536                                 self.dev.openFax()
537                             except Error, e:
538                                 log.error("Unable to open channel (%s)." % e.msg)
539                                 fax_send_state = FAX_SEND_STATE_ERROR
540                         else:
541                             log.debug("Skipped.")
542
543
544                     elif fax_send_state == FAX_SEND_STATE_CHECK_IDLE: # -------------- Check for initial idle (110, 80, 0)
545                         log.debug("%s State: Check idle" % ("*"*20))
546                         fax_send_state = FAX_SEND_STATE_START_REQUEST
547
548                         dl_state = self.getFaxDownloadState()
549                         tx_status = self.getFaxJobTxStatus()
550                         rx_status = self.getFaxJobRxStatus()
551
552                         if ((dl_state == pml.UPDN_STATE_IDLE or \
553                             dl_state == pml.UPDN_STATE_ERRORABORT or \
554                             dl_state == pml.UPDN_STATE_XFERDONE) and \
555                             (tx_status == pml.FAXJOB_TX_STATUS_IDLE or tx_status == pml.FAXJOB_TX_STATUS_DONE) and \
556                             (rx_status == pml.FAXJOB_RX_STATUS_IDLE or rx_status == pml.FAXJOB_RX_STATUS_DONE)):
557
558                             # xwas if state == pml.UPDN_STATE_IDLE:
559                             if dl_state == pml.UPDN_STATE_IDLE:
560                                 log.debug("Starting in idle state")
561                             else:
562                                 log.debug("Resetting to idle...")
563                                 self.dev.setPML(pml.OID_FAX_DOWNLOAD, pml.UPDN_STATE_IDLE)
564                                 time.sleep(0.5)
565                         else:
566                             fax_send_state = FAX_SEND_STATE_BUSY
567
568                     elif fax_send_state == FAX_SEND_STATE_START_REQUEST: # -------------- Request fax start (110, 90, 0)
569                         log.debug("%s State: Request start" % ("*"*20))
570                         fax_send_state = FAX_SEND_STATE_SET_PARAMS
571
572                         dl_state = self.getFaxDownloadState()
573
574                         if dl_state == pml.UPDN_STATE_IDLE:
575                             log.debug("Try: 0")
576                             log.debug("Setting to up/down state request start...")
577                             self.dev.setPML(pml.OID_FAX_DOWNLOAD, pml.UPDN_STATE_REQSTART)
578                             time.sleep(1)
579
580                             log.debug("Waiting for active state...")
581                             i = 1
582
583                             while i < 10:
584                                 log.debug("Try: %d" % i)
585                                 try:
586                                     dl_state = self.getFaxDownloadState()
587                                 except Error:
588                                     log.error("PML/SNMP error")
589                                     fax_send_state = FAX_SEND_STATE_ERROR
590                                     break
591
592                                 if dl_state == pml.UPDN_STATE_XFERACTIVE:
593                                     break
594
595                                 time.sleep(1)
596                                 log.debug("Setting to up/down state request start...")
597                                 self.dev.setPML(pml.OID_FAX_DOWNLOAD, pml.UPDN_STATE_REQSTART)
598
599                                 i += 1
600
601                             else:
602                                 log.error("Could not get into active state!")
603                                 fax_send_state = FAX_SEND_STATE_BUSY
604
605                             monitor_state = True
606
607                         else:
608                             log.error("Could not get into idle state!")
609                             fax_send_state = FAX_SEND_STATE_BUSY
610
611
612                     elif fax_send_state == FAX_SEND_STATE_SET_PARAMS: # -------------- Set fax send params (110, 70, 0)
613                         log.debug("%s State: Set params" % ("*"*20))
614                         fax_send_state = FAX_SEND_STATE_LATE_OPEN
615
616                         try:
617                             self.dev.setPML(pml.OID_DEV_DOWNLOAD_TIMEOUT, pml.DEFAULT_DOWNLOAD_TIMEOUT)
618                             self.dev.setPML(pml.OID_FAXJOB_TX_TYPE, pml.FAXJOB_TX_TYPE_HOST_ONLY)
619                             log.debug("Setting date and time on device.")
620                             self.dev.setDateAndTime()
621                         except Error, e:
622                             log.error("PML/SNMP error (%s)" % e.msg)
623                             fax_send_state = FAX_SEND_STATE_ERROR
624
625
626                     elif fax_send_state == FAX_SEND_STATE_LATE_OPEN: # -------------- Late open (older models) (110, 100, 0)
627                         log.debug("%s State: Late open" % ("*"*20))
628                         fax_send_state = FAX_SEND_STATE_SEND_DIAL_STRINGS
629
630                         if self.dev.fax_type == FAX_TYPE_BLACK_SEND_LATE_OPEN: # older
631                             log.debug("Opening fax channel.")
632                             try:
633                                 self.dev.openFax()
634                             except Error:
635                                 log.error("Unable to open channel.")
636                                 fax_send_state = FAX_SEND_STATE_ERROR
637                         else:
638                             log.debug("Skipped.")
639
640
641                     elif fax_send_state == FAX_SEND_STATE_SEND_DIAL_STRINGS: # -------------- Dial strings (110, 110, 0)
642                         log.debug("%s State: Send dial strings" % ("*"*20))
643                         fax_send_state = FAX_SEND_STATE_SEND_FAX_HEADER
644
645                         log.debug("Dialing: %s" % recipient['fax'])
646
647                         log.debug("Sending dial strings...")
648                         self.create_mfpdtf_fixed_header(DT_DIAL_STRINGS, True,
649                             PAGE_FLAG_NEW_DOC | PAGE_FLAG_END_DOC | PAGE_FLAG_END_STREAM) # 0x1c on Windows, we were sending 0x0c
650                         #print recipient
651                         dial_strings = recipient['fax'].encode('ascii')
652                         log.debug(repr(dial_strings))
653                         self.create_mfpdtf_dial_strings(dial_strings)
654
655                         try:
656                             self.write_stream()
657                         except Error:
658                             log.error("Channel write error.")
659                             fax_send_state = FAX_SEND_STATE_ERROR
660
661
662                     elif fax_send_state == FAX_SEND_STATE_SEND_FAX_HEADER: # -------------- Fax header (110, 120, 0)
663                         log.debug("%s State: Send fax header" % ("*"*20))
664                         fax_send_state = FAX_SEND_STATE_SEND_PAGES
665
666                         try:
667                             ff = file(self.f, 'r')
668                         except IOError:
669                             log.error("Unable to read fax file.")
670                             fax_send_state = FAX_SEND_STATE_ERROR
671                             continue
672
673                         try:
674                             header = ff.read(FILE_HEADER_SIZE)
675                         except IOError:
676                             log.error("Unable to read fax file.")
677                             fax_send_state = FAX_SEND_STATE_ERROR
678                             continue
679
680                         magic, version, total_pages, hort_dpi, vert_dpi, page_size, \
681                             resolution, encoding, reserved1, reserved2 = self.decode_fax_header(header)
682
683                         if magic != 'hplip_g3':
684                             log.error("Invalid file header. Bad magic.")
685                             fax_send_state = FAX_SEND_STATE_ERROR
686                         else:
687                             log.debug("Magic=%s Ver=%d Pages=%d hDPI=%d vDPI=%d Size=%d Res=%d Enc=%d" %
688                                       (magic, version, total_pages, hort_dpi, vert_dpi, page_size, resolution, encoding))
689
690                             log.debug("Sending fax header...")
691                             self.create_mfpdtf_fixed_header(DT_FAX_IMAGES, True, PAGE_FLAG_NEW_DOC)
692                             self.create_mfpdtf_fax_header(total_pages)
693
694                             try:
695                                 self.write_stream()
696                             except Error:
697                                 log.error("Unable to write to channel.")
698                                 fax_send_state = FAX_SEND_STATE_ERROR
699
700
701                     elif fax_send_state == FAX_SEND_STATE_SEND_PAGES:  # --------------------------------- Send fax pages state machine (110, 130, 0)
702                         log.debug("%s State: Send pages" % ("*"*20))
703                         fax_send_state = FAX_SEND_STATE_SEND_END_OF_STREAM
704                         page = StringIO()
705
706                         for p in range(total_pages):
707
708                             if self.check_for_cancel():
709                                 fax_send_state = FAX_SEND_STATE_ABORT
710
711                             if fax_send_state == FAX_SEND_STATE_ABORT:
712                                 break
713
714                             try:
715                                 header = ff.read(PAGE_HEADER_SIZE)
716                             except IOError:
717                                 log.error("Unable to read fax file.")
718                                 fax_send_state = FAX_SEND_STATE_ERROR
719                                 continue
720
721                             page_num, ppr, rpp, bytes_to_read, thumbnail_bytes, reserved2 = \
722                                 self.decode_page_header(header)
723
724                             log.debug("Page=%d PPR=%d RPP=%d BPP=%d Thumb=%d" %
725                                       (page_num, ppr, rpp, bytes_to_read, thumbnail_bytes))
726
727                             page.write(ff.read(bytes_to_read))
728                             thumbnail = ff.read(thumbnail_bytes) # thrown away for now (should be 0 read)
729                             page.seek(0)
730
731                             self.create_mfpdtf_fixed_header(DT_FAX_IMAGES, page_flags=PAGE_FLAG_NEW_PAGE)
732                             self.create_sop_record(page_num, hort_dpi, vert_dpi, ppr, rpp, encoding)
733
734                             try:
735                                 data = page.read(RASTER_DATA_SIZE)
736                             except IOError:
737                                 log.error("Unable to read fax file.")
738                                 fax_send_state = FAX_SEND_STATE_ERROR
739                                 continue
740
741                             if data == '':
742                                 log.error("No data!")
743                                 fax_send_state = FAX_SEND_STATE_ERROR
744                                 continue
745
746                             self.create_raster_data_record(data)
747                             total_read = RASTER_DATA_SIZE
748
749                             while True:
750                                 data = page.read(RASTER_DATA_SIZE)
751                                 total_read += RASTER_DATA_SIZE
752
753                                 dl_state = self.getFaxDownloadState()
754                                 if dl_state == pml.UPDN_STATE_ERRORABORT:
755                                     fax_send_state = FAX_SEND_STATE_ERROR
756                                     break
757
758                                 if self.check_for_cancel():
759                                     fax_send_state = FAX_SEND_STATE_ABORT
760                                     break
761
762                                 if data == '':
763                                     self.create_eop_record(rpp)
764
765                                     try:
766                                         self.write_stream()
767                                     except Error:
768                                         log.error("Channel write error.")
769                                         fax_send_state = FAX_SEND_STATE_ERROR
770                                     break
771
772                                 else:
773                                     try:
774                                         self.write_stream()
775                                     except Error:
776                                         log.error("Channel write error.")
777                                         fax_send_state = FAX_SEND_STATE_ERROR
778                                         break
779
780                                 status = self.getFaxJobTxStatus()
781                                 while status == pml.FAXJOB_TX_STATUS_DIALING:
782                                     self.write_queue((STATUS_DIALING, 0, recipient['fax']))
783                                     time.sleep(1.0)
784
785                                     if self.check_for_cancel():
786                                         fax_send_state = FAX_SEND_STATE_ABORT
787                                         break
788
789                                     dl_state = self.getFaxDownloadState()
790                                     if dl_state == pml.UPDN_STATE_ERRORABORT:
791                                         fax_send_state = FAX_SEND_STATE_ERROR
792                                         break
793
794                                     status = self.getFaxJobTxStatus()
795
796                                 if fax_send_state not in (FAX_SEND_STATE_ABORT, FAX_SEND_STATE_ERROR):
797
798                                     while status == pml.FAXJOB_TX_STATUS_CONNECTING:
799                                         self.write_queue((STATUS_CONNECTING, 0, recipient['fax']))
800                                         time.sleep(1.0)
801
802                                         if self.check_for_cancel():
803                                             fax_send_state = FAX_SEND_STATE_ABORT
804                                             break
805
806                                         dl_state = self.getFaxDownloadState()
807                                         if dl_state == pml.UPDN_STATE_ERRORABORT:
808                                             fax_send_state = FAX_SEND_STATE_ERROR
809                                             break
810
811                                         status = self.getFaxJobTxStatus()
812
813                                 if status == pml.FAXJOB_TX_STATUS_TRANSMITTING:
814                                     self.write_queue((STATUS_SENDING, page_num, recipient['fax']))
815
816                                 self.create_mfpdtf_fixed_header(DT_FAX_IMAGES, page_flags=0)
817                                 self.create_raster_data_record(data)
818
819                                 if fax_send_state in (FAX_SEND_STATE_ABORT, FAX_SEND_STATE_ERROR):
820                                     break
821
822                             page.truncate(0)
823                             page.seek(0)
824
825
826                     elif fax_send_state == FAX_SEND_STATE_SEND_END_OF_STREAM: # -------------- EOS (110, 140, 0)
827                         log.debug("%s State: Send EOS" % ("*"*20))
828                         fax_send_state = FAX_SEND_STATE_WAIT_FOR_COMPLETE
829                         log.debug("End of stream...")
830                         self.create_mfpdtf_fixed_header(DT_FAX_IMAGES, False, PAGE_FLAG_END_STREAM)
831
832                         try:
833                             self.write_stream()
834                         except Error:
835                             log.error("Channel write error.")
836                             fax_send_state = FAX_SEND_STATE_ERROR
837
838                         monitor_state = False
839
840
841                     elif fax_send_state == FAX_SEND_STATE_WAIT_FOR_COMPLETE: # -------------- Wait for complete (110, 150, 0)
842                         log.debug("%s State: Wait for completion" % ("*"*20))
843
844                         fax_send_state = FAX_SEND_STATE_WAIT_FOR_COMPLETE
845
846                         time.sleep(1.0)
847                         status = self.getFaxJobTxStatus()
848
849                         if status == pml.FAXJOB_TX_STATUS_DIALING:
850                                 self.write_queue((STATUS_DIALING, 0, recipient['fax']))
851                                 log.debug("Dialing ...")
852
853                         elif status == pml.FAXJOB_TX_STATUS_TRANSMITTING:
854                             self.write_queue((STATUS_SENDING, page_num, recipient['fax']))
855                             log.debug("Transmitting ...")
856
857                         elif status in (pml.FAXJOB_TX_STATUS_DONE, pml.FAXJOB_RX_STATUS_IDLE):
858                             fax_send_state = FAX_SEND_STATE_RESET_TOKEN
859                             state = STATE_NEXT_RECIPIENT
860                             log.debug("Transmitting done or idle ...")
861
862                         else:
863                             self.write_queue((STATUS_SENDING, page_num, recipient['fax']))
864                             log.debug("Pending ...")
865
866
867                     elif fax_send_state == FAX_SEND_STATE_RESET_TOKEN: # -------------- Release fax token (110, 160, 0)
868                         log.debug("%s State: Release fax token" % ("*"*20))
869                         self.write_queue((STATUS_CLEANUP, 0, ''))
870
871                         try:
872                             self.dev.setPML(pml.OID_FAX_TOKEN, '\x00'*16)
873                         except Error:
874                             log.error("Unable to release fax token.")
875
876                         fax_send_state = FAX_SEND_STATE_CLOSE_SESSION
877
878
879                     elif fax_send_state == FAX_SEND_STATE_CLOSE_SESSION: # -------------- Close session (110, 170, 0)
880                         log.debug("%s State: Close session" % ("*"*20))
881                         fax_send_state = FAX_SEND_STATE_DONE
882                         log.debug("Closing session...")
883
884                         try:
885                             mm.close()
886                         except NameError:
887                             pass
888
889                         try:
890                             ff.close()
891                         except NameError:
892                             pass
893
894                         if self.dev.fax_type == FAX_TYPE_BLACK_SEND_LATE_OPEN:
895                             log.debug("Closing fax channel.")
896                             self.dev.closeFax()
897
898                         self.dev.setPML(pml.OID_FAX_DOWNLOAD, pml.UPDN_STATE_IDLE)
899
900                         time.sleep(1)
901
902                         if self.dev.fax_type == FAX_TYPE_BLACK_SEND_EARLY_OPEN:
903                             log.debug("Closing fax channel.")
904                             self.dev.closeFax()
905
906                         self.dev.close()
907
908
909             elif state == STATE_CLEANUP: # --------------------------------- Cleanup (120, 0, 0)
910                 log.debug("%s State: Cleanup" % ("*"*20))
911
912                 if self.remove_temp_file:
913                     log.debug("Removing merged file: %s" % self.f)
914                     try:
915                         os.remove(self.f)
916                         log.debug("Removed")
917                     except OSError:
918                         log.debug("Not found")
919
920                 state = STATE_DONE
921
922
923
924 # --------------------------------- Support functions
925
926
927     def getFaxDownloadState(self):
928         result_code, state = self.dev.getPML(pml.OID_FAX_DOWNLOAD)
929         if state:
930             log.debug("D/L State=%d (%s)" % (state, pml.UPDN_STATE_STR.get(state, 'Unknown')))
931             return state
932         else:
933             return pml.UPDN_STATE_ERRORABORT
934
935     def getFaxDownloadError(self):
936         result_code, state = self.dev.getPML(pml.OID_FAX_DOWNLOAD_ERROR)
937         if state:
938             return state
939         else:
940             return pml.DN_ERROR_UNKNOWN
941
942     def getFaxJobTxStatus(self):
943         result_code, status = self.dev.getPML(pml.OID_FAXJOB_TX_STATUS)
944         if status:
945             log.debug("Tx Status=%d (%s)" % (status, pml.FAXJOB_TX_STATUS_STR.get(status, 'Unknown')))
946             return status
947         else:
948             return pml.FAXJOB_TX_STATUS_IDLE
949
950     def getFaxJobRxStatus(self):
951         result_code, status = self.dev.getPML(pml.OID_FAXJOB_RX_STATUS)
952         if status:
953             log.debug("Rx Status=%d (%s)" % (status, pml.FAXJOB_RX_STATUS_STR.get(status, 'Unknown')))
954             return status
955         else:
956             return pml.FAXJOB_RX_STATUS_IDLE
957
958     def getCfgUploadState(self):
959         result_code, state = self.dev.getPML(pml.OID_DEVICE_CFG_UPLOAD)
960         if state:
961             log.debug("Cfg Upload State = %d (%s)" % (state, pml.UPDN_STATE_STR.get(state, 'Unknown')))
962             return state
963         else:
964             return pml.UPDN_STATE_ERRORABORT
965
966     def create_mfpdtf_fixed_header(self, data_type, send_variant=False, page_flags=0):
967         header_len = FIXED_HEADER_SIZE
968
969         if send_variant:
970             if data_type == DT_DIAL_STRINGS:
971                     header_len += DIAL_STRINGS_VARIANT_HEADER_SIZE
972
973             elif data_type == DT_FAX_IMAGES:
974                 header_len += FAX_IMAGE_VARIANT_HEADER_SIZE
975
976         self.stream.write(struct.pack("<IHBB",
977                           0, header_len, data_type, page_flags))
978
979
980     def create_mfpdtf_dial_strings(self, number):
981         p = struct.pack("<BBHH51s",
982                           MAJOR_VER, MINOR_VER,
983                           1, 51, number[:51])
984         log.debug(repr(p))
985         self.stream.write(p)
986
987
988     def adjust_fixed_header_block_size(self):
989         size = self.stream.tell()
990         self.stream.seek(0)
991         self.stream.write(struct.pack("<I", size))
992
993
994     def create_sop_record(self, page_num, hort_dpi, vert_dpi, ppr, rpp, encoding, bpp=1):
995         self.stream.write(struct.pack("<BBHHHIHHHHHHIHHHH",
996                             RT_START_PAGE, encoding, page_num,
997                             ppr, bpp,
998                             rpp, 0x00, hort_dpi, 0x00, vert_dpi,
999                             ppr, bpp,
1000                             rpp, 0x00, hort_dpi, 0x00, vert_dpi))
1001
1002
1003     def create_eop_record(self, rpp):
1004         self.stream.write(struct.pack("<BBBBII",
1005                             RT_END_PAGE, 0, 0, 0,
1006                             rpp, 0,))
1007
1008
1009     def create_raster_data_record(self, data):
1010         assert len(data) <= RASTER_DATA_SIZE
1011         self.stream.write(struct.pack("<BBH",
1012                         RT_RASTER, 0, len(data),))
1013         self.stream.write(data)
1014
1015
1016     def create_mfpdtf_fax_header(self, total_pages):
1017         self.stream.write(struct.pack("<BBBHBI20s20s20sI",
1018                             MAJOR_VER, MINOR_VER, SRC_HOST, total_pages,
1019                             TTI_PREPENDED_TO_IMAGE, 0, '', '', '', 0))
1020
1021
1022     def write_stream(self):
1023         self.adjust_fixed_header_block_size()
1024         self.dev.writeFax(self.stream.getvalue())
1025         self.stream.truncate(0)
1026         self.stream.seek(0)