Index: server/lib/TODO
===================================================================
--- server/lib/TODO	(revision f0807b837cb15a66cd237eb6347a4fa47a741dba)
+++ server/lib/TODO	(revision 1b6dc137690cd01fe3d742c314f5810b8e88ca6b)
@@ -16,6 +16,6 @@
 
 - add support in printer.py for:
-     [ ] print job
-     [ ] validate job
+     [x] print job
+     [x] validate job
      [x] pause printer
      [x] resume printer
@@ -30,20 +30,27 @@
      [x] resume job
 
-- finish test cases for printer.py
-- write test cases for requests.py
-- write convenience client-side API
-- write test cases for future client API
-- all the documentation
-- deal with all the code marked 'XXX'
-- setuptools entry points for notification system (e.g. zephyr)
-- check test case coverage ( http://nedbatchelder.com/code/coverage/ )
-- deal with queue management/reordering
-- add support for volume management
-- make sure all CUPS commands are compatible
-- rewrite gbr/gbq/etc. scripts to use client API
-- rewrite server-side queue display to use API
-- support authentication/security
-- why doesn't the bug tracker work?! relatedly, figure out a
-  solution that makes it easier for non-MIT developers to contribute
+- server stuff
+     [ ] write convenience client-side API
+     [ ] setuptools entry points for notification system (e.g. zephyr)
+     [ ] deal with queue management/reordering
+     [ ] add support for volume management
+     [ ] support authentication/security
+
+- client-ish stuff
+     [ ] rewrite gbr/gbq/etc. scripts to use client API
+     [ ] rewrite server-side queue display to use API
+
+- misc
+     [ ] make sure all CUPS commands are compatible
+     [ ] deal with all the code marked 'XXX'
+
+- documentation and testing
+     [ ] finish test cases for printer.py
+     [ ] write test cases for requests.py
+     [ ] write test cases for future client API
+     [ ] all the documentation
+     [ ] check test case coverage ( http://nedbatchelder.com/code/coverage/ )
+     [ ] why doesn't the bug tracker work?! relatedly, figure out a
+         solution that makes it easier for non-MIT developers to contribute
 
 Ponies
Index: server/lib/gutenbach-config
===================================================================
--- server/lib/gutenbach-config	(revision a9eb577e4cd2b47f81db5ec3c68805dcb0e6362b)
+++ server/lib/gutenbach-config	(revision ab7c1dd8e8ec638a4adc2e31dc8d9f871a625556)
@@ -1,5 +1,5 @@
 port: 8000
 loglevel: debug
-logfile: gutenbach.log
+#logfile: gutenbach.log
 
 printers:
Index: server/lib/gutenbach/server/job.py
===================================================================
--- server/lib/gutenbach/server/job.py	(revision 57bc2dca8c24215f23d2db575746bec4b66fc245)
+++ server/lib/gutenbach/server/job.py	(revision bd5bffcd3ecf6e7bb5aefc5caae54483392c5f06)
@@ -56,10 +56,12 @@
     def __del__(self):
         if self.player:
-            self.player.mplayer_stop()
+            if self.player.is_playing:
+                self.player.mplayer_stop()
+            if self.player.fh:
+                if self.player.fh.closed:
+                    self.player.fh.close()
             self.player = None
-        if self.document and not self.document.closed:
-            self.document.close()
-            self.document = None
-
+
+        self.document = None
         self.id = None
         self.creator = None
Index: server/lib/gutenbach/server/player.py
===================================================================
--- server/lib/gutenbach/server/player.py	(revision cf0d7e841609343938618ddcce617a7fdb26fd9a)
+++ server/lib/gutenbach/server/player.py	(revision bd5bffcd3ecf6e7bb5aefc5caae54483392c5f06)
@@ -28,11 +28,14 @@
     def is_playing(self):
         if self._dryrun:
-            return self.isAlive() and not self.is_done
+            return self.ident is not None and \
+                   self.isAlive() and \
+                   not self.is_done
         else:
-            return self.isAlive() and \
-                      not self.is_done and \
-                      self.player is not None and \
-                      self.player.poll() is None
-
+            return self.ident is not None and \
+                   self.isAlive() and \
+                   not self.is_done and \
+                   self.player is not None and \
+                   self.player.poll() is None
+        
     @property
     @sync
@@ -121,7 +124,7 @@
                 logger.warning("trying to pause non-playing job")
         time.sleep(self._lag)
-                
+
     def mplayer_stop(self):
-        # Note: Inner Lock due to join.
+        # Note: Inner lock due to join.
         with self.lock:
             if self.is_playing:
@@ -134,2 +137,3 @@
                 logger.warning("trying to stop non-playing job")
         self.join()
+
Index: server/test/server/job.py
===================================================================
--- server/test/server/job.py	(revision adf8cf08aeb3ec6309cc42b014118ef3a11e51fb)
+++ server/test/server/job.py	(revision bd5bffcd3ecf6e7bb5aefc5caae54483392c5f06)
@@ -6,4 +6,5 @@
 import sys
 import time
+import logging
 
 def make_tempfile():
@@ -204,3 +205,4 @@
 
 if __name__ == "__main__":
+    logging.basicConfig(loglevel=logging.CRITICAL)
     unittest.main()
