Replace 'tap' to 'spaces' to make gbs build succeed
[platform/upstream/hplip.git] / copier / copier.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 from __future__ import generators
23
24 # Std Lib
25 import sys
26 import os
27 import os.path
28 import time
29 import threading
30 import Queue
31 from cStringIO import StringIO
32
33 # Local
34 from base.g import *
35 from base.codes import *
36 from base import device, utils, status, pml
37
38 # Event queue values (UI ==> Copy thread)
39 COPY_CANCELED = 1
40
41 # Update queue values (Copy thread ==> UI)
42 STATUS_IDLE = 0
43 STATUS_SETTING_UP = 1
44 STATUS_WARMING_UP = 2
45 STATUS_ACTIVE = 3
46 STATUS_DONE = 4
47 STATUS_ERROR = 5
48
49
50 # PML Copier Only
51 class PMLCopyDevice(device.Device):
52     def __init__(self, device_uri=None, printer_name=None, 
53                  service=None, callback=None):
54
55         device.Device.__init__(self, device_uri, printer_name,
56                                service, callback)
57
58         self.copy_thread = None
59
60     def copy(self, num_copies=1, contrast=0, reduction=100,
61              quality=pml.COPIER_QUALITY_NORMAL, 
62              fit_to_page=pml.COPIER_FIT_TO_PAGE_ENABLED,
63              scan_src=SCAN_SRC_FLATBED,
64              update_queue=None, event_queue=None): 
65
66         if not self.isCopyActive():
67             self.copy_thread = PMLCopyThread(self, num_copies, contrast, reduction, quality, 
68                                              fit_to_page, scan_src, update_queue, event_queue)
69             self.copy_thread.start()
70             return True
71         else:
72             return False
73
74     def isCopyActive(self):
75         if self.copy_thread is not None:
76             return self.copy_thread.isAlive()
77         else:
78             return False
79
80     def waitForCopyThread(self):
81         if self.copy_thread is not None and \
82             self.copy_thread.isAlive():
83
84             self.copy_thread.join()
85
86
87
88 class PMLCopyThread(threading.Thread):
89     def __init__(self, dev, num_copies, contrast, reduction, quality, 
90                  fit_to_page, scan_src, 
91                  update_queue=None, event_queue=None):
92
93         threading.Thread.__init__(self)
94         self.dev = dev
95         self.num_copies = num_copies
96         self.contrast = contrast
97         self.reduction = reduction
98         self.quality = quality
99         self.fit_to_page = fit_to_page
100         self.scan_src = scan_src
101         self.event_queue = event_queue
102         self.update_queue = update_queue
103         self.prev_update = ''
104         self.copy_type = self.dev.copy_type
105         log.debug("Copy-type = %d" % self.copy_type)
106
107     def run(self):
108         STATE_DONE = 0
109         STATE_ERROR = 5
110         STATE_ABORTED = 10
111         STATE_SUCCESS = 20
112         STATE_BUSY = 25
113         STATE_SET_TOKEN = 30
114         STATE_SETUP_STATE = 40
115         STATE_SETUP_PARAMS = 50
116         STATE_START = 60
117         STATE_ACTIVE = 70
118         STATE_RESET_TOKEN = 80
119
120 #       state = STATE_SET_TOKEN
121         state = STATE_SETUP_STATE
122
123         while state != STATE_DONE: # ------------------------- Copier Thread
124             # revisit - Checking cancel and setting state here means
125             # every state can unconditionally transition to STATE_ABORTED.
126             # This has not been verified.
127             # if self.check_for_cancel():
128                 # state = STATE_ABORTED
129
130             if state == STATE_ABORTED:
131                 log.debug("%s State: Aborted" % ("*"*20))
132                 self.write_queue(STATUS_DONE) # This was STATUS_ERROR.
133                 state = STATE_RESET_TOKEN
134
135             if state == STATE_ERROR:
136                 log.debug("%s State: Error" % ("*"*20))
137                 self.write_queue(STATUS_ERROR)
138                 state = STATE_RESET_TOKEN
139
140             elif state == STATE_SUCCESS:
141                 log.debug("%s State: Success" % ("*"*20))
142                 self.write_queue(STATUS_DONE)
143                 state = STATE_RESET_TOKEN
144
145             elif state == STATE_BUSY:
146                 log.debug("%s State: Busy" % ("*"*20))
147                 self.write_queue(STATUS_ERROR)
148                 state = STATE_RESET_TOKEN
149
150             elif state == STATE_SET_TOKEN:
151                 log.debug("%s State: Acquire copy token" % ("*"*20))
152
153                 self.write_queue(STATUS_SETTING_UP)
154
155                 try:
156                     result_code, token = self.dev.getPML(pml.OID_COPIER_TOKEN)
157                 except Error:
158                     log.debug("Unable to acquire copy token (1).")
159                     state = STATE_SETUP_STATE
160                 else:
161                     if result_code > pml.ERROR_MAX_OK:
162                         state = STATE_SETUP_STATE
163                         log.debug("Skipping token acquisition.")
164                     else:
165                         token = time.strftime("%d%m%Y%H:%M:%S", time.gmtime())
166                         log.debug("Setting token: %s" % token)
167                         try:
168                             self.dev.setPML(pml.OID_COPIER_TOKEN, token)
169                         except Error:
170                             log.error("Unable to acquire copy token (2).")
171                             state = STATUS_ERROR
172                         else:
173                             result_code, check_token = self.dev.getPML(pml.OID_COPIER_TOKEN)
174
175                             if check_token == token:
176                                 state = STATE_SETUP_STATE
177                             else:
178                                 log.error("Unable to acquire copy token (3).")
179                                 state = STATE_ERROR
180
181             elif state == STATE_SETUP_STATE:
182                 log.debug("%s State: Setup state" % ("*"*20))
183
184                 if self.copy_type == COPY_TYPE_DEVICE:
185                     result_code, copy_state = self.dev.getPML(pml.OID_COPIER_JOB)
186
187                     if copy_state == pml.COPIER_JOB_IDLE:
188                         self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_SETUP)
189                         state = STATE_SETUP_PARAMS
190
191                     else:
192                         state = STATE_BUSY
193
194                 elif self.copy_type == COPY_TYPE_AIO_DEVICE:
195                     result_code, copy_state = self.dev.getPML(pml.OID_SCAN_TO_PRINTER)
196
197                     if copy_state == pml.SCAN_TO_PRINTER_IDLE:
198                         state = STATE_SETUP_PARAMS
199
200                     else:
201                         state = STATE_BUSY
202
203
204
205             elif state == STATE_SETUP_PARAMS:
206                 log.debug("%s State: Setup Params" % ("*"*20))
207
208                 if self.num_copies < 0: self.num_copies = 1
209                 if self.num_copies > 99: self.num_copies = 99
210
211                 if self.copy_type == COPY_TYPE_DEVICE: # MFP
212
213                     # num_copies
214                     self.dev.setPML(pml.OID_COPIER_JOB_NUM_COPIES, self.num_copies)
215
216                     # contrast
217                     self.dev.setPML(pml.OID_COPIER_JOB_CONTRAST, self.contrast)
218
219                     # reduction
220                     self.dev.setPML(pml.OID_COPIER_JOB_REDUCTION, self.reduction)
221
222                     # quality
223                     self.dev.setPML(pml.OID_COPIER_JOB_QUALITY, self.quality)
224
225                     # fit_to_page
226                     if self.scan_src == SCAN_SRC_FLATBED:
227                         self.dev.setPML(pml.OID_COPIER_JOB_FIT_TO_PAGE, self.fit_to_page)
228
229                 else: # AiO
230                     # num_copies
231                     self.dev.setPML(pml.OID_COPIER_NUM_COPIES_AIO, self.num_copies)
232
233                     # contrast
234                     self.contrast = (self.contrast * 10 / 25) + 50
235                     self.dev.setPML(pml.OID_COPIER_CONTRAST_AIO, self.contrast)
236
237                     if self.fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED:
238                         self.reduction = 0
239
240                     # reduction
241                     self.dev.setPML(pml.OID_COPIER_REDUCTION_AIO, self.reduction)
242
243                     # quality
244                     self.dev.setPML(pml.OID_COPIER_QUALITY_AIO, self.quality)
245
246                     self.dev.setPML(pml.OID_PIXEL_DATA_TYPE, pml.PIXEL_DATA_TYPE_COLOR_24_BIT)
247                     self.dev.setPML(pml.OID_COPIER_SPECIAL_FEATURES, pml.COPY_FEATURE_NONE)
248                     self.dev.setPML(pml.OID_COPIER_PHOTO_MODE, pml.ENHANCE_LIGHT_COLORS | pml.ENHANCE_TEXT)
249                     
250                     # tray select
251                     self.dev.setPML(pml.OID_COPIER_JOB_INPUT_TRAY_SELECT, pml.COPIER_JOB_INPUT_TRAY_1)
252                     
253                     # media type
254                     self.dev.setPML(pml.OID_COPIER_MEDIA_TYPE, pml.COPIER_MEDIA_TYPE_AUTOMATIC)
255                     
256                     # pixel data type
257                     self.dev.setPML(pml.OID_PIXEL_DATA_TYPE, pml.PIXEL_DATA_TYPE_COLOR_24_BIT)
258                     
259                     # special features
260                     self.dev.setPML(pml.OID_COPIER_SPECIAL_FEATURES, pml.COPY_FEATURE_NONE)
261                     
262                     # media size
263                     self.dev.setPML(pml.OID_COPIER_JOB_MEDIA_SIZE, pml.COPIER_JOB_MEDIA_SIZE_US_LETTER)
264                     
265
266                 
267                 
268                 log.debug("num_copies = %d" % self.num_copies)
269                 log.debug("contrast= %d" % self.contrast)
270                 log.debug("reduction = %d" % self.reduction)
271                 log.debug("quality = %d" % self.quality)
272                 log.debug("fit_to_page = %d" % self.fit_to_page)
273
274                 state = STATE_START
275
276             elif state == STATE_START:
277                 log.debug("%s State: Start" % ("*"*20))
278
279                 if self.copy_type == COPY_TYPE_DEVICE:
280                     self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_START)
281
282                 elif self.copy_type == COPY_TYPE_AIO_DEVICE:
283                     self.dev.setPML(pml.OID_SCAN_TO_PRINTER, pml.SCAN_TO_PRINTER_START)
284
285                 state = STATE_ACTIVE
286
287             elif state == STATE_ACTIVE:
288                 log.debug("%s State: Active" % ("*"*20))
289
290                 if self.copy_type == COPY_TYPE_DEVICE:
291                     while True:
292                         result_code, copy_state = self.dev.getPML(pml.OID_COPIER_JOB)
293
294                         if self.check_for_cancel():
295                             self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_IDLE) # cancel
296                             state = STATE_ABORTED
297                             break
298
299                         if copy_state == pml.COPIER_JOB_START:
300                             log.debug("state = start")
301                             time.sleep(1)
302                             continue
303
304                         if copy_state == pml.COPIER_JOB_ACTIVE:
305                             self.write_queue(STATUS_ACTIVE)
306                             log.debug("state = active")
307                             time.sleep(2)
308                             continue
309
310                         elif copy_state == pml.COPIER_JOB_ABORTING:
311                             log.debug("state = aborting")
312                             state = STATE_ABORTED
313                             break
314
315                         elif copy_state == pml.COPIER_JOB_IDLE:
316                             log.debug("state = idle")
317                             state = STATE_SUCCESS
318                             break
319
320                 elif self.copy_type == COPY_TYPE_AIO_DEVICE:
321                     while True:
322                         result_code, copy_state = self.dev.getPML(pml.OID_SCAN_TO_PRINTER)
323
324                         if self.check_for_cancel():
325                             self.dev.setPML(pml.OID_SCAN_TO_PRINTER, pml.SCAN_TO_PRINTER_IDLE) # cancel
326                             state = STATE_ABORTED
327                             break
328
329                         if copy_state == pml.SCAN_TO_PRINTER_START:
330                             log.debug("state = start")
331                             time.sleep(1)
332                             continue
333
334                         if copy_state == pml.SCAN_TO_PRINTER_ACTIVE:
335                             self.write_queue(STATUS_ACTIVE)
336                             log.debug("state = active")
337                             time.sleep(2)
338                             continue
339
340                         elif copy_state == pml.SCAN_TO_PRINTER_ABORTED:
341                             log.debug("state = aborting")
342                             state = STATE_ABORTED
343                             break
344
345                         elif copy_state == pml.SCAN_TO_PRINTER_IDLE:
346                             log.debug("state = idle")
347                             state = STATE_SUCCESS
348                             break
349
350
351             elif state == STATE_RESET_TOKEN:
352                 log.debug("%s State: Release copy token" % ("*"*20))
353
354                 try:
355                     self.dev.setPML(pml.OID_COPIER_TOKEN, '\x00'*16)
356                 except Error:
357                     log.error("Unable to release copier token.")
358
359                 self.dev.close() # Close the device.
360                 
361                 state = STATE_DONE
362
363
364     def check_for_cancel(self):
365         canceled = False
366         while self.event_queue.qsize():
367             try:
368                 event = self.event_queue.get(0)
369                 if event == COPY_CANCELED:
370                     canceled = True
371                     log.debug("Cancel pressed!")
372             except Queue.Empty:
373                 break
374
375         return canceled
376
377     def write_queue(self, message):
378         if self.update_queue is not None and message != self.prev_update:
379             self.update_queue.put(message)
380             time.sleep(0)
381             self.prev_update = message