Mercurial > code > home > repos > homeauto
comparison service/playSound/playSound.py @ 669:b27a4652cd84
playsound is working ok on dash right now
Ignore-this: 3a0b801cb75eb157a7d189f9de5d7b0c
author | drewp@bigasterisk.com |
---|---|
date | Sun, 22 Dec 2019 00:34:08 -0800 |
parents | aaabba10ce04 |
children |
comparison
equal
deleted
inserted
replaced
668:aaabba10ce04 | 669:b27a4652cd84 |
---|---|
1 """ | 1 """ |
2 play sounds according to POST requests. | 2 play sounds according to POST requests. |
3 """ | 3 """ |
4 from docopt import docopt | 4 from docopt import docopt |
5 import cyclone.web | 5 import cyclone.web |
6 import os, sys, tempfile, itertools | 6 import os, sys, tempfile, itertools, subprocess |
7 import treq | |
7 from twisted.internet import reactor | 8 from twisted.internet import reactor |
8 from cyclone.httpclient import fetch | 9 from twisted.internet.defer import inlineCallbacks |
9 from twisted.web.static import File | 10 from twisted.web.static import File |
10 from standardservice.logsetup import log, verboseLogging | 11 from standardservice.logsetup import log, verboseLogging |
11 | 12 |
12 class LOADING(object): pass | 13 class LOADING(object): pass |
13 | 14 |
16 self.buffers = {} # URIRef : path | 17 self.buffers = {} # URIRef : path |
17 self.playingSources = [] | 18 self.playingSources = [] |
18 self.queued = [] | 19 self.queued = [] |
19 self.volume = 1 # level for the next sound that's played (or existing instances of the same sound) | 20 self.volume = 1 # level for the next sound that's played (or existing instances of the same sound) |
20 | 21 |
22 @inlineCallbacks | |
21 def _getSound(self, uri): | 23 def _getSound(self, uri): |
22 def done(resp): | 24 resp = yield treq.get(uri.encode('utf8')) |
23 print('save') | 25 body = yield treq.content(resp) |
24 body = bytes(resp.body) | 26 path = '/tmp/sound_%s' % hash(uri) |
25 path = '/tmp/sound_%s' % hash(uri) | 27 with open(path, 'wb') as out: |
26 with open(path, 'wb') as out: | 28 out.write(body) |
27 out.write(body) | 29 log.info('write %s bytes to %s', len(body), path) |
28 log.info('write %s bytes to %s', len(resp.body), path) | 30 self.buffers[uri] = path |
29 self.buffers[uri] = path | 31 print('donesave') |
30 print('donesave') | |
31 | |
32 return fetch(uri.encode('utf8')).addCallback(done).addErrback(log.error) | |
33 | 32 |
34 def playEffect(self, uri: str): | 33 def playEffect(self, uri: str): |
35 if uri not in self.buffers: | 34 if uri not in self.buffers: |
36 self.buffers[uri] = LOADING | 35 self.buffers[uri] = LOADING |
37 self._getSound(uri).addCallback(lambda ret: self.playEffect(uri)) | 36 self._getSound(uri).addCallback(lambda ret: self.playEffect(uri)).addErrback(log.error) |
38 return | 37 return b'will play after load' |
39 if self.buffers[uri] is LOADING: | 38 if self.buffers[uri] is LOADING: |
40 # The first playback loads then plays, but any attempts | 39 # The first playback loads then plays, but any attempts |
41 # during that load are dropped, not queued. | 40 # during that load are dropped, not queued. |
42 return | 41 return |
43 snd = self.buffers[uri] | 42 snd = self.buffers[uri] |
44 print('subp') | 43 print('subp') |
45 subprocess.check_call(['paplay', snd]) | 44 subprocess.check_call(['paplay', snd]) |
46 return | 45 return b'played' |
47 | 46 |
48 def done(self, src): | 47 def done(self, src): |
49 try: | 48 try: |
50 self.playingSources.remove(src) | 49 self.playingSources.remove(src) |
51 except ValueError: | 50 except ValueError: |
63 self.render('index.html') | 62 self.render('index.html') |
64 | 63 |
65 class PlaySound(cyclone.web.RequestHandler): | 64 class PlaySound(cyclone.web.RequestHandler): |
66 def post(self): | 65 def post(self): |
67 uri = self.get_argument('uri') | 66 uri = self.get_argument('uri') |
68 self.settings.sfx.playEffect(uri) | 67 return self.settings.sfx.playEffect(uri) |
69 return "ok" | |
70 | 68 |
71 class Volume(cyclone.web.RequestHandler): | 69 class Volume(cyclone.web.RequestHandler): |
72 def put(self): | 70 def put(self): |
73 self.settings.sfx.setVolume(float(self.get_argument('v'))) | 71 self.settings.sfx.setVolume(float(self.get_argument('v'))) |
74 return "ok" | 72 return b"ok" |
75 | 73 |
76 class StopAll(cyclone.web.RequestHandler): | 74 class StopAll(cyclone.web.RequestHandler): |
77 def post(self): | 75 def post(self): |
78 self.settings.sfx.stopAll() | 76 self.settings.sfx.stopAll() |
79 return "ok" | 77 return b"ok" |
80 | 78 |
81 | 79 |
82 if __name__ == '__main__': | 80 if __name__ == '__main__': |
83 arg = docopt(''' | 81 arg = docopt(''' |
84 Usage: playSound.py [options] | 82 Usage: playSound.py [options] |