source: server/lib/gutenbach/server/player.py @ b8c3505

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

Better threading with job.py and player.py

  • Property mode set to 100644
File size: 3.8 KB
Line 
1import logging
2import threading
3import subprocess
4import time
5
6# initialize logger
7logger = logging.getLogger(__name__)
8
9class Player(threading.Thread):
10
11    def __init__(self, fh, *args, **kwargs):
12        self.lock = threading.RLock()
13
14        with self.lock:
15            super(Player, self).__init__(*args, **kwargs)
16            self.fh = fh
17            self.player = None
18            self._callback = None
19            self._paused = False
20            self._done = False
21            self._dryrun = False
22            self._dryrun_time = 0.5
23            self._lag = 0.01
24
25    @property
26    def is_playing(self):
27        with self.lock:
28            if self._dryrun:
29                playing = self.isAlive() and not self.is_done
30            else:
31                playing = self.isAlive() and \
32                          not self.is_done and \
33                          self.player is not None and \
34                          self.player.poll() is None
35        return playing
36
37    @property
38    def is_paused(self):
39        with self.lock:
40            paused = self.is_playing and self._paused
41        return paused
42
43    @property
44    def is_done(self):
45        return self._done
46
47    @property
48    def callback(self):
49        return self._callback
50    @callback.setter
51    def callback(self, val):
52        with self.lock:
53            self._callback = val
54
55    def start(self):
56        super(Player, self).start()
57        time.sleep(self._lag)
58
59    def run(self):
60        if self.fh is None:
61            raise ValueError, "file handler is None"
62       
63        logger.info("playing file '%s'" % self.fh.name)
64
65        with self.lock:
66            self._paused = False
67            self._done = False
68
69        if self._dryrun:
70            step = 0.01
71            while self._dryrun_time > 0:
72                time.sleep(step)
73                self._dryrun_time -= step
74                while self.is_paused:
75                    time.sleep(0.01)
76
77        else:
78            # open mplayer
79            with self.lock:
80                self.player = subprocess.Popen(
81                    "/usr/bin/mplayer -really-quiet -slave %s" % self.fh.name,
82                    shell=True,
83                    stdin=subprocess.PIPE,
84                    stderr=subprocess.PIPE,
85                    stdout=subprocess.PIPE)
86
87            # wait for mplayer to finish
88            while True:
89                with self.lock:
90                    playing = self.is_playing
91                if not playing:
92                    break
93                time.sleep(0.1)
94
95            logger.info("mplayer finished with code %d" % self.player.returncode)
96       
97            # get output from mplayer and log it
98            with self.lock:
99                stderr = self.player.stderr.read()
100                stdout = self.player.stdout.read()
101           
102            if stderr.strip() != "":
103                logger.error(stderr)
104            if stdout.strip() != "":
105                logger.debug(stdout)
106
107        with self.lock:
108            if self.callback:
109                self.callback()
110            self._done = True
111
112    def mplayer_pause(self):
113        with self.lock:
114            if self.is_playing:
115                if not self._dryrun:
116                    self.player.stdin.write("pause\n")
117                self._paused = not(self._paused)
118                logger.info("paused: %s", self.is_paused)
119            else:
120                logger.warning("trying to pause non-playing job")
121        time.sleep(self._lag)
122               
123    def mplayer_stop(self):
124        with self.lock:
125            if self.is_playing:
126                if not self._dryrun:
127                    self.player.stdin.write("quit\n")
128                else:
129                    self._dryrun_time = 0.0
130                logger.info("stopped")
131            else:
132                logger.warning("trying to stop non-playing job")
133        self.join()
Note: See TracBrowser for help on using the repository browser.