source: server/lib/gutenbach/server/printer.py @ e58af05

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

Implement send-document operation and add threading so that the gutenbach server can play jobs

  • Property mode set to 100644
File size: 7.5 KB
RevLine 
[b2e077a]1#import alsaaudio as aa
[e58af05]2from . import InvalidJobException, InvalidPrinterStateException
3from . import Job
[b2e077a]4import gutenbach.ipp as ipp
5import logging
6import time
[d04a689]7
8# initialize logger
9logger = logging.getLogger(__name__)
[776a659]10
[b2e077a]11class GutenbachPrinter(object):
12
[1a63bf7]13    # for IPP
[b2e077a]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",
[f6e2532]33        "compression-supported",
34        "multiple-operation-time-out",
35        "multiple-document-jobs-supported",
[1a63bf7]36    ]
[b2e077a]37
[f6e2532]38    operations = [
39        "print-job",
40        "complete-job",
41        "start-job",
42        "get-job",
43        "get-jobs",
44    ]
45       
46
[b2e077a]47    #def __init__(self, name, card, mixer):
48    def __init__(self, name):
49
[1a63bf7]50        self.name = name
51        self.uri = "ipp://localhost:8000/printers/" + self.name
52        self.time_created = int(time.time())
53        self.state = "idle"
[b2e077a]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)
[776a659]61       
[b2e077a]62        # self.card = card
63        # self.mixer = mixer
[776a659]64
65        self.finished_jobs = []
66        self.active_jobs = []
67        self.jobs = {}
68
[7c143c9]69        # cups ignores jobs with id 0, so we have to start at 1
70        self._next_jobid = 1 
[776a659]71
[1a63bf7]72    def __getattr__(self, attr):
73        try:
[6effd50]74            return self.__getattribute__(attr)
[1a63bf7]75        except AttributeError:
76            pass
[6effd50]77        return self.__getattribute__(attr.replace("-", "_"))
[1a63bf7]78
79    def __hasattr__(self, attr):
[6effd50]80        try:
81            getattr(self, attr)
82            return True
83        except AttributeError:
84            return False
[1a63bf7]85
[b2e077a]86    ## Printer attributes
[1a63bf7]87
[b2e077a]88    @property
89    def printer_uri_supported(self):
[793432f]90        return ipp.PrinterUriSupported(self.uri)
[1a63bf7]91
[b2e077a]92    @property
93    def uri_authentication_supported(self):
[793432f]94        return ipp.UriAuthenticationSupported("none")
[b2e077a]95
96    @property
97    def uri_security_supported(self):
[793432f]98        return ipp.UriSecuritySupported("none")
[b2e077a]99
100    @property
101    def printer_name(self):
[793432f]102        return ipp.PrinterName(self.name)
[1a63bf7]103
[b2e077a]104    @property
105    def printer_state(self):
[793432f]106        return ipp.PrinterState(ipp.constants.PrinterStates.IDLE)
[1a63bf7]107
[b2e077a]108    @property
109    def printer_state_reasons(self):
[793432f]110        return ipp.PrinterStateReasons("none")
[b2e077a]111
112    @property
113    def ipp_versions_supported(self):
[793432f]114        return ipp.IppVersionsSupported("1.0", "1.1")
[1a63bf7]115
[f6e2532]116    # XXX: We should query ourself for the supported operations
[b2e077a]117    @property
118    def operations_supported(self):
[793432f]119        return ipp.OperationsSupported(ipp.OperationCodes.GET_JOBS)
[b2e077a]120
121    @property
122    def charset_configured(self):
[793432f]123        return ipp.CharsetConfigured("utf-8")
[b2e077a]124
125    @property
126    def charset_supported(self):
[793432f]127        return ipp.CharsetSupported("utf-8")
[b2e077a]128
129    @property
130    def natural_language_configured(self):
[793432f]131        return ipp.NaturalLanguageConfigured("en-us")
[b2e077a]132
133    @property
134    def generated_natural_language_supported(self):
[793432f]135        return ipp.GeneratedNaturalLanguageSupported("en-us")
[b2e077a]136
137    @property
138    def document_format_default(self):
[793432f]139        return ipp.DocumentFormatDefault("application/octet-stream")
[b2e077a]140
141    @property
142    def document_format_supported(self):
[793432f]143        return ipp.DocumentFormatSupported("application/octet-stream", "audio/mp3")
[b2e077a]144
145    @property
146    def printer_is_accepting_jobs(self):
[793432f]147        return ipp.PrinterIsAcceptingJobs(True)
[b2e077a]148
149    @property
150    def queued_job_count(self):
[793432f]151        return ipp.QueuedJobCount(len(self.active_jobs))
[b2e077a]152
153    @property
154    def pdl_override_supported(self):
[793432f]155        return ipp.PdlOverrideSupported("not-attempted")
[b2e077a]156
157    @property
158    def printer_up_time(self):
[793432f]159        return ipp.PrinterUpTime(int(time.time()) - self.time_created)
[b2e077a]160
161    @property
162    def compression_supported(self):
[793432f]163        return ipp.CompressionSupported("none")
[b2e077a]164
[f6e2532]165    @property
166    def multiple_operation_time_out(self):
[793432f]167        return ipp.MultipleOperationTimeOut(240)
[f6e2532]168
169    @property
170    def multiple_document_jobs_supported(self):
[793432f]171        return ipp.MultipleDocumentJobsSupported(False)
[f6e2532]172
[ee8e6d0]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]
[b2e077a]185        return attributes
186
[ee8e6d0]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
[776a659]222
[e58af05]223    def send_document(self, jobid, document):
224        job = self.jobs[jobid]
225        if job.status != ipp.JobStates.HELD:
226            raise InvalidPrinterStateException(
227                "Invalid job state: %d" % job.status)
228        job.document = document
229        job.status = ipp.JobStates.PENDING
230
[776a659]231    def print_job(self, job):
[ee8e6d0]232        pass
[776a659]233
234    def complete_job(self, jobid):
[5d24a81]235        job = self.jobs[self.active_jobs.pop(0)]
[776a659]236        self.finished_jobs.append(job)
237        job.finish()
[e58af05]238        return job.jid
[776a659]239
240    def start_job(self, jobid):
[5d24a81]241        job = self.jobs[self.active_jobs[0]]
[e58af05]242        if job.status != ipp.JobStates.PENDING:
[776a659]243            raise InvalidPrinterStateException(
[e58af05]244                "Invalid job state: %s" % job.status)
[776a659]245        job.play()
246
[e58af05]247    @property
248    def next_job(self):
249        if len(self.active_jobs) == 0:
250            job = None
251        else:
252            job = self.active_jobs[0]
253        return job       
254
[776a659]255    def get_job(self, jobid):
256        if jobid not in self.jobs:
257            raise InvalidJobException(jobid)
258        return self.jobs[jobid]
259
[b2e077a]260    def get_jobs(self):
[ee8e6d0]261        print self.active_jobs
[b2e077a]262        jobs = [self.jobs[job_id] for job_id in self.active_jobs]
[ee8e6d0]263        return jobs
[b2e077a]264
[ee8e6d0]265    # def __repr__(self):
266    #     return str(self)
[776a659]267
[ee8e6d0]268    # def __str__(self):
269    #     return "<Printer '%s'>" % self.name
Note: See TracBrowser for help on using the repository browser.