Parameter file to store selected audio device
authorNirgal <contact_ampy@nirgal.com>
Mon, 14 Oct 2019 22:17:42 +0000 (22:17 +0000)
committerNirgal <contact_ampy@nirgal.com>
Mon, 14 Oct 2019 22:20:53 +0000 (22:20 +0000)
README.rst
device.py [new file with mode: 0755]
devices.py [deleted file]
record.py
run.py

index 52ef1dd6e4569edfbe01937391fe843d3a0ed613..7a752b69139c5656d99193d6060d6dc1a9c84a78 100644 (file)
@@ -11,7 +11,7 @@ It is designed for self-hosting, without any third party analysing when you're h
 Hardware
 ========
 
-You need a ampmeter sensor that outputs an audio signal.
+You need a ammeter sensor that outputs an audio signal.
 
 It has been tested with `this YHDC sensor`_.
 
@@ -85,7 +85,7 @@ Configuration
 Select the alsa audio input
 ---------------------------
 
-Run ``device.py`` to find out which entry you should use.
+Run ``device.py`` to select which entry you want to use.
 
 Then adjust DEVICE in run.py
 
diff --git a/device.py b/device.py
new file mode 100755 (executable)
index 0000000..9035cec
--- /dev/null
+++ b/device.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python3
+
+import json
+import os
+import sys
+
+import pyaudio
+
+PARAMFILE = '/var/lib/ampy/params.json'
+
+p = pyaudio.PyAudio()
+
+
+def main():
+    import argparse
+
+    parser = argparse.ArgumentParser(description='Ampy configuration tool')
+    parser.add_argument(
+            'device',
+            metavar='channel',
+            help='set audio input channel to use',
+            type=int,
+            choices=range(p.get_device_count()),
+            nargs='?',
+            )
+    args = parser.parse_args()
+
+    # Read the old values
+
+    params = {}
+    params_device = None
+    try:
+        with open(PARAMFILE) as f:
+            params = json.loads(f.read())
+        params_device = params['alsadevice']
+    except FileNotFoundError:
+        print(file=sys.stderr)
+        print("Parameters file not found. Device has never been selected?",
+              file=sys.stderr)
+    except json.decoder.JSONDecodeError:
+        print(file=sys.stderr)
+        print("{} is corrupted: Try deleting it?".format(PARAMFILE),
+              file=sys.stderr)
+    except KeyError:
+        print(file=sys.stderr)
+        print("Parameter file has no device value. "
+              " Device has never been selected?",
+              file=sys.stderr)
+
+    # Store the new value in device var and in file
+
+    stored = False
+    if args.device is None:
+        # No argument? Use the existing params
+        device = params_device
+    else:
+        if args.device == params_device:
+            # No change
+            device = params_device
+        else:
+            params['alsadevice'] = args.device
+            try:
+                with open(PARAMFILE+'.new', 'w') as f:
+                    f.write(json.dumps(params))
+                os.rename(PARAMFILE+'.new', PARAMFILE)
+                device = args.device
+                stored = True
+            except PermissionError:
+                device = params_device
+                print(file=sys.stderr)
+                print("ERROR Permission denied. Are you in group ampy?"
+                      " Try sudo -u ampy ...",
+                      file=sys.stderr)
+
+    # Print state
+
+    print('Audio input devices:')
+    for i in range(p.get_device_count()):
+        print(' * ' if i == device else '   ',
+              i,
+              p.get_device_info_by_index(i)['name'])
+
+    if device is None:
+        print()
+        print("Which audio input device would you like to listen to?")
+        print("Please pick a number.")
+    if stored:
+        print()
+        print("Value stored. Please restart ampy daemon.")
+
+
+if __name__ == '__main__':
+    main()
diff --git a/devices.py b/devices.py
deleted file mode 100755 (executable)
index 20c3fa4..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/python3
-
-import pyaudio
-
-p = pyaudio.PyAudio()
-
-print('Listing api:')
-for i in range(p.get_host_api_count()):
-    print(i, p.get_host_api_info_by_index(i)['name'])
-
-print('Listing devices:')
-for i in range(p.get_device_count()):
-    print(i, p.get_device_info_by_index(i)['name'])
index 69cb10fa91f8c8e944053b8315c9714bab67fbfb..61020c011943f24a55655ae828297b81cb566d32 100755 (executable)
--- a/record.py
+++ b/record.py
@@ -4,32 +4,40 @@ PyAudio example: Record a few seconds of audio and save to a WAVE
 file.
 """
 
+import json
 import sys
 import wave
 
 import pyaudio
 
+PARAMFILE = '/var/lib/ampy/params.json'
 CHUNK = 1024
 FORMAT = pyaudio.paInt16
 CHANNELS = 2
 RATE = 44100
 RECORD_SECONDS = 5
-WAVE_OUTPUT_FILENAME = "output.wav"
-DEVICE = 5
+WAVE_OUTPUT_FILENAME = "/tmp/output.wav"
 
 if sys.platform == 'darwin':
     CHANNELS = 1
 
 p = pyaudio.PyAudio()
 
+try:
+    with open(PARAMFILE) as f:
+        params = json.loads(f.read())
+        alsadevice = params['alsadevice']
+except (FileNotFoundError, json.decoder.JSONDecodeError, KeyError):
+    print("Error reading the parameters. Please run device.py")
+
 stream = p.open(format=FORMAT,
                 channels=CHANNELS,
                 rate=RATE,
                 input=True,
-                input_device_index=DEVICE,
+                input_device_index=alsadevice,
                 frames_per_buffer=CHUNK)
 
-print("* recording")
+print("* recording to", WAVE_OUTPUT_FILENAME)
 
 frames = []
 
diff --git a/run.py b/run.py
index 3a599fc2f7d6931069d7462e79abe25e1bff5c8b..cfdb9500c40121f2a88fbb7f83a1014fb72216e1 100755 (executable)
--- a/run.py
+++ b/run.py
@@ -4,15 +4,16 @@ PyAudio example: Record a few seconds of audio and save to a WAVE
 file.
 """
 
+import json
 import os
 import struct
 import time
 
 import pyaudio
 
+PARAMFILE = '/var/lib/ampy/params.json'
 FORMAT = pyaudio.paInt32  # Format
 STRUCTFORMAT = 'i'  # Format for python struct module
-DEVICE = 5  # which alsa decive to read
 RATE = 44100
 RECORD_SECONDS = 0.5
 
@@ -36,17 +37,32 @@ VOLUME_CONSTANT = 132360.98315789475
 # average 4806.6W
 
 
+def read_params_file():
+    with open(PARAMFILE) as f:
+        params = json.loads(f.read())
+    return params
+
+
 def loop(optrecord, optstats):
+    try:
+        params = read_params_file()
+        alsadevice = params['alsadevice']
+    except (FileNotFoundError, json.decoder.JSONDecodeError, KeyError):
+        print("Error reading the parameters. Please run device.py")
+
     p = pyaudio.PyAudio()
+    print("PyAudio opened")
+
+    print("Ampy Selected input device #{}: {}".format(
+        alsadevice, p.get_device_info_by_index(alsadevice)['name']))
 
-    print("opened")
     NSAMPLE = int(RATE * RECORD_SECONDS)
     stream = p.open(
             format=FORMAT,
             channels=1,  # Our ampmeter always returns 0 on the second channel
             rate=RATE,
             input=True,
-            input_device_index=DEVICE)
+            input_device_index=alsadevice)
 
     structformat = '<' + STRUCTFORMAT * NSAMPLE
     while(True):
@@ -91,7 +107,7 @@ def loop(optrecord, optstats):
 def main():
     import argparse
 
-    parser = argparse.ArgumentParser(description='Ampemeter processing')
+    parser = argparse.ArgumentParser(description='Ammeter processing')
     parser.add_argument(
             '--stats',
             action='store_true',