[33ea505] | 1 | from .errors import InvalidJobStateException, MissingDataException |
---|
[eee389a] | 2 | from .player import Player |
---|
[b01b6d1] | 3 | from gutenbach.ipp import JobStates as States |
---|
[ee8e6d0] | 4 | import logging |
---|
[33ea505] | 5 | import os |
---|
[d04a689] | 6 | |
---|
| 7 | # initialize logger |
---|
| 8 | logger = logging.getLogger(__name__) |
---|
[776a659] | 9 | |
---|
[33ea505] | 10 | class GutenbachJob(object): |
---|
[b2e077a] | 11 | |
---|
[33ea505] | 12 | def __init__(self, job_id=None, creator=None, name=None): |
---|
[b01b6d1] | 13 | """Create an empty Gutenbach job. |
---|
[e58af05] | 14 | |
---|
[776a659] | 15 | """ |
---|
[ee8e6d0] | 16 | |
---|
[b01b6d1] | 17 | self.player = None |
---|
[ee8e6d0] | 18 | |
---|
[b01b6d1] | 19 | self.id = job_id |
---|
| 20 | self.creator = creator |
---|
| 21 | self.name = name |
---|
[eee389a] | 22 | self.state = States.HELD |
---|
| 23 | self.priority = 1 |
---|
[33ea505] | 24 | self.document = None |
---|
[ee8e6d0] | 25 | |
---|
[b01b6d1] | 26 | def __repr__(self): |
---|
| 27 | return str(self) |
---|
| 28 | |
---|
| 29 | def __str__(self): |
---|
| 30 | return "<Job %d '%s'>" % (self.id, self.name) |
---|
[e58af05] | 31 | |
---|
[eee389a] | 32 | def __cmp__(self, other): |
---|
| 33 | return cmp(self.priority, other.priority) |
---|
| 34 | |
---|
[b01b6d1] | 35 | ###################################################################### |
---|
| 36 | ### Properties ### |
---|
| 37 | ###################################################################### |
---|
[1a63bf7] | 38 | |
---|
[b01b6d1] | 39 | @property |
---|
| 40 | def id(self): |
---|
| 41 | """Unique job identifier. Should be a positive integer, |
---|
| 42 | except when unassigned, when it defaults to -1. |
---|
| 43 | |
---|
| 44 | """ |
---|
| 45 | return self._id |
---|
| 46 | @id.setter |
---|
| 47 | def id(self, val): |
---|
[1a63bf7] | 48 | try: |
---|
[b01b6d1] | 49 | self._id = int(val) |
---|
| 50 | except TypeError: |
---|
| 51 | self._id = -1 |
---|
| 52 | |
---|
| 53 | @property |
---|
| 54 | def creator(self): |
---|
| 55 | """The user who created the job; analogous to the IPP |
---|
| 56 | requesting-user-name. |
---|
| 57 | |
---|
| 58 | """ |
---|
| 59 | return self._creator |
---|
| 60 | @creator.setter |
---|
| 61 | def creator(self, val): |
---|
| 62 | if val is None: |
---|
| 63 | self._creator = "" |
---|
| 64 | else: |
---|
| 65 | self._creator = str(val) |
---|
| 66 | |
---|
| 67 | @property |
---|
| 68 | def name(self): |
---|
| 69 | """The job's name. |
---|
| 70 | |
---|
| 71 | """ |
---|
| 72 | return self._name |
---|
| 73 | @name.setter |
---|
| 74 | def name(self, val): |
---|
| 75 | if val is None: |
---|
| 76 | self._name = "" |
---|
| 77 | else: |
---|
| 78 | self._name = str(val) |
---|
| 79 | |
---|
| 80 | @property |
---|
| 81 | def size(self): |
---|
| 82 | """The size of the job in bytes. |
---|
[1a63bf7] | 83 | |
---|
[b01b6d1] | 84 | """ |
---|
[ee8e6d0] | 85 | try: |
---|
[33ea505] | 86 | size = os.path.getsize(self.document) |
---|
| 87 | except: |
---|
| 88 | size = 0 |
---|
| 89 | return size |
---|
[b01b6d1] | 90 | |
---|
[eee389a] | 91 | @property |
---|
| 92 | def is_playing(self): |
---|
| 93 | return self.state == States.PROCESSING |
---|
| 94 | |
---|
| 95 | @property |
---|
| 96 | def is_ready(self): |
---|
| 97 | return self.state == States.PENDING |
---|
| 98 | |
---|
| 99 | @property |
---|
| 100 | def is_finished(self): |
---|
[34a4e5d] | 101 | return self.state != States.PENDING and \ |
---|
| 102 | self.state != States.PROCESSING and \ |
---|
| 103 | self.state != States.HELD |
---|
[eee389a] | 104 | |
---|
[b01b6d1] | 105 | ###################################################################### |
---|
| 106 | ### Methods ### |
---|
| 107 | ###################################################################### |
---|
| 108 | |
---|
[33ea505] | 109 | def spool(self, document, username=None): |
---|
| 110 | if self.state != States.HELD: |
---|
| 111 | raise InvalidJobStateException(self.state) |
---|
| 112 | |
---|
| 113 | self.document = document.name |
---|
| 114 | self.player = Player(document) |
---|
| 115 | self.creator = username |
---|
| 116 | self.state = States.PENDING |
---|
| 117 | |
---|
| 118 | logger.debug("document for job %d is '%s'" % (self.id, self.document)) |
---|
| 119 | |
---|
| 120 | |
---|
[b01b6d1] | 121 | def play(self): |
---|
[33ea505] | 122 | """Non-blocking play function. Sets the job state to |
---|
| 123 | PROCESSING. |
---|
| 124 | |
---|
| 125 | Raises |
---|
| 126 | ------ |
---|
| 127 | InvalidJobStateException |
---|
| 128 | If the job is not ready to be played. |
---|
[eee389a] | 129 | |
---|
| 130 | """ |
---|
| 131 | |
---|
| 132 | # make sure the job is waiting to be played and that it's |
---|
| 133 | # valid |
---|
[33ea505] | 134 | if not self.is_ready: |
---|
[eee389a] | 135 | raise InvalidJobStateException(self.state) |
---|
| 136 | |
---|
| 137 | # and set the state to processing if we're good to go |
---|
[b01b6d1] | 138 | logger.info("playing job %s" % str(self)) |
---|
[33ea505] | 139 | |
---|
| 140 | def _completed(): |
---|
| 141 | logger.info("completed job %s" % str(self)) |
---|
| 142 | self.state = States.COMPLETE |
---|
| 143 | self.player = None |
---|
| 144 | |
---|
[eee389a] | 145 | self.state = States.PROCESSING |
---|
[33ea505] | 146 | self.player.callback = _completed |
---|
[d21198f] | 147 | self.player.start() |
---|
[eee389a] | 148 | |
---|
| 149 | def pause(self): |
---|
[33ea505] | 150 | """Non-blocking pause function. Sets the job state to |
---|
| 151 | STOPPED. |
---|
| 152 | |
---|
| 153 | """ |
---|
| 154 | |
---|
| 155 | if not self.is_playing: |
---|
| 156 | raise InvalidJobStateException(self.state) |
---|
| 157 | |
---|
| 158 | self.player.mplayer_pause() |
---|
| 159 | self.state = States.STOPPED |
---|
[34a4e5d] | 160 | |
---|
| 161 | def cancel(self): |
---|
[33ea505] | 162 | def _canceled(): |
---|
| 163 | logger.info("canceled job %s" % str(self)) |
---|
| 164 | self.state = States.CANCELLED |
---|
| 165 | self.player = None |
---|
| 166 | |
---|
[34a4e5d] | 167 | if self.is_playing: |
---|
[33ea505] | 168 | self.player.callback = _canceled |
---|
[34a4e5d] | 169 | self.player.mplayer_stop() |
---|
[33ea505] | 170 | elif self.is_finished: |
---|
| 171 | raise InvalidJobStateException(self.state) |
---|
| 172 | |
---|
[34a4e5d] | 173 | self.state = States.CANCELLED |
---|
[eee389a] | 174 | |
---|
[34a4e5d] | 175 | def abort(self): |
---|
[33ea505] | 176 | def _aborted(): |
---|
| 177 | logger.info("aborted job %s" % str(self)) |
---|
| 178 | self.state = States.ABORTED |
---|
| 179 | self.player = None |
---|
| 180 | |
---|
[34a4e5d] | 181 | if self.is_playing: |
---|
[33ea505] | 182 | self.player.callback = _aborted |
---|
[eee389a] | 183 | self.player.mplayer_stop() |
---|
[33ea505] | 184 | elif self.is_finished: |
---|
[eee389a] | 185 | raise InvalidJobStateException(self.state) |
---|
[b01b6d1] | 186 | |
---|
[33ea505] | 187 | self.state = States.ABORTED |
---|
[776a659] | 188 | |
---|
| 189 | |
---|