Index: server/lib/gutenbach/server/printer.py
===================================================================
--- server/lib/gutenbach/server/printer.py	(revision d04a6891fc6c9f9ce772732907214ccd85485868)
+++ server/lib/gutenbach/server/printer.py	(revision b2e077a94f58512ca52085a59f40ffecab7178d5)
@@ -1,25 +1,52 @@
+#import alsaaudio as aa
 from .exceptions import InvalidJobException, InvalidPrinterStateException
 from gutenbach.ipp.attribute import Attribute
-import alsaaudio as aa
-import gutenbach.ipp
+import gutenbach.ipp as ipp
+import gutenbach.ipp.constants as const
+import logging
+import time
 
 # initialize logger
 logger = logging.getLogger(__name__)
 
-class Printer(object):
-
-    def __init__(self, name, card, mixer):
-
-	self.name = name
-
-	if card >= len(aa.cards()):
-	    raise aa.ALSAAudioError(
-		"Audio card at index %d does not exist!" % card)
-	elif mixer not in aa.mixers(card):
-	    raise aa.ALSAAudioError(
-		"Audio mixer '%s' does not exist!" % mixer)
+class GutenbachPrinter(object):
+
+    attributes = [
+        "printer-uri-supported",
+        "uri-authentication-supported",
+        "uri-security-supported",
+        "printer-name",
+        "printer-state",
+        "printer-state-reasons",
+        "ipp-versions-supported",
+        "operations-supported",
+        "charset-configured",
+        "charset-supported",
+        "natural-language-configured",
+        "generated-natural-language-supported",
+        "document-format-default",
+        "document-format-supported",
+        "printer-is-accepting-jobs",
+        "queued-job-count",
+        "pdl-override-supported",
+        "printer-up-time",
+        "compression-supported"]
+
+    #def __init__(self, name, card, mixer):
+    def __init__(self, name):
+
+	self._name = name
+        self._uri = "ipp://localhost:8000/printers/" + self._name
+        self._time_created = int(time.time())
+
+	# if card >= len(aa.cards()):
+	#     raise aa.ALSAAudioError(
+	# 	"Audio card at index %d does not exist!" % card)
+	# elif mixer not in aa.mixers(card):
+	#     raise aa.ALSAAudioError(
+	# 	"Audio mixer '%s' does not exist!" % mixer)
 	
-	self.card = card
-	self.mixer = mixer
+	# self.card = card
+	# self.mixer = mixer
 
 	self.finished_jobs = []
@@ -29,12 +56,131 @@
 	self._next_jobid = 0
 
+    ## Printer attributes
+    @property
+    def printer_uri_supported(self):
+        return ipp.Attribute(
+            "printer-uri-supported",
+            [ipp.Value(ipp.Tags.URI, self._uri)])
+    
+    @property
+    def uri_authentication_supported(self):
+        return ipp.Attribute(
+            "uri-authentication-supported",
+            [ipp.Value(ipp.Tags.KEYWORD, "none")])
+
+    @property
+    def uri_security_supported(self):
+        return ipp.Attribute(
+            "uri-security-supported",
+            [ipp.Value(ipp.Tags.KEYWORD, "none")])
+
+    @property
+    def printer_name(self):
+        return ipp.Attribute(
+            "printer-name",
+            [ipp.Value(ipp.Tags.NAME_WITHOUT_LANGUAGE, self._name)])
+        
+    @property
+    def printer_state(self):
+        return ipp.Attribute(
+            "printer-state",
+            [ipp.Value(ipp.Tags.ENUM, const.PrinterStates.IDLE)])
+        
+    @property
+    def printer_state_reasons(self):
+        return ipp.Attribute(
+            "printer-state-reasons",
+            [ipp.Value(ipp.Tags.KEYWORD, "none")])
+
+    @property
+    def ipp_versions_supported(self):
+        return ipp.Attribute(
+            "ipp-versions-supported",
+            [ipp.Value(ipp.Tags.KEYWORD, "1.0"),
+             ipp.Value(ipp.Tags.KEYWORD, "1.1")])
+
+    # XXX: We should query ourself for the supported operations
+    @property
+    def operations_supported(self):
+        return ipp.Attribute(
+            "operations-supported",
+            [ipp.Value(ipp.Tags.ENUM, const.Operations.GET_JOBS)])
+
+    @property
+    def charset_configured(self):
+        return ipp.Attribute(
+            "charset-configured",
+            [ipp.Value(ipp.Tags.CHARSET, "utf-8")])
+
+    @property
+    def charset_supported(self):
+        return ipp.Attribute(
+            "charset-supported",
+            [ipp.Value(ipp.Tags.CHARSET, "utf-8")])
+
+    @property
+    def natural_language_configured(self):
+        return ipp.Attribute(
+            "natural-language-configured",
+            [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, "en-us")])
+
+    @property
+    def generated_natural_language_supported(self):
+        return ipp.Attribute(
+            "generated-natural-language-supported",
+            [ipp.Value(ipp.Tags.NATURAL_LANGUAGE, "en-us")])
+
+    @property
+    def document_format_default(self):
+        return ipp.Attribute(
+            "document-format-default",
+            [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "application/octet-stream")])
+
+    @property
+    def document_format_supported(self):
+        return ipp.Attribute(
+            "document-format-supported",
+            [ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "application/octet-stream"),
+             ipp.Value(ipp.Tags.MIME_MEDIA_TYPE, "audio/mp3")])
+
+    @property
+    def printer_is_accepting_jobs(self):
+        return ipp.Attribute(
+            "printer-is-accepting-jobs",
+            [ipp.Value(ipp.Tags.BOOLEAN, True)])
+
+    @property
+    def queued_job_count(self):
+        return ipp.Attribute(
+            "queued-job-count",
+            [ipp.Value(ipp.Tags.INTEGER, len(self.active_jobs))])
+
+    @property
+    def pdl_override_supported(self):
+        return ipp.Attribute(
+            "pdl-override-supported",
+            [ipp.Value(ipp.Tags.KEYWORD, "not-attempted")])
+
+    @property
+    def printer_up_time(self):
+        return ipp.Attribute(
+            "printer-up-time",
+            [ipp.Value(ipp.Tags.INTEGER, int(time.time()) - self._time_created)])
+
+    @property
+    def compression_supported(self):
+        return ipp.Attribute(
+            "compression-supported",
+            [ipp.Value(ipp.Tags.KEYWORD, "none")])
+
+    def get_printer_attributes(self, request):
+        attributes = [getattr(self, attr.replace("-", "_")) for attr in self.attributes]
+        return attributes
+
+    ## Printer operations
     @property
     def next_jobid(self):
 	self._next_jobid += 1
 	return self._next_jobid
-
-    @next_jobid.setter
-    def next_jobid(self, val):
-	raise AttributeError("Setting next_jobid is illegal!")
 
     def print_job(self, job):
@@ -75,7 +221,11 @@
 	return self.jobs[jobid]
 
+    def get_jobs(self):
+        jobs = [self.jobs[job_id] for job_id in self.active_jobs]
+        return jobs            
+
     def __repr__(self):
 	return str(self)
 
     def __str__(self):
-	return "<Printer '%s'>" % self.name
+	return "<Printer '%s'>" % self._name
