parallelise serial port usage and I/O for writing sounds files
parallelise serial port usage and I/O for writing sounds files

file:a/scannr.py -> file:b/scannr.py
--- a/scannr.py
+++ b/scannr.py
@@ -12,60 +12,102 @@
 #python -m serial.tools.miniterm -p COM20 -e -b 115200 --cr
 import psycopg2
 import csv
-import sys,os
+import sys
+import os
 
 
 sys.path.insert(0, os.path.join(os.path.dirname(__file__) or '.', 'pynma'))
 import pynma
 
 filename = "demo.wav"
+last_call = (None, None, None)
 MIN_LENGTH = 90000
+lock = threading.RLock()
 
 
-def worker(filename, length):
+def get_call():
+    global lock
+    with lock:
+        ser.write("GLG\r")
+        line = ser.readline()   # read a '\n' terminated line
+        print line
+        reader = csv.reader([line])
+        for row in reader:
+            #GLG,40078,NFM,0,0,CanberraBlackMnt,AustralianCapita,SES Ops 1,1,0
+            #,NONE,NONE,NONE
+            if (row[0] != 'GLG' or row[1] == ''):
+                print "uh oh"
+                return (None, None, None)
+            if (row[1] != ''):
+                tgid = row[1]
+                #nma.push("scannr", "ping", filename, "http://www.google.com")
+                tgname = row[7]
+                sitename = row[5]
+                return (tgid, tgname, sitename)
 
+
+def log_recording(tgid, tgname, sitename, filename, length):
+    cur = conn.cursor()
+    cur.execute("INSERT INTO recordings \
+    (tgid, tgname, sitename, filename, length)\
+     VALUES (%s, %s, %s, %s, %s)",( tgid, tgname, sitename, filename, length))
+    conn.commit()
+    cur.close()
+
+
+def tgid_worker():
+    global last_call
+    last_call = get_call()
+
+
+def save_worker(filename, length):
+    global last_call
     """thread worker function
     http://www.doughellmann.com/PyMOTW/threading/
     https://github.com/uskr/pynma
 ffmpeg -i 2012-09-29-1348911268.34-demo.wav -ar 8000 -ab 4.75k test.3gp
-http://stackoverflow.com/questions/2559746/getting-error-while-converting-wav-to-amr-using-ffmpeg
+http://stackoverflow.com/questions/2559746/getting-error-while-converting-
+wav-to-amr-using-ffmpeg
 """
-    print 'Worker for '+filename
-    ser.write("GLG\r")   
-    line = ser.readline()   # read a '\n' terminated line
-    print line
-    reader = csv.reader([line])
-    for row in reader:
-        #GLG,40078,NFM,0,0,CanberraBlackMnt,AustralianCapita,SES Ops 1,1,0,NONE,NONE,NONE
-        if (row[0] != 'GLG'):
-            print "uh oh"
-        if (row[1] != ''):  
-            tgid = row[1]
-            #nma.push("scannr", "ping", filename, "http://www.google.com")
-            tgname = row[7]
-            sitename = row[5]
-            """http://initd.org/psycopg/docs/usage.html"""
-            cur = conn.cursor()
-            cur.execute("INSERT INTO recordings (filename,tgid,tgname,sitename,length) VALUES (%s, %s,%s, %s, %s)",(filename,tgid,tgname,sitename, length))
-            conn.commit()
-            cur.close()
+    print 'Worker for ' + filename
+    (oldtgid, oldtgname, oldsitename) = last_call
+    (tgid, tgname, sitename) = get_call()
+    if oldtgid == tgid:
+        if tgid == None or tgid == '':
+            print filename + " has no TGID"
         else:
-            print filename+" has no TGID"
+            log_recording(tgid, tgname, sitename, filename, length)
+    else:
+        if tgid == None or tgid == '':
+            print filename + " has no TGID"
+        else:
+            log_recording(tgid, tgname, sitename, filename, length)
+        if oldtgid == None or oldtgid == '':
+            print filename + " has no old TGID"
+        else:
+            log_recording(oldtgid, oldtgname, oldsitename, filename, length)
+    return
 
-    return
 
 def filenameMaker():
     global filename
     filename = date.today().isoformat()+'-'+str(time.time())+'-demo.wav'
 
-def record_to_async_file():
-    "Records from the microphone and outputs the resulting data to `path`"
+def do_record():
     sample_width, data = snd.record()
-    print str(len(data))
+    thr = threading.Thread(target=record_to_async_file, args=(sample_width,data,filename))
+    thr.start()
+
+
+def record_to_async_file(sample_width,data,filename):
+    "Records from the microphone and outputs the resulting data to `filename`"
+    print "Recording complete"
     if len(data) > MIN_LENGTH:
+        print "Recording being saved..."
+        dispatcher.send( signal='FILE_CREATED', sender=filename, filename=filename, length=len(data))
+        print str(len(data))
         data = snd.pack('<' + ('h'*len(data)), *data)
         path = "./data/"+filename
-        dispatcher.send( signal='FILE_CREATED', sender=filename, filename=filename, length=len(data))
         wf = wave.open(path, 'wb')
         wf.setnchannels(2)
         wf.setsampwidth(sample_width)
@@ -77,20 +119,23 @@
     del data
 
 dispatcher.connect( filenameMaker, signal='SND_STARTED', sender=dispatcher.Any )
-dispatcher.connect( worker, signal='FILE_CREATED', sender=dispatcher.Any )
+dispatcher.connect( tgid_worker, signal='SND_STARTED', sender=dispatcher.Any )
+dispatcher.connect( save_worker, signal='FILE_CREATED', sender=dispatcher.Any )
 
 print "Opening serial port..."
 if sys.platform.startswith('darwin'):
-	ser = serial.Serial('/dev/tty.usbserial-FTB3VL83', 112500, timeout=1) 
+	ser = serial.Serial('/dev/tty.usbserial-FTB3VL83', 112500, timeout=1)
 elif sys.platform.startswith('win32'):
-	ser = serial.Serial('COM20', 112500, timeout=1) 
+	ser = serial.Serial('COM20', 112500, timeout=1)
 print "Loading notifymyandroid..."
-nma = pynma.PyNMA( "a6f50f76119eda33befe4325b4b9e1dd25eef7bad2868e4f")    
+nma = pynma.PyNMA( "a6f50f76119eda33befe4325b4b9e1dd25eef7bad2868e4f")
 print "Connecting database..."
 conn = psycopg2.connect("dbname=scannr user=postgres password=snmc")
 print "Scannr started."
 while True:
     print "ready to record again"
-    record_to_async_file()
+    do_record()
 ser.close()
 
+
+

file:a/snd.py -> file:b/snd.py
--- a/snd.py
+++ b/snd.py
@@ -1,15 +1,12 @@
-""" Record a few seconds of audio and save to a WAVE file. 
+""" Record a few seconds of audio and save to a WAVE file.
 Based on http://stackoverflow.com/questions/892199/detect-record-audio-in-python/6743593#6743593
 """
 
 import pyaudio
 import wave
 import sys
-import audioop # http://docs.python.org/library/audioop
-from os.path import exists
 from array import array
 from struct import unpack, pack
-import threading
 from pydispatch import dispatcher
 
 THRESHOLD = 500
@@ -21,7 +18,7 @@
 elif sys.platform.startswith('win32'):
        CHANNELS = 1
 
-MAX_SILENT = 60
+MAX_SILENT = 80
 
 def is_silent(L):
     "Returns `True` if below the 'silent' threshold"
@@ -72,16 +69,16 @@
 
 def record():
     """
-    Record a word or words from the microphone and 
+    Record a word or words from the microphone and
     return the data as an array of signed shorts.
 
-    Normalizes the audio, trims silence from the 
-    start and end, and pads with 0.5 seconds of 
-    blank sound to make sure VLC et al can play 
+    Normalizes the audio, trims silence from the
+    start and end, and pads with 0.5 seconds of
+    blank sound to make sure VLC et al can play
     it without getting chopped off.
     """
     p = pyaudio.PyAudio()
-    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, 
+    stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE,
                     input=True,
                     frames_per_buffer=CHUNK_SIZE)
 
@@ -110,6 +107,8 @@
             dispatcher.send( signal='SND_STARTED')
             snd_started = True
             print snd_started
+        if snd_started and not silent:
+	    num_silent = 0
         if snd_started:
             LRtn.extend(L)
         if snd_started and num_silent > MAX_SILENT: