source: server/lib/gutenbach/server/printer.py @ 7c143c9

no-cups
Last change on this file since 7c143c9 was 7c143c9, checked in by Jessica B. Hamrick <jhamrick@…>, 12 years ago

Add support for chunking, i.e. receiving file data

  • Property mode set to 100644
File size: 7.3 KB
Line 
1#import alsaaudio as aa
2from .exceptions import InvalidJobException, InvalidPrinterStateException
3from .job import Job
4import gutenbach.ipp as ipp
5import logging
6import time
7
8# initialize logger
9logger = logging.getLogger(__name__)
10
11class GutenbachPrinter(object):
12
13    # for IPP
14    attributes = [
15        "printer-uri-supported",
16        "uri-authentication-supported",
17        "uri-security-supported",
18        "printer-name",
19        "printer-state",
20        "printer-state-reasons",
21        "ipp-versions-supported",
22        "operations-supported",
23        "charset-configured",
24        "charset-supported",
25        "natural-language-configured",
26        "generated-natural-language-supported",
27        "document-format-default",
28        "document-format-supported",
29        "printer-is-accepting-jobs",
30        "queued-job-count",
31        "pdl-override-supported",
32        "printer-up-time",
33        "compression-supported",
34        "multiple-operation-time-out",
35        "multiple-document-jobs-supported",
36    ]
37
38    operations = [
39        "print-job",
40        "complete-job",
41        "start-job",
42        "get-job",
43        "get-jobs",
44    ]
45       
46
47    #def __init__(self, name, card, mixer):
48    def __init__(self, name):
49
50        self.name = name
51        self.uri = "ipp://localhost:8000/printers/" + self.name
52        self.time_created = int(time.time())
53        self.state = "idle"
54
55        # if card >= len(aa.cards()):
56        #     raise aa.ALSAAudioError(
57        #       "Audio card at index %d does not exist!" % card)
58        # elif mixer not in aa.mixers(card):
59        #     raise aa.ALSAAudioError(
60        #       "Audio mixer '%s' does not exist!" % mixer)
61       
62        # self.card = card
63        # self.mixer = mixer
64
65        self.finished_jobs = []
66        self.active_jobs = []
67        self.jobs = {}
68
69        # cups ignores jobs with id 0, so we have to start at 1
70        self._next_jobid = 1 
71
72    def __getattr__(self, attr):
73        try:
74            return self.__getattribute__(attr)
75        except AttributeError:
76            pass
77        return self.__getattribute__(attr.replace("-", "_"))
78
79    def __hasattr__(self, attr):
80        try:
81            getattr(self, attr)
82            return True
83        except AttributeError:
84            return False
85
86    ## Printer attributes
87
88    @property
89    def printer_uri_supported(self):
90        return ipp.PrinterUriSupported(self.uri)
91
92    @property
93    def uri_authentication_supported(self):
94        return ipp.UriAuthenticationSupported("none")
95
96    @property
97    def uri_security_supported(self):
98        return ipp.UriSecuritySupported("none")
99
100    @property
101    def printer_name(self):
102        return ipp.PrinterName(self.name)
103
104    @property
105    def printer_state(self):
106        return ipp.PrinterState(ipp.constants.PrinterStates.IDLE)
107
108    @property
109    def printer_state_reasons(self):
110        return ipp.PrinterStateReasons("none")
111
112    @property
113    def ipp_versions_supported(self):
114        return ipp.IppVersionsSupported("1.0", "1.1")
115
116    # XXX: We should query ourself for the supported operations
117    @property
118    def operations_supported(self):
119        return ipp.OperationsSupported(ipp.OperationCodes.GET_JOBS)
120
121    @property
122    def charset_configured(self):
123        return ipp.CharsetConfigured("utf-8")
124
125    @property
126    def charset_supported(self):
127        return ipp.CharsetSupported("utf-8")
128
129    @property
130    def natural_language_configured(self):
131        return ipp.NaturalLanguageConfigured("en-us")
132
133    @property
134    def generated_natural_language_supported(self):
135        return ipp.GeneratedNaturalLanguageSupported("en-us")
136
137    @property
138    def document_format_default(self):
139        return ipp.DocumentFormatDefault("application/octet-stream")
140
141    @property
142    def document_format_supported(self):
143        return ipp.DocumentFormatSupported("application/octet-stream", "audio/mp3")
144
145    @property
146    def printer_is_accepting_jobs(self):
147        return ipp.PrinterIsAcceptingJobs(True)
148
149    @property
150    def queued_job_count(self):
151        return ipp.QueuedJobCount(len(self.active_jobs))
152
153    @property
154    def pdl_override_supported(self):
155        return ipp.PdlOverrideSupported("not-attempted")
156
157    @property
158    def printer_up_time(self):
159        return ipp.PrinterUpTime(int(time.time()) - self.time_created)
160
161    @property
162    def compression_supported(self):
163        return ipp.CompressionSupported("none")
164
165    @property
166    def multiple_operation_time_out(self):
167        return ipp.MultipleOperationTimeOut(240)
168
169    @property
170    def multiple_document_jobs_supported(self):
171        return ipp.MultipleDocumentJobsSupported(False)
172
173    ## Printer operations
174
175    def get_printer_attributes(self, request=None):
176        if request and 'requested-attributes' in request:
177            requested = []
178            for value in request['requested-attributes'].values:
179                if value.value in self.attributes:
180                    requested.append(value.value)
181        else:
182            requested = self.attributes
183           
184        attributes = [getattr(self, attr) for attr in requested]
185        return attributes
186
187    def create_job(self, request):
188        operation = request.attribute_groups[0]
189        kwargs = {}
190       
191        # requesting username
192        if 'requesting-user-name' in operation:
193            username_attr = operation['requesting-user-name']
194            username = username_attr.values[0].value
195            if username_attr != ipp.RequestingUserName(username):
196                raise ipp.errors.ClientErrorBadRequest(str(username_attr))
197            kwargs['creator'] = username
198
199        # job name
200        if 'job-name' in operation:
201            job_name_attr = operation['job-name']
202            job_name = job_name_attr.values[0].value
203            if job_name_attr != ipp.JobName(job_name):
204                raise ipp.errors.ClientErrorBadRequest(str(job_name_attr))
205            kwargs['name'] = job_name
206
207        # job size
208        if 'job-k-octets' in operation:
209            job_k_octets_attr = operation['job-k-octets']
210            job_k_octets = job_k_octets_attr.values[0].value
211            if job_k_octets_attr != ipp.JobKOctets(job_k_octets):
212                raise ipp.errors.ClientErrorBadRequest(str(job_k_octets_attr))
213            kwargs['size'] = job_k_octets
214
215        job_id = self._next_jobid
216        self._next_jobid += 1
217       
218        job = Job(job_id, self, **kwargs)
219        self.jobs[job_id] = job
220        self.active_jobs.append(job_id)
221        return job
222
223    def print_job(self, job):
224        pass
225
226    def complete_job(self, jobid):
227        job = self.jobs[self.active_jobs.pop(0)]
228        if job.jobid != jobid:
229            raise InvalidJobException(
230                "Completed job %d has unexpected job id %d!" % \
231                (job.jobid, jobid))
232       
233        self.finished_jobs.append(job)
234        job.finish()
235        return job.jobid
236
237    def start_job(self, jobid):
238        job = self.jobs[self.active_jobs[0]]
239        if job.jobid != jobid:
240            raise InvalidJobException(
241                "Completed job %d has unexpected job id %d!" % \
242                (job.jobid, jobid))
243
244        if job.status == 'playing':
245            raise InvalidPrinterStateException(
246                "Next job in queue (id %d) is " + \
247                "already playing!" % jobid)
248
249        job.play()
250
251    def get_job(self, jobid):
252        if jobid not in self.jobs:
253            raise InvalidJobException(jobid)
254        return self.jobs[jobid]
255
256    def get_jobs(self):
257        print self.active_jobs
258        jobs = [self.jobs[job_id] for job_id in self.active_jobs]
259        return jobs
260
261    # def __repr__(self):
262    #     return str(self)
263
264    # def __str__(self):
265    #     return "<Printer '%s'>" % self.name
Note: See TracBrowser for help on using the repository browser.