Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/audiograb.py
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2011-12-02 15:24:47 (GMT)
committer Walter Bender <walter.bender@gmail.com>2011-12-02 15:24:47 (GMT)
commit6bb37b3fd19a6d6a7e7671cd3b3406e41d43893a (patch)
tree43256f02164d30dbf0239afb5297d1db58c5e0c6 /audiograb.py
parentbb68a17ac0163ca673050f4754329e2f64a705e9 (diff)
more pipeline cleanups -- autodetection of channels
Diffstat (limited to 'audiograb.py')
-rw-r--r--audiograb.py147
1 files changed, 95 insertions, 52 deletions
diff --git a/audiograb.py b/audiograb.py
index 610a903..ef91631 100644
--- a/audiograb.py
+++ b/audiograb.py
@@ -24,6 +24,7 @@ import gst.interfaces
from numpy import fromstring
import os
import subprocess
+import traceback
from string import find
from threading import Timer
@@ -45,7 +46,7 @@ SENSOR_DC_NO_BIAS = 'voltage'
SENSOR_DC_BIAS = 'resistance'
-class AudioGrab:
+class AudioGrab():
""" The interface between measure and the audio device """
def __init__(self, callable1, activity):
@@ -63,7 +64,7 @@ class AudioGrab:
self.screenshot = True
self.rate = RATE
- self._channels = self.activity.wave.channels
+ self._channels = None
self.final_count = 0
self.count_temp = 0
self.entry_count = 0
@@ -81,9 +82,16 @@ class AudioGrab:
self._hardwired = False # Query controls or use hardwired names
self._display_value = DISPLAY_DUTY_CYCLE
- # Set up gstreamer pipeline
+ self._query_mixer()
+ if self._channels is None: # didn't find channels in any controllers
+ self._channels = 2
+ self.activity.wave.set_channels(self._channels)
+ # Set up gstreamer pipeline
self._pad_count = 0
+ self.pads = []
+ self.queue = []
+ self.fakesink = []
self.pipeline = gst.Pipeline('pipeline')
self.alsasrc = gst.element_factory_make('alsasrc', 'alsa-source')
self.pipeline.add(self.alsasrc)
@@ -92,34 +100,42 @@ class AudioGrab:
caps_str = 'audio/x-raw-int,rate=%d,channels=%d,depth=16' % (
RATE, self._channels)
self.caps1.set_property('caps', gst.caps_from_string(caps_str))
- self.queue = [None, None]
- self.fakesink = [None, None]
if self._channels == 1:
- self.fakesink[0] = gst.element_factory_make('fakesink', 'fsink')
+ self.fakesink.append(gst.element_factory_make('fakesink', 'fsink'))
self.pipeline.add(self.fakesink[0])
self.fakesink[0].connect('handoff', self.on_buffer)
self.fakesink[0].set_property('signal-handoffs', True)
gst.element_link_many(self.alsasrc, self.caps1, self.fakesink[0])
- else: # We only process 2 channels
- self.splitter = gst.element_factory_make('deinterleave',
- 'splitter')
- self.pipeline.add(self.splitter)
- self.splitter.set_properties('keep-positions=true', 'name=d')
- self.splitter.connect('pad-added', self._splitter_pad_added)
+ else:
+ if not hasattr(self, 'splitter'):
+ self.splitter = gst.element_factory_make('deinterleave')
+ self.pipeline.add(self.splitter)
+ self.splitter.set_properties('keep-positions=true', 'name=d')
+ self.splitter.connect('pad-added', self._splitter_pad_added)
+ gst.element_link_many(self.alsasrc, self.caps1, self.splitter)
for i in range(self._channels):
- self.queue[i] = gst.element_factory_make('queue',
- 'queue%d' % (i))
+ self.queue.append(gst.element_factory_make('queue'))
self.pipeline.add(self.queue[i])
- self.fakesink[i] = gst.element_factory_make('fakesink',
- 'fsink%d' % (i))
+ self.fakesink.append(gst.element_factory_make('fakesink'))
self.pipeline.add(self.fakesink[i])
self.fakesink[i].connect('handoff', self.on_buffer, i)
self.fakesink[i].set_property('signal-handoffs', True)
- gst.element_link_many(self.alsasrc, self.caps1, self.splitter)
-
self.dont_queue_the_buffer = False
+ # Variables for saving and resuming state of sound device
+ self.master = self.get_master()
+ self.bias = BIAS
+ self.dcmode = DC_MODE_ENABLE
+ self.capture_gain = CAPTURE_GAIN
+ self.mic_boost = MIC_BOOST
+ self.mic = self.get_mic_gain()
+
+ # Timer for interval sampling and switch to indicate when to capture
+ self.capture_timer = None
+ self.capture_interval_sample = False
+
+ def _query_mixer(self):
self._mixer = gst.element_factory_make('alsamixer')
rc = self._mixer.set_state(gst.STATE_PAUSED)
assert rc == gst.STATE_CHANGE_SUCCESS
@@ -128,6 +144,16 @@ class AudioGrab:
try: # F11+
log.debug('controls: %r', [t.props.untranslated_label \
for t in self._mixer.list_tracks()])
+ self._capture_control = self._find_control(['capture'])
+ if self._capture_control is not None:
+ log.debug('Capture is %s' % (
+ self._capture_control.props.untranslated_label))
+ log.debug('Min %s' % (str(self._capture_control.min_volume)))
+ log.debug('Max %s' % (str(self._capture_control.max_volume)))
+ log.debug('Channels %s' % (
+ str(self._capture_control.num_channels)))
+ if self._channels is None:
+ self._channels = self._capture_control.num_channels
self._dc_control = self._find_control(['dc mode'])
self._mic_bias_control = self._find_control(['mic bias',
'dc input bias',
@@ -139,6 +165,8 @@ class AudioGrab:
log.debug('Max %s' % (str(self._mic_bias_control.max_volume)))
log.debug('Channels %s' % (
str(self._mic_bias_control.num_channels)))
+ if self._channels is None:
+ self._channels = self._mic_bias_control.num_channels
self._mic_boost_control = self._find_control(['mic boost',
'mic boost (+20db)',
'internal mic boost',
@@ -150,49 +178,49 @@ class AudioGrab:
log.debug('Max %s' % (str(self._mic_boost_control.max_volume)))
log.debug('Channels %s' % (
str(self._mic_boost_control.num_channels)))
+ if self._channels is None:
+ self._channels = self._mic_boost_control.num_channels
self._mic_gain_control = self._find_control(['mic'])
- self._capture_control = self._find_control(['capture'])
- if self._capture_control is not None:
- log.debug('Capture is %s' % (
- self._capture_control.props.untranslated_label))
- log.debug('Min %s' % (str(self._capture_control.min_volume)))
- log.debug('Max %s' % (str(self._capture_control.max_volume)))
- log.debug('Channels %s' % (
- str(self._capture_control.num_channels)))
self._master_control = self._find_control(['master'])
except AttributeError: # F9- (no untranslated_label attribute)
self._hardwired = True
- # Variables for saving and resuming state of sound device
- self.master = self.get_master()
- self.bias = BIAS
- self.dcmode = DC_MODE_ENABLE
- self.capture_gain = CAPTURE_GAIN
- self.mic_boost = MIC_BOOST
- self.mic = self.get_mic_gain()
+ def _unlink_sink_queues(self):
+ ''' Build the sink pipelines '''
- # Timer for interval sampling and switch to indicate when to capture
- self.capture_timer = None
- self.capture_interval_sample = False
+ # If there were existing pipelines, unlink them
+ for i in range(self._pad_count):
+ log.debug('unlinking old elements')
+ try:
+ self.splitter.unlink(self.queue[i])
+ self.queue[i].unlink(self.fakesink[i])
+ except:
+ traceback.print_exc()
+
+ # Build the new pipelines
+ self._pad_count = 0
+ self.pads = []
+ log.debug('building new pipelines')
def _splitter_pad_added(self, element, pad):
''' Seems to be the case that ring is right channel 0,
tip is left channel 1'''
log.debug('splitter pad %d added' % (self._pad_count))
- if (self._pad_count < MAX_GRAPHS):
+ self.pads.append(pad)
+ if (self._pad_count < min(self._channels, MAX_GRAPHS)):
pad.link(self.queue[self._pad_count].get_pad('sink'))
self.queue[self._pad_count].get_pad('src').link(
self.fakesink[self._pad_count].get_pad('sink'))
self._pad_count += 1
else:
- log.debug('ignoring channels > %d' % (MAX_GRAPHS))
+ log.debug('ignoring channels > %d' % (min(self._channels,
+ MAX_GRAPHS)))
def set_handoff_signal(self, handoff_state):
'''Sets whether the handoff signal would generate an interrupt or not'''
- self.fakesink[0].set_property('signal-handoffs', handoff_state)
- if self._channels == 2:
- self.fakesink[1].set_property('signal-handoffs', handoff_state)
+ for i in range(len(self.fakesink)):
+ self.fakesink[i].set_property('signal-handoffs', handoff_state)
def _new_buffer(self, buf, channel):
''' Use a new buffer '''
@@ -205,14 +233,12 @@ class AudioGrab:
def on_buffer(self, element, buffer, pad, channel):
'''The function that is called whenever new data is available
This is the signal handler for the handoff signal'''
+ # log.debug('on_buffer: channel %d' % (channel))
temp_buffer = fromstring(buffer, 'int16')
if not self.dont_queue_the_buffer:
+ # log.debug('on_buffer: calling _new_buffer')
self._new_buffer(temp_buffer, channel=channel)
- # FIXME: manage multiple channels
- if channel > 0:
- return False
-
if self.logging_state:
# If we've hit the maximum no. of log files, stop.
if self.waveform_id == SOUND_MAX_WAVE_LOGS:
@@ -232,11 +258,13 @@ class AudioGrab:
# In sensor mode, periodly update the textbox with a sample value
if self.activity.CONTEXT == 'sensor' and not self.logging_state:
+ # log.debug('on_buffer: setting display value')
if self._display_value == 0: # Display value at DISPLAY_DUTY_CYCLE
self.sensor.set_sample_value(str(temp_buffer[0]))
self._display_value = DISPLAY_DUTY_CYCLE
else:
self._display_value -= 1
+ # log.debug('on_buffer: return False')
return False
def set_freeze_the_display(self, freeze=False):
@@ -343,6 +371,7 @@ class AudioGrab:
def start_grabbing(self):
'''Called right at the start of the Activity'''
self.start_sound_device()
+ self.set_handoff_signal(True)
def pause_grabbing(self):
'''When Activity goes into background'''
@@ -353,6 +382,7 @@ class AudioGrab:
'''When Activity becomes active after going to background'''
self.start_sound_device()
self.resume_state()
+ self.set_handoff_signal(True)
def stop_grabbing(self):
'''Not used ???'''
@@ -777,17 +807,31 @@ class AudioGrab:
}
mode, bias, gain, boost = PARAMETERS[sensor_type]
log.debug('====================================')
- log.debug('Set Sensor Type to %s' % (str(sensor_type)))
+ log.debug('Set sensor type to %s' % (str(sensor_type)))
self._set_sensor_type(mode, bias, gain, boost)
log.debug('====================================')
def _set_sensor_type(self, mode=None, bias=None, gain=None, boost=None):
'''Helper to modify (some) of the sensor settings.'''
- if mode is not None:
- self.set_dc_mode(mode)
- if self._dc_control is not None:
- os.system('amixer get "%s"' %\
- (self._dc_control.props.untranslated_label))
+
+ log.debug('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ log.debug('parameters: %s %s %s %s' % (str(mode), str(bias),
+ str(gain), str(boost)))
+ log.debug('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
+ log.debug('%s %s' % (str(mode), str(self.dcmode)))
+ if mode is not None and mode != self.dcmode:
+ # If we change to/from dcmode, we need to rebuild the pipelines
+ self.stop_grabbing()
+ self._unlink_sink_queues()
+
+ if mode is not None:
+ self.set_dc_mode(mode)
+ if self._dc_control is not None:
+ os.system('amixer get "%s"' %\
+ (self._dc_control.props.untranslated_label))
+ self.dcmode = mode
+ self.start_grabbing()
+
if bias is not None:
self.set_bias(bias)
if self._mic_bias_control is not None:
@@ -823,7 +867,6 @@ class AudioGrab_XO1(AudioGrab):
''' Use default parameters for OLPC XO 1.0 laptop '''
pass
-
class AudioGrab_XO15(AudioGrab):
''' Override parameters for OLPC XO 1.5 laptop '''
def set_sensor_type(self, sensor_type=SENSOR_AC_BIAS):