changeset 1144:b9981f50b82d

audioInputLevels robustness and cleanup Ignore-this: f7bf0ef344cc704ed15d5d7f330e235e darcs-hash:1699712f056d62957ff365b9f6051ca6ddc54eca
author drewp <drewp@bigasterisk.com>
date Sat, 03 Mar 2018 18:12:18 -0800
parents d1bc88f67969
children 0ba7a29a1886
files service/audioInputLevels/audioInputLevelsPulse.py service/audioInputLevels/pydeps service/audioInputLevels/requirements.txt
diffstat 3 files changed, 32 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/service/audioInputLevels/audioInputLevelsPulse.py	Sat Mar 03 18:09:34 2018 -0800
+++ b/service/audioInputLevels/audioInputLevelsPulse.py	Sat Mar 03 18:12:18 2018 -0800
@@ -1,6 +1,6 @@
 # based on http://freshfoo.com/blog/pulseaudio_monitoring
 from __future__ import division
-import socket, argparse, time
+import socket, argparse, time, logging, os
 from Queue import Queue
 from ctypes import POINTER, c_ubyte, c_void_p, c_ulong, cast
 from influxdb import InfluxDBClient
@@ -8,8 +8,10 @@
 # From https://github.com/Valodim/python-pulseaudio
 from pulseaudio import lib_pulseaudio as P
 
+logging.basicConfig(level=logging.INFO)
+log = logging.getLogger()
+
 METER_RATE = 1
-MAX_SAMPLE_VALUE = 127
 
 class PeakMonitor(object):
 
@@ -44,17 +46,22 @@
         state = P.pa_context_get_state(context)
 
         if state == P.PA_CONTEXT_READY:
-            print "Pulseaudio connection ready..."
+            log.info("Pulseaudio connection ready...")
             # Connected to Pulseaudio. Now request that source_info_cb
             # be called with information about the available sources.
             o = P.pa_context_get_source_info_list(context, self._source_info_cb, None)
             P.pa_operation_unref(o)
 
         elif state == P.PA_CONTEXT_FAILED :
-            print "Connection failed"
+            log.error("Connection failed")
+            os.abort()
 
         elif state == P.PA_CONTEXT_TERMINATED:
-            print "Connection terminated"
+            log.error("Connection terminated")
+            os.abort()
+
+        else:
+            log.info('context_notify_cb state=%r', state)
 
     def source_info_cb(self, context, source_info_p, _, __):
         if not source_info_p:
@@ -65,14 +72,15 @@
         if source_info.name == self.source_name:
             # Found the source we want to monitor for peak levels.
             # Tell PA to call stream_read_cb with peak samples.
-            print 'setting up peak recording using', source_info.name
-            print 'description:', source_info.description
+            log.info('setting up peak recording using %s', source_info.name)
+            log.info('description: %r', source_info.description)
+            
             samplespec = P.pa_sample_spec()
             samplespec.channels = 1
             samplespec.format = P.PA_SAMPLE_U8
             samplespec.rate = self.rate
-
-            pa_stream = P.pa_stream_new(context, "peak detect demo", samplespec, None)
+            pa_stream = P.pa_stream_new(context, "audioInputLevels", samplespec, None)
+            
             P.pa_stream_set_read_callback(pa_stream,
                                           self._stream_read_cb,
                                           source_info.index)
@@ -85,16 +93,19 @@
         data = c_void_p()
         P.pa_stream_peek(stream, data, c_ulong(length))
         data = cast(data, POINTER(c_ubyte))
-        for i in xrange(length):
-            # When PA_SAMPLE_U8 is used, samples values range from 128
-            # to 255 because the underlying audio data is signed but
-            # it doesn't make sense to return signed peaks.
-            self._samples.put(data[i] - 128)
+        try:
+            for i in xrange(length):
+                # When PA_SAMPLE_U8 is used, samples values range from 128
+                # to 255 because the underlying audio data is signed but
+                # it doesn't make sense to return signed peaks.
+                self._samples.put(data[i] - 128)
+        except ValueError:
+            # "data will be NULL and nbytes will contain the length of the hole"
+            log.info("skipping hole of length %s" % length)
+            # This seems to happen at startup for a while.
         P.pa_stream_drop(stream)
 
 def main():
-
-
     parser = argparse.ArgumentParser()
     parser.add_argument(
         '--source', required=True,
@@ -102,20 +113,15 @@
 
     args = parser.parse_args()
 
-    def ipv6Init(self, host="localhost", port=2003):
-        self._addr = (host, port, 0, 0)
-        self._sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
-        self._sock.connect(self._addr)
-
     influx = InfluxDBClient('bang6', 9060, 'root', 'root', 'main')
 
     hostname = socket.gethostname()
     monitor = PeakMonitor(args.source, METER_RATE)
     for sample in monitor:
-        #print ' %3d %s' % (sample, '>' * sample)
+        log.debug(' %3d %s', sample, '>' * sample)
         influx.write_points([{'measurement': 'audioLevel',
                               "tags": dict(stat='max', location=hostname),
-                              "fields": {"value": sample /  128},
+                              "fields": {"value": sample / 128},
                               "time": int(time.time())}], time_precision='s')
         
 if __name__ == '__main__':
--- a/service/audioInputLevels/pydeps	Sat Mar 03 18:09:34 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-galena==0.3
-libpulseaudio==1.1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/service/audioInputLevels/requirements.txt	Sat Mar 03 18:12:18 2018 -0800
@@ -0,0 +1,3 @@
+# upstream is missing
+#libpulseaudio==1.1
+influxdb==3.0.0