diff options
author | Walter Bender <walter@sugarlabs.org> | 2010-06-30 17:29:42 (GMT) |
---|---|---|
committer | Walter Bender <walter@sugarlabs.org> | 2010-06-30 17:29:42 (GMT) |
commit | 80d1f37f02c0713dc7dc401b02b15364c2276019 (patch) | |
tree | b0d59de9374f02c22e589fde31536188c8b8082c | |
parent | ee578a5eb9a728be6cce94b56f1a7ce0e25b87fd (diff) |
support for 0.86+ toolbars; general cleanup
-rw-r--r-- | audiograb.py | 277 | ||||
-rw-r--r-- | config.py | 20 | ||||
-rw-r--r-- | drawwaveform.py | 125 | ||||
-rw-r--r-- | measure.py | 173 | ||||
-rw-r--r-- | sensor_toolbar.py | 90 | ||||
-rw-r--r-- | sound_toolbar.py | 110 | ||||
-rw-r--r-- | toolbar_side.py | 54 |
7 files changed, 519 insertions, 330 deletions
diff --git a/audiograb.py b/audiograb.py index d6966f1..73ade5d 100644 --- a/audiograb.py +++ b/audiograb.py @@ -2,10 +2,11 @@ # # Author: Arjun Sarwal arjun@laptop.org # Copyright (C) 2007, Arjun Sarwal -# Copyright (C) 2009, Walter Bender +# Copyright (C) 2009,10 Walter Bender # Copyright (C) 2009, Benjamin Berg, Sebastian Berg # Copyright (C) 2009, Sayamindu Dasgupta -# +# Copyright (C) 2010, Sascha Silbe +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -24,12 +25,14 @@ import pygst pygst.require("0.10") import gst import gst.interfaces -import numpy as np +from numpy import fromstring import os import subprocess from string import find import time -import config +from config import RATE, BIAS, DC_MODE_ENABLE, CAPTURE_GAIN, MIC_BOOST,\ + SOUND_MAX_WAVE_LOGS, QUIT_MIC_BOOST, QUIT_DC_MODE_ENABLE,\ + QUIT_CAPTURE_GAIN, QUIT_BIAS from threading import Timer # Initialize logging. @@ -46,11 +49,12 @@ SENSOR_DC_BIAS = 'resistance' class AudioGrab: """ The interface between measure and the audio device """ - def __init__(self, callable1, journal): + def __init__(self, callable1, activity): """ Initialize the class: callable1 is a data buffer; journal is used for logging """ + self.callable1 = callable1 - self.ji = journal + self.activity = activity self.sensor = None self.temp_buffer = [0] @@ -61,7 +65,7 @@ class AudioGrab: # self.logging_status = False self.screenshot = True - self.rate = 48000 + self.rate = 48000 self.final_count = 0 self.count_temp = 0 self.entry_count = 0 @@ -72,6 +76,10 @@ class AudioGrab: self.counter_buffer = 0 + self._dc_control = None + self._mic_bias_control = None + self._capture_control = None + self._mic_boost_control = None self._hardwired = False # Query controls or use hardwired names # Set up gst pipeline @@ -81,11 +89,11 @@ class AudioGrab: self.caps1 = gst.element_factory_make("capsfilter", "caps1") self.pipeline.add(self.caps1) caps_str = "audio/x-raw-int,rate=%d,channels=1,depth=16" % \ - (config.RATE) + (RATE) self.caps1.set_property("caps", gst.caps_from_string(caps_str) ) self.fakesink = gst.element_factory_make("fakesink", "fsink") - self.pipeline.add(self.fakesink) - self.fakesink.connect("handoff", self.on_buffer) + self.pipeline.add(self.fakesink) + self.fakesink.connect("handoff", self.on_buffer) self.fakesink.set_property("signal-handoffs", True) gst.element_link_many(self.alsasrc, self.caps1, self.fakesink) @@ -104,21 +112,44 @@ class AudioGrab: self._mic_bias_control = self._find_control(['mic bias', 'dc input bias', 'v_refout']) + if self._mic_bias_control is not None: + log.debug("Mic Bias is %s" % ( + self._mic_bias_control.props.untranslated_label)) + log.debug("Min %s" % (str(self._mic_bias_control.min_volume))) + log.debug("Max %s" % (str(self._mic_bias_control.max_volume))) + log.debug("Channels %s" % ( + str(self._mic_bias_control.num_channels))) self._mic_boost_control = self._find_control(['mic boost', + 'mic boost (+20db)', 'internal mic boost', 'analog mic boost']) + if self._mic_boost_control is not None: + log.debug("Mic Boost is %s" % ( + self._mic_boost_control.props.untranslated_label)) + log.debug("Min %s" % (str(self._mic_boost_control.min_volume))) + log.debug("Max %s" % (str(self._mic_boost_control.max_volume))) + log.debug("Channels %s" % ( + str(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: # F9- (To do: what is the specific exception raised?) + 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 = config.BIAS - self.dcmode = config.DC_MODE_ENABLE - self.capture_gain = config.CAPTURE_GAIN - self.mic_boost = config.MIC_BOOST + 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 @@ -140,19 +171,19 @@ class AudioGrab: pass return - def on_buffer(self, element, buffer, pad): + def on_buffer(self, element, buffer, pad): """The function that is called whenever new data is available This is the signal handler for the handoff signal""" - temp_buffer = np.fromstring(buffer, 'int16') + temp_buffer = fromstring(buffer, 'int16') if not self.dont_queue_the_buffer: self._new_buffer(temp_buffer) else: pass if self.logging_state: - if self.waveform_id == config.SOUND_MAX_WAVE_LOGS: + if self.waveform_id == SOUND_MAX_WAVE_LOGS: self.waveform_id = 1 self.logging_state = False - self.ji.stop_session() + self.activity.ji.stop_session() else: if self.capture_interval_sample or\ self.buffer_interval_logging == 0: @@ -162,15 +193,13 @@ class AudioGrab: # for the logging session if self.buffer_interval_logging == 0: self.logging_state = False - self.ji.stop_session() + self.activity.ji.stop_session() self.waveform_id = 1 - if config.CONTEXT == 'sensor': - try: + if self.activity.CONTEXT == 'sensor': + if not self._hardwired: # don't display label on F9 self.sensor.set_sample_value(str(temp_buffer[0])) - except: - pass return False - + def set_freeze_the_display(self, freeze=False): """Useful when just the display is needed to be frozen, but logging should continue""" @@ -189,14 +218,14 @@ class AudioGrab: def _emit_for_logging(self, buf): """Sends the data for logging""" if self.buffer_interval_logging == 0: - self.ji.take_screenshot() + self.activity.ji.take_screenshot() else: if self.screenshot == True: - self.ji.take_screenshot(self.waveform_id) + self.activity.ji.take_screenshot(self.waveform_id) self.waveform_id+=1 else: # save value to Journal - self.ji.write_value(buf[0]) + self.activity.ji.write_value(buf[0]) # display value on Sensor toolbar try: self.sensor.set_sample_value(str(buf[0])) @@ -243,7 +272,8 @@ class AudioGrab: """ Create the next timer that will go off at the proper interval. This is used when the user has selected a sampling interval > 0 and the logging_state is True. """ - self.capture_timer = Timer(self.buffer_interval_logging, self.sample_now) + self.capture_timer = Timer(self.buffer_interval_logging, + self.sample_now) self.capture_timer.start() def take_picture(self): @@ -338,6 +368,8 @@ class AudioGrab: controls.sort(key=lambda e: e[1]) if controls: + log.debug("found control: %s" %\ + (str(controls[0][0].props.untranslated_label))) return controls[0][0] return None @@ -368,7 +400,7 @@ class AudioGrab: value = bool(control.flags & gst.interfaces.MIXER_TRACK_MUTE) log.debug('Getting %s (%s) mute status: %r', name, - control.props.untranslated_label, value) + control.props.untranslated_label, value) return value def _set_mute(self, control, name, value): @@ -379,7 +411,7 @@ class AudioGrab: self._mixer.set_mute(control, value) log.debug('Set mute for %s (%s) to %r', name, - control.props.untranslated_label, value) + control.props.untranslated_label, value) return def _get_volume(self, control, name): @@ -388,10 +420,12 @@ class AudioGrab: log.warning('No %s control, returning constant volume', name) return 100 - try: # sometimes control is not None and yet it is not a tuple? + try: # sometimes get_volume does not return a tuple hw_volume = self._mixer.get_volume(control)[0] except IndexError: - log.debug('ERROR getting control %s', control) + log.warning('_get_volume: %s (%d-%d) %d channels' % ( + control.props.untranslated_label, control.min_volume, + control.max_volume, control.num_channels)) return 100 min_vol = control.min_volume @@ -410,10 +444,15 @@ class AudioGrab: # convert value to scale of control min_vol = control.min_volume max_vol = control.max_volume - hw_volume = value*(max_vol - min_vol)//100 + min_vol - self._mixer.set_volume(control, (hw_volume,)*control.num_channels) - log.debug('Set volume of %s (%s) to %d (%d)', name, - control.props.untranslated_label, value, hw_volume) + if min_vol != max_vol: + hw_volume = value*(max_vol - min_vol)//100 + min_vol + self._mixer.set_volume(control, (hw_volume,)*control.num_channels) + log.debug('Set volume of %s (%s) to %d (%d)', name, + control.props.untranslated_label, value, hw_volume) + else: + log.warning('_set_volume: %s (%d-%d) %d channels' % ( + control.props.untranslated_label, control.min_volume, + control.max_volume, control.num_channels)) return def mute_master(self): @@ -456,41 +495,66 @@ class AudioGrab: return int(p) def set_bias(self, bias_state=False): - """Enables / disables bias voltage. On XO-1.5 it uses the 80% setting. - """ + """Enables / disables bias voltage.""" if not self._hardwired: - if not isinstance(self._mic_bias_control, - gst.interfaces.MixerOptions): + # if not isinstance(self._mic_bias_control, + # gst.interfaces.MixerOptions): + if self._mic_bias_control not in self._mixer.list_tracks(): + log.warning("set_bias: not in mixer") return self._set_mute(self._mic_bias_control, 'Mic Bias', not bias_state) - values = self._mic_bias_control.get_values() + #values = self._mic_bias_control.get_values() # We assume that values are sorted from lowest (=off) to highest. # Since they are mixed strings ("Off", "50%", etc.), we cannot # easily ensure this by sorting with the default sort order. - if bias_state: - self._mixer.set_option(self._mic_bias_control, values[-1]) - else: - self._mixer.set_option(self._mic_bias_control, values[0]) + log.debug("set bias max is %s" % (str( + self._mic_bias_control.max_volume))) + try: + if bias_state: + # self._mixer.set_option(self._mic_bias_control, values[-1]) + self._mixer.set_volume(self._mic_bias_control, + self._mic_bias_control.max_volume) + else: + self._mixer.set_volume(self._mic_bias_control, + self._mic_bias_control.min_volume) + # self._mixer.set_option(self._mic_bias_control, values[0]) + except TypeError: + log.warning('set_bias: %s (%d-%d) %d channels' % ( + self._mic_bias_control.props.untranslated_label, + self._mic_bias_control.min_volume, + self._mic_bias_control.max_volume, + self._mic_bias_control.num_channels)) + self._set_mute(self._mic_bias_control, 'Mic Bias', + not bias_state) else: - if bias_state==False: - bias_str="mute" + if bias_state: + bias_str="unmute" else: - bias_str="unmute" + bias_str="mute" os.system("amixer set 'V_REFOUT Enable' " + bias_str) return def get_bias(self): """Check whether bias voltage is enabled.""" if not self._hardwired: - if not isinstance(self._mic_bias_control, - gst.interfaces.MixerOptions): + if self._mic_bias_control not in self._mixer.list_tracks(): + # gst.interfaces.MixerOptions): + log.warning("get_bias: not in mixer") return not self._get_mute(self._mic_bias_control, 'Mic Bias', False) - values = self._mic_bias_control.get_values() - current = self._mixer.get_option(self._mic_bias_control) + #values = self._mic_bias_control.get_option() + #values = self._mic_bias_control.get_values() + log.warning('get_bias: %s (%d-%d) %d channels' % ( + self._mic_bias_control.props.untranslated_label, + self._mic_bias_control.min_volume, + self._mic_bias_control.max_volume, + self._mic_bias_control.num_channels)) + current = self._mixer.get_volume(self._mic_bias_control) # same ordering assertion as in set_bias() applies - if current == values[0]: + # if current == values[0]: + log.debug('current: %s' % (str(current))) + if current == self._mic_bias_control.min_volume: return False return True else: @@ -500,19 +564,19 @@ class AudioGrab: p = p[find(p,"[")+1:] p = p[:find(p,"]")] if p=="on": - return True + return True return False - def set_dc_mode(self, dc_mode = False): + def set_dc_mode(self, dc_mode=False): """Sets the DC Mode Enable control pass False to mute and True to unmute""" if not self._hardwired: self._set_mute(self._dc_control, 'DC mode', not dc_mode) else: - if dc_mode==False: - dcm_str="mute" + if dc_mode: + dcm_str="unmute" else: - dcm_str="unmute" + dcm_str="mute" os.system("amixer set 'DC Mode Enable' " + dcm_str) return @@ -528,33 +592,51 @@ class AudioGrab: p = p[find(p,"[")+1:] p = p[:find(p,"]")] if p=="on": - return True + return True else: - return False + return False def set_mic_boost(self, mic_boost=False): """Set Mic Boost. True = +20dB, False = 0dB""" if not self._hardwired: - if not isinstance(self._mic_boost_control, - gst.interfaces.MixerOptions): + if self._mic_boost_control not in self._mixer.list_tracks(): + # gst.interfaces.MixerOptions): + log.warning("set_mic_boost not in mixer %s" %\ + (str(self._mic_boost_control))) return self._set_mute(self._mic_boost_control, 'Mic Boost', mic_boost) - values = self._mic_boost_control.get_values() + #values = self._mic_boost_control.get_values() + value = self._mixer.get_volume(self._mic_boost_control) + """ if '20dB' not in values or '0dB' not in values: logging.error("Mic Boost (%s) is an option list, but doesn't " "contain 0dB and 20dB settings", self._mic_boost_control.props.label) return - if mic_boost: - self._mixer.set_option(self._mic_boost_control, '20dB') - else: - self._mixer.set_option(self._mic_boost_control, '0dB') + """ + try: + if mic_boost: + # self._mixer.set_option(self._mic_boost_control, '20dB') + self._mixer.set_volume(self._mic_boost_control, + self._mic_boost_control.max_volume) + else: + # self._mixer.set_option(self._mic_boost_control, '0dB') + self._mixer.set_volume(self._mic_boost_control, + self._mic_boost_control.min_volume) + except TypeError: + log.warning('set_mic_boost: %s (%d-%d) %d channels' % ( + self._mic_boost_control.props.untranslated_label, + self._mic_boost_control.min_volume, + self._mic_boost_control.max_volume, + self._mic_boost_control.num_channels)) + return self._set_mute(self._mic_boost_control, 'Mic Boost', + not mic_boost) else: - if mic_boost==False: - mb_str="mute" + if mic_boost: + mb_str="unmute" else: - mb_str="unmute" + mb_str="mute" os.system("amixer set 'Mic Boost (+20dB)' " + mb_str) return @@ -562,18 +644,29 @@ class AudioGrab: """Return Mic Boost setting. True = +20dB, False = 0dB""" if not self._hardwired: - if not isinstance(self._mic_boost_control, - gst.interfaces.MixerOptions): + if self._mic_boost_control not in self._mixer.list_tracks(): + logging.error("get_mic_boost not found in mixer %s" %\ + (str(self._mic_boost_control))) return self._get_mute(self._mic_boost_control, 'Mic Boost', False) - values = self._mic_boost_control.get_values() + #values = self._mic_boost_control.get_values() + # values = self._mixer.get_option(self._mic_boost_control) + """ if '20dB' not in values or '0dB' not in values: logging.error("Mic Boost (%s) is an option list, but doesn't " "contain 0dB and 20dB settings", self._mic_boost_control.props.label) return False - current = self._mixer.get_option(self._mic_boost_control) - if current == '20dB': + """ + log.warning('get_mic_boost: %s (%d-%d) %d channels' % ( + self._mic_boost_control.props.untranslated_label, + self._mic_boost_control.min_volume, + self._mic_boost_control.max_volume, + self._mic_boost_control.num_channels)) + current = self._mixer.get_volume(self._mic_boost_control) + log.debug('current: %s' % (str(current))) + # if current == '20dB': + if current != self._mic_boost_control.min_volume: return True return False else: @@ -583,9 +676,9 @@ class AudioGrab: p = p[find(p,"[")+1:] p = p[:find(p,"]")] if p=="on": - return True + return True else: - return False + return False def set_capture_gain(self, capture_val): """Sets the Capture gain slider settings @@ -652,7 +745,7 @@ class AudioGrab: SENSOR_AC_NO_BIAS: (False, False, 50, True), SENSOR_AC_BIAS: (False, True, 40, True), SENSOR_DC_NO_BIAS: (True, False, 0, False), - SENSOR_DC_BIAS: (True, True, 0, False), + SENSOR_DC_BIAS: (True, True, 0, False) } mode, bias, gain, boost = PARAMETERS[sensor_type] log.debug("====================================") @@ -665,20 +758,32 @@ class AudioGrab: """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)) if bias is not None: self.set_bias(bias) + if self._mic_bias_control is not None: + os.system("amixer get '%s'" %\ + (self._mic_bias_control.props.untranslated_label)) if gain is not None: self.set_capture_gain(gain) + if self._capture_control is not None: + os.system("amixer get '%s'" %\ + (self._capture_control.props.untranslated_label)) if boost is not None: self.set_mic_boost(boost) + if self._mic_boost_control is not None: + os.system("amixer get '%s'" %\ + (self._mic_boost_control.props.untranslated_label)) return def on_activity_quit(self): """When Activity quits""" - self.set_mic_boost(config.QUIT_MIC_BOOST) - self.set_dc_mode(config.QUIT_DC_MODE_ENABLE) - self.set_capture_gain(config.QUIT_CAPTURE_GAIN) - self.set_bias(config.QUIT_BIAS) + self.set_mic_boost(QUIT_MIC_BOOST) + self.set_dc_mode(QUIT_DC_MODE_ENABLE) + self.set_capture_gain(QUIT_CAPTURE_GAIN) + self.set_bias(QUIT_BIAS) self.stop_sound_device() return @@ -694,7 +799,7 @@ class AudioGrab_XO_1_5(AudioGrab): SENSOR_AC_NO_BIAS: (False, False, 80, True), SENSOR_AC_BIAS: (False, True, 80, True), SENSOR_DC_NO_BIAS: (True, False, 80, False), - SENSOR_DC_BIAS: (True, True, 80, False), + SENSOR_DC_BIAS: (True, True, 90, False) } log.debug("====================================") log.debug("Set Sensor Type to %s" % (str(sensor_type))) @@ -710,6 +815,8 @@ class AudioGrab_Unknown(AudioGrab): PARAMETERS = { SENSOR_AC_NO_BIAS: (None, False, 50, True), SENSOR_AC_BIAS: (None, True, 40, True), + SENSOR_DC_NO_BIAS: (True, False, 80, False), + SENSOR_DC_BIAS: (True, True, 90, False) } log.debug("====================================") log.debug("Set Sensor Type to %s" % (str(sensor_type))) @@ -21,18 +21,16 @@ Global configuration for Measure. """ -import os +from os import environ, path try: from sugar.activity import activity + MEASURE_ROOT = activity.get_bundle_path() SUGAR = True except ImportError: + MEASURE_ROOT = environ['HOME'] SUGAR = False -if SUGAR: - MEASURE_ROOT = activity.get_bundle_path() -else: - MEASURE_ROOT = os.environ['HOME'] -ICONS_DIR = os.path.join(MEASURE_ROOT, 'icons') +ICONS_DIR = path.join(MEASURE_ROOT, 'icons') #Multiplied with width and height to set placement of text TEXT_X_M = 0.65 @@ -58,14 +56,8 @@ QUIT_CAPTURE_GAIN = 100 QUIT_BIAS = True QUIT_PCM = 70 -#Toolbars +#Toolbars for 0.84- Sugar TOOLBARS = ['project','sound','sensor'] -#Which context is active on start -CONTEXT = 'sound' - -#How many maximum screenshots Measure will save while recording in Sound context +#Maximum no. of screenshots Measure will save while recording in Sound context SOUND_MAX_WAVE_LOGS = 10 - -#To track if one context is logging, other wouldn't also do it simultaneously -LOGGING_IN_SESSION = False diff --git a/drawwaveform.py b/drawwaveform.py index 9d85f50..a8f0197 100644 --- a/drawwaveform.py +++ b/drawwaveform.py @@ -26,19 +26,26 @@ import gobject import time import os import audioop -import math -import numpy as np +from math import floor, ceil +from numpy import array, where, float64, multiply, fft, arange, blackman from ringbuffer import RingBuffer1d from gtk import gdk try: import gconf + _using_gconf = True except ImportError: # older Sugar didn't use gconf from sugar import profile + _using_gconf = False from gettext import gettext as _ -import config +from config import MAX_GRAPHS, SUGAR +# Initialize logging. +import logging +log = logging.getLogger('Measure') +log.setLevel(logging.DEBUG) +logging.basicConfig() class DrawWaveform(gtk.DrawingArea): """ Handles all the drawing of waveforms """ @@ -49,15 +56,16 @@ class DrawWaveform(gtk.DrawingArea): TRIGGER_POS = 1 TRIGGER_NEG = 2 - def __init__(self, input_frequency=48000): + def __init__(self, activity, input_frequency=48000): """ Initialize drawing area and scope parameter """ gtk.DrawingArea.__init__(self) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | \ gtk.gdk.PROPERTY_CHANGE_MASK) + self.using_gconf = _using_gconf + self.activity = activity self._input_freq = input_frequency - self.stroke_color = None self.triggering = self.TRIGGER_NONE self.trigger_xpos = 0.0 self.trigger_ypos = 0.5 @@ -65,8 +73,8 @@ class DrawWaveform(gtk.DrawingArea): self.active = False self._redraw_atom = gtk.gdk.atom_intern('MeasureRedraw') - self.buffers = np.array([]) - self.main_buffers = np.array([]) + self.buffers = array([]) + self.main_buffers = array([]) self.str_buffer='' self.peaks = [] self.fftx = [] @@ -79,7 +87,7 @@ class DrawWaveform(gtk.DrawingArea): self.count = 0 self.invert = False - self.y_mag = 3.0 + self.y_mag = 3.0 # additional scale factor for display self.gain = 1.0 # (not in dB) introduced by Capture Gain and Mic Boost self.bias = 0 # vertical position fine-tuning from slider self._freq_range = 4 # See comment in sound_toolbar.py @@ -104,7 +112,6 @@ class DrawWaveform(gtk.DrawingArea): self._TRIGGER_LINE_THICKNESS = 3 self._FOREGROUND_LINE_THICKNESS = 6 - # self.logging_status = False self.f = None self.stop = False self.fft_show = False @@ -117,7 +124,7 @@ class DrawWaveform(gtk.DrawingArea): self.expose_event_id = self.connect("expose_event", self._expose) self.pr_time = 0 - self.MAX_GRAPHS = config.MAX_GRAPHS # Maximum simultaneous graphs + self.MAX_GRAPHS = MAX_GRAPHS # Maximum simultaneous graphs self.graph_show_state = [] self.Xstart = [] @@ -136,7 +143,7 @@ class DrawWaveform(gtk.DrawingArea): self.Xend.append(1000) self.Yend.append(500) self.type .append(0) - self.color.append([65535,0,0]) + self.color.append("#FF0000") self.source.append(0) self.graph_id.append(x) @@ -146,11 +153,7 @@ class DrawWaveform(gtk.DrawingArea): self.Xend[0] = 1150 self.Yend[0] = 750 self.type[0] = 0 - - if config.SUGAR: - self.color[0] = self.get_stroke_color_from_sugar() - else: - self.color[0] = '#ffffff' + self.color[0] = self.get_stroke_color_from_sugar() self.source[0] = 0 """ @@ -194,7 +197,6 @@ class DrawWaveform(gtk.DrawingArea): self.debug_str="start" self.context = True - def set_max_samples(self, num): """ Maximum no. of samples in ringbuffer """ @@ -263,31 +265,29 @@ class DrawWaveform(gtk.DrawingArea): return def do_realize(self): - """ Some initializations upon first 'realizing' the drawing area """ + """ Called when we are creating all of our window resources """ gtk.DrawingArea.do_realize(self) - # force a native X window to exist + + # Force a native X window to exist xid = self.window.xid colormap = self.get_colormap() self._line_gc = [] for graph_id in self.graph_id: - r, g, b = self.color[graph_id] - clr = colormap.alloc_color(r, g, b, False, False) + if len(self.color) > graph_id: + clr = colormap.alloc_color(self.color[graph_id]) - self._line_gc.append(self.window.new_gc(foreground=clr)) - self._line_gc[graph_id].set_line_attributes( - self._FOREGROUND_LINE_THICKNESS, gdk.LINE_SOLID, - gdk.CAP_ROUND, gdk.JOIN_BEVEL) + self._line_gc.append(self.window.new_gc(foreground=clr)) + self._line_gc[graph_id].set_line_attributes( + self._FOREGROUND_LINE_THICKNESS, gdk.LINE_SOLID, + gdk.CAP_ROUND, gdk.JOIN_BEVEL) - self._line_gc[graph_id].set_foreground(clr) + self._line_gc[graph_id].set_foreground(clr) - if config.SUGAR: - r, g, b = self.get_stroke_color_from_sugar() - else: - r = g = b = 255 - clr = colormap.alloc_color(r, g, b, False, False) + # Sugar stroke color + clr = colormap.alloc_color(self.color[0]) self._trigger_line_gc = self.window.new_gc(foreground=clr) self._trigger_line_gc.set_line_attributes( @@ -349,7 +349,7 @@ class DrawWaveform(gtk.DrawingArea): for graph_id in self.graph_id: if self.graph_show_state[graph_id] == True: buf = self.ringbuffer.read(None, self.input_step) - samples = math.ceil( + samples = ceil( self.allocation.width/self.draw_interval) if len(buf) == 0: # We don't have enough data to plot. @@ -377,7 +377,7 @@ class DrawWaveform(gtk.DrawingArea): ints &= buf[samples-samples_to_end+1:\ -samples_to_end-2] > ypos - ints = np.where(ints)[0] + ints = where(ints)[0] if len(ints) > 0: position = max(position, ints[-1]) @@ -387,7 +387,7 @@ class DrawWaveform(gtk.DrawingArea): ints &= buf[samples-samples_to_end+1:\ -samples_to_end-2] < ypos - ints = np.where(ints)[0] + ints = where(ints)[0] if len(ints) > 0: position = max(position, ints[-1]) @@ -404,9 +404,9 @@ class DrawWaveform(gtk.DrawingArea): data = buf[position-samples+samples_to_end:\ position+samples_to_end+2].astype( - np.float64) + float64) else: - data = buf[-samples:].astype(np.float64) + data = buf[-samples:].astype(float64) else: ###############FFT################ @@ -415,12 +415,12 @@ class DrawWaveform(gtk.DrawingArea): try: # Multiply input with the window - np.multiply(buf, self.fft_window, buf) + multiply(buf, self.fft_window, buf) # Should be fast enough even without pow(2) stuff. - self.fftx = np.fft.rfft(buf) + self.fftx = fft.rfft(buf) self.fftx = abs(self.fftx) - data = np.multiply(self.fftx, 0.02, self.fftx) + data = multiply(self.fftx, 0.02, self.fftx) ################################## except ValueError: # TODO: Figure out how this can happen. @@ -429,7 +429,7 @@ class DrawWaveform(gtk.DrawingArea): return True ################Scaling the values################### - if config.CONTEXT == 'sensor': + if self.activity.CONTEXT == 'sensor': self.y_mag = 1.0 if self.invert: @@ -447,7 +447,7 @@ class DrawWaveform(gtk.DrawingArea): ##########The actual drawing of the graph################## - lines = (np.arange(len(data), dtype='float32') *\ + lines = (arange(len(data), dtype='float32') *\ self.draw_interval) + x_offset # Use ints or draw_lines will throw warnings @@ -524,15 +524,15 @@ class DrawWaveform(gtk.DrawingArea): if self.fft_show: max_freq = (self.freq_div*self.get_ticks()) wanted_step = 1.0/max_freq/2*self._input_freq - self.input_step = max(math.floor(wanted_step), 1) + self.input_step = max(floor(wanted_step), 1) self.draw_interval = 5.0 - self.set_max_samples(math.ceil(self.allocation.width/float( + self.set_max_samples(ceil(self.allocation.width/float( self.draw_interval)*2)*self.input_step) # Create the (blackman) window - self.fft_window = np.blackman(math.ceil(self.allocation.width/float( + self.fft_window = blackman(ceil(self.allocation.width/float( self.draw_interval)*2)) self.draw_interval *= wanted_step/self.input_step @@ -544,8 +544,7 @@ class DrawWaveform(gtk.DrawingArea): samples = time * self._input_freq self.set_max_samples(samples * self.max_samples_fact) - self.input_step = max(math.ceil(samples/( - self.allocation.width/3.0)),1) + self.input_step = max(ceil(samples/(self.allocation.width/3.0)),1) self.draw_interval = self.allocation.width/( float(samples)/self.input_step) @@ -560,29 +559,17 @@ class DrawWaveform(gtk.DrawingArea): def get_stroke_color_from_sugar(self): """Returns in (r,g,b) format the stroke color from the Sugar profile""" - # Hitting gconf is a large overhead. - if self.stroke_color is None: - try: - client = gconf.client_get_default() - color = client.get_string("/desktop/sugar/user/color") - except: - color = profile.get_color().to_string() - - if color == None: - return(255, 255, 255) - - stroke,fill = color.split(",") - colorstring = stroke.strip() - if colorstring[0] == '#': - colorstring = colorstring[1:] - r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:] - r += r - g += g - b += b - r, g, b = [int(n, 16) for n in (r, g, b)] - self.stroke_color = (r, g, b) - - return self.stroke_color + if self.using_gconf: + client = gconf.client_get_default() + color = client.get_string("/desktop/sugar/user/color") + else: + color = profile.get_color().to_string() + + if color == None: + return("#ffffff") + + stroke, fill = color.split(",") + return stroke.strip() def get_mag_params(self): return self.gain, self.y_mag @@ -25,23 +25,37 @@ pygst.require("0.10") import pygtk import gtk import gobject -import time import dbus -import config #This has all the globals -import os -import tempfile -from os import environ -from os.path import join +from time import sleep +from config import TOOLBARS, ICONS_DIR +from tempfile import mkstemp +from os import environ, path, chmod +from textbox import TextBox +from gettext import gettext as _ + +from sugar.activity import activity +try: # 0.86+ toolbar widgets + from sugar.bundle.activitybundle import ActivityBundle + from sugar.activity.widgets import ActivityToolbarButton + from sugar.activity.widgets import StopButton + from sugar.graphics.toolbarbox import ToolbarBox + from sugar.graphics.toolbarbox import ToolbarButton + _new_sugar_system = True +except ImportError: + from sugar.activity.activity import ActivityToolbox + _new_sugar_system = False +from sugar.datastore import datastore from journal import JournalInteraction -import audiograb +from audiograb import AudioGrab_XO_1_5, AudioGrab_XO_1, AudioGrab_Unknown from drawwaveform import DrawWaveform from toolbar_side import SideToolbar -from toolbar_top import Toolbar -from textbox import TextBox +from sound_toolbar import SoundToolbar +from sensor_toolbar import SensorToolbar -from sugar.activity import activity -from sugar.datastore import datastore +def _is_xo(hw): + """ Return True if this is xo hardware """ + return hw in ['xo1','xo1.5'] # Initialize logging. import logging @@ -65,14 +79,15 @@ def _get_hardware(): return 'xo1' else: return 'unknown' - elif os.path.exists('/etc/olpc-release') or \ - os.path.exists('/sys/power/olpc-pm'): + elif path.exists('/etc/olpc-release') or \ + path.exists('/sys/power/olpc-pm'): return 'xo1' # elif 'olpc' in dev.GetProperty('system.kernel.version'): # return 'xo1' else: return 'unknown' + class MeasureActivity(activity.Activity): """ Oscilloscope Sugar activity """ @@ -86,15 +101,17 @@ class MeasureActivity(activity.Activity): activity.Activity.__init__(self, handle) try: - tmp_dir = os.path.join(activity.get_activity_root(), "data") + tmp_dir = path.join(activity.get_activity_root(), "data") except: # Early versions of Sugar (e.g., 656) didn't support # get_activity_root() - tmp_dir = os.path.join(os.environ['HOME'], + tmp_dir = path.join(environ['HOME'], ".sugar/default/org.laptop.MeasureActivity/data") self.active_status = True self.ACTIVE = True + self.LOGGING_IN_SESSION = False + self.CONTEXT = '' self.connect("notify::active", self._active_cb) self.connect("destroy", self.on_quit) @@ -103,25 +120,23 @@ class MeasureActivity(activity.Activity): self.existing = True else: #logging.debug('1.1 Launched from frame or from Mesh View') - self._jobject.file_path = str(tempfile.mkstemp(dir=tmp_dir)[1]) - os.chmod(self._jobject.file_path, 0777) + self._jobject.file_path = str(mkstemp(dir=tmp_dir)[1]) + chmod(self._jobject.file_path, 0777) self.existing = False self.ji = JournalInteraction(self._jobject.file_path, self.existing) - self.wave = DrawWaveform() + self.wave = DrawWaveform(self) self.hw = _get_hardware() print "running on %s hardware" % (self.hw) if self.hw == 'xo1.5': - self.audiograb = \ - audiograb.AudioGrab_XO_1_5(self.wave.new_buffer, self.ji) + self.audiograb = AudioGrab_XO_1_5(self.wave.new_buffer, self) elif self.hw == 'xo1': - self.audiograb = \ - audiograb.AudioGrab_XO_1(self.wave.new_buffer, self.ji) - else: # Use 1.5 settings as default, 0) - self.audiograb = \ - audiograb.AudioGrab_Unknown(self.wave.new_buffer, self.ji) - # log.error('Sorry, we do not support your hardware yet.') + self.audiograb = AudioGrab_XO_1(self.wave.new_buffer, self) + else: + self.audiograb = AudioGrab_Unknown(self.wave.new_buffer, self) + + self.new_sugar_system = _new_sugar_system self.side_toolbar = SideToolbar(self) self.text_box = TextBox() @@ -136,15 +151,76 @@ class MeasureActivity(activity.Activity): self.set_canvas(self.box1) - toolbox = Toolbar(self) - self.set_toolbox(toolbox) + if self.new_sugar_system: + # Use 0.86 toolbar design + toolbox = ToolbarBox() + + activity_button = ActivityToolbarButton(self) + toolbox.toolbar.insert(activity_button, 0) + activity_button.show() + else: + toolbox = ActivityToolbox(self) + self.set_toolbox(toolbox) + toolbox.connect("current-toolbar-changed", self._toolbar_changed_cb) + + self.sound_toolbar = SoundToolbar(self) + if self.new_sugar_system: + self._sound_button = ToolbarButton( + page=self.sound_toolbar, + icon_name='sound-tools') + toolbox.toolbar.insert(self._sound_button, -1) + self._sound_button.show() + else: + toolbox.add_toolbar(_('Sound'), self.sound_toolbar) + self.sound_toolbar.show() + + if _is_xo(self.hw): + self.sensor_toolbar = SensorToolbar(self) + if self.new_sugar_system: + self._sensor_button = ToolbarButton( + page=self.sensor_toolbar, + icon_name='sensor-tools') + toolbox.toolbar.insert(self._sensor_button, -1) + self._sensor_button.show() + else: + toolbox.add_toolbar(_('Sensors'), self.sensor_toolbar) + self.sensor_toolbar.show() + + if self.new_sugar_system: + _separator = gtk.SeparatorToolItem() + _separator.props.draw = True + _separator.set_expand(False) + toolbox.toolbar.insert(_separator, -1) + _separator.show() + self.mode_image = gtk.Image() + self.mode_image.set_from_file(ICONS_DIR + '/domain-time2.svg') + mode_image_tool = gtk.ToolItem() + mode_image_tool.add(self.mode_image) + toolbox.toolbar.insert(mode_image_tool,-1) + _separator = gtk.SeparatorToolItem() + _separator.props.draw = False + _separator.set_expand(True) + toolbox.toolbar.insert(_separator, -1) + _separator.show() + _stop_button = StopButton(self) + _stop_button.props.accelerator = _('<Ctrl>Q') + toolbox.toolbar.insert(_stop_button, -1) + _stop_button.show() + + self.set_toolbox(toolbox) + + if not self.new_sugar_system: + toolbox.set_current_toolbar(TOOLBARS.index('sound')) + else: + self._sound_button.set_expanded(True) + toolbox.show() self.show_all() self.first = True - self.set_show_hide_windows() + self.set_show_hide_windows('sound') self.wave.set_active(True) self.wave.set_context_on() @@ -153,10 +229,18 @@ class MeasureActivity(activity.Activity): if mode == 'sound': self.wave.set_context_on() self.side_toolbar.set_show_hide(True, mode) + if not self.new_sugar_system: + toolbox.set_current_toolbar(TOOLBARS.index('sound')) + else: + self._sound_button.set_expanded(True) return elif mode == 'sensor': self.wave.set_context_on() self.side_toolbar.set_show_hide(True, mode) + if not self.new_sugar_system: + toolbox.set_current_toolbar(TOOLBARS.index('sensor')) + else: + self._sensor_button.set_expanded(True) return def on_quit(self,data=None): @@ -167,13 +251,13 @@ class MeasureActivity(activity.Activity): def _active_cb( self, widget, pspec ): """ Callback to handle starting/pausing capture when active/idle """ - if(self.first == True): + if self.first: self.audiograb.start_grabbing() self.first = False - if (not self.props.active and self.ACTIVE): + if not self.props.active and self.ACTIVE: self.audiograb.pause_grabbing() self.active_status = False - elif (self.props.active and not self.ACTIVE): + elif self.props.active and not self.ACTIVE: self.audiograb.resume_grabbing() self.active_status = True @@ -189,4 +273,29 @@ class MeasureActivity(activity.Activity): """ Read data from journal on start """ return + def _toolbar_changed_cb(self, toolbox, num): + """ Callback for changing the primary toolbar (0.84-) """ + if TOOLBARS[num] == 'sound': + self.set_sound_context() + elif TOOLBARS[num] == 'sensor': + self.set_sensor_context() + return True + + def set_sound_context(self): + """ Called when sound toolbar is selected or button pushed """ + self.set_show_hide_windows('sound') + if _is_xo(self.hw): + self.sensor_toolbar.context_off() + sleep(0.5) + self.sound_toolbar.context_on() + self.CONTEXT = 'sound' + + def set_sensor_context(self): + """ Called when sensor toolbar is selected or button pushed """ + self.set_show_hide_windows('sensor') + self.sound_toolbar.context_off() + sleep(0.5) + self.sensor_toolbar.context_on() + self.CONTEXT = 'sensor' + gtk.gdk.threads_init() diff --git a/sensor_toolbar.py b/sensor_toolbar.py index 63499be..0fc873c 100644 --- a/sensor_toolbar.py +++ b/sensor_toolbar.py @@ -3,7 +3,7 @@ # # Author: Arjun Sarwal arjun@laptop.org # Copyright (C) 2007, Arjun Sarwal -# Copyright (C) 2009, Walter Bender +# Copyright (C) 2009,10 Walter Bender # Copyright (C) 2009, Benjamin Berg, Sebastian Berg # # This program is free software; you can redistribute it and/or modify @@ -22,10 +22,10 @@ import pygtk import gtk -import time +from time import sleep from gettext import gettext as _ -import config +from config import ICONS_DIR from sugar.graphics.toolbutton import ToolButton from sugar.graphics.combobox import ComboBox @@ -35,7 +35,7 @@ log = logging.getLogger('Measure') log.setLevel(logging.DEBUG) try: import gconf -except: +except ImportError: from sugar import profile @@ -59,20 +59,16 @@ class SensorToolbar(gtk.Toolbar): self.gain_state = None self.boost_state = None - # self.b = 0 - self.string_for_textbox = "" - self.wave = activity.wave - self.ag = activity.audiograb - self.ag.set_sensor(self) - self.textbox_copy = activity.text_box - self.ji = activity.ji + self.activity = activity + self.activity.audiograb.set_sensor(self) - # self.logging_status = False - # Set up Resistance Button - self._resistance = ToolButton('bias-on2') + if self.activity.new_sugar_system: + self._resistance = ToolButton('bias-on') + else: + self._resistance = ToolButton('bias-on2') self.insert(self._resistance, -1) self._resistance.show() self._resistance.set_tooltip(_('Resistance Sensor')) @@ -91,7 +87,7 @@ class SensorToolbar(gtk.Toolbar): self.insert(self._invert, -1) self._invert.set_tooltip(_('Invert')) self._invert.connect('clicked', self._invert_control_cb) - self.wave.set_invert_state(False) + self.activity.wave.set_invert_state(False) separator = gtk.SeparatorToolItem() separator.props.draw = True @@ -99,7 +95,7 @@ class SensorToolbar(gtk.Toolbar): # Set up Logging Interval combo box self.loginterval_img = gtk.Image() - self.loginterval_img.set_from_file(config.ICONS_DIR+'/sample_rate.svg') + self.loginterval_img.set_from_file(ICONS_DIR+'/sample_rate.svg') self.loginterval_img_tool = gtk.ToolItem() self.loginterval_img_tool.add(self.loginterval_img) self.insert(self.loginterval_img_tool,-1) @@ -141,18 +137,15 @@ class SensorToolbar(gtk.Toolbar): def set_sample_value(self, label=""): """ Write a sample value to the toolbar label """ - self.sample_value.set_text(label) + self.sample_value.set_text(str(label)) self.sample_value.show() def record_control(self, data=None): """Depending upon the selected interval, does either a logging session, or just logs the current buffer""" - # config.LOGGING_IN_SESSION appears to be a duplicate of - # self.logging_status. - # - if config.LOGGING_IN_SESSION == False: - Xscale = (1.00/self.ag.get_sampling_rate()) + if self.activity.LOGGING_IN_SESSION == False: + Xscale = (1.00/self.activity.audiograb.get_sampling_rate()) Yscale = 0.0 interval = self.interval_convert() try: @@ -160,21 +153,18 @@ class SensorToolbar(gtk.Toolbar): username = client.get_string("/desktop/suagr/user/nick") except: username = profile.get_nick_name() - self.ji.start_new_session(username, Xscale, Yscale, + self.activity.ji.start_new_session(username, Xscale, Yscale, self.logginginterval_status) - self.ag.set_logging_params(True, interval, False) - config.LOGGING_IN_SESSION = True - # self.logging_status = True + self.activity.audiograb.set_logging_params(True, interval, False) + self.activity.LOGGING_IN_SESSION = True self._record.set_icon('record-stop') self._record.show() self._record.set_tooltip(_('Stop Recording')) else: - # if self.logging_status == True: - self.ag.set_logging_params(False) - time.sleep(0.2) - self.ji.stop_session() - config.LOGGING_IN_SESSION = False - # self.logging_status = False + self.activity.audiograb.set_logging_params(False) + sleep(0.2) + self.activity.ji.stop_session() + self.activity.LOGGING_IN_SESSION = False self._record.set_icon('media-record') self._record.show() self._record.set_tooltip(_('Start Recording')) @@ -203,6 +193,11 @@ class SensorToolbar(gtk.Toolbar): def set_resistance_voltage_mode(self, data=None, mode_to_set='resistance'): """ Callback for Resistance/Voltage Buttons """ + + # Make sure the current context is for sensor capture. + if self.activity.CONTEXT != 'sensor': + self.activity.set_sensor_context() + self.set_mode(mode_to_set) if mode_to_set == 'resistance': self._resistance.set_icon('bias-on2') @@ -210,26 +205,31 @@ class SensorToolbar(gtk.Toolbar): self._resistance.show() self._voltage.show() self._update_string_for_textbox() - return False + self.activity.mode_image.set_from_file(ICONS_DIR +\ + '/bias-on2.svg') elif mode_to_set == 'voltage': self._resistance.set_icon('bias-on') self._voltage.set_icon('bias-off2') self._resistance.show() self._voltage.show() self._update_string_for_textbox() - return False + self.activity.mode_image.set_from_file(ICONS_DIR +\ + '/bias-off2.svg') else: logging.error("unknown mode %s" % (mode_to_set)) - return False + if self.activity.new_sugar_system: + self.activity.sound_toolbar._time.set_icon('domain-time') + self.activity.sound_toolbar._freq.set_icon('domain-freq') + return False def _invert_control_cb(self, data=None): """ Callback for Invert Button """ - if self.wave.get_invert_state()==True: - self.wave.set_invert_state(False) + if self.activity.wave.get_invert_state()==True: + self.activity.wave.set_invert_state(False) self._invert.set_icon('invert') self._invert.show() else: - self.wave.set_invert_state(True) + self.activity.wave.set_invert_state(True) self._invert.set_icon('invert2') self._invert.show() self._update_string_for_textbox() @@ -238,19 +238,19 @@ class SensorToolbar(gtk.Toolbar): def set_mode(self, mode='resistance'): """ Set the mixer settings to match the current mode. """ self.mode = mode - self.ag.set_sensor_type(self.mode) + self.activity.audiograb.set_sensor_type(self.mode) return def context_off(self): """ Called when sensor toolbar is no longer selected. """ - self.ag.pause_grabbing() + self.activity.audiograb.pause_grabbing() def context_on(self): """ Called when sensor toolbar is selected. """ - self.ag.resume_grabbing() - self.ag.set_sensor_type(self.mode) + self.activity.audiograb.resume_grabbing() + self.activity.audiograb.set_sensor_type(self.mode) self._update_string_for_textbox() - self.wave.set_trigger(self.wave.TRIGGER_NONE) + self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE) def _update_string_for_textbox(self): """ Update the status field at the bottom of the canvas. """ @@ -260,6 +260,6 @@ class SensorToolbar(gtk.Toolbar): self.string_for_textbox += self._STR_R else: self.string_for_textbox += self._STR_V - if self.wave.get_invert_state()==True: + if self.activity.wave.get_invert_state()==True: self.string_for_textbox += self._STR_I - self.textbox_copy.set_data_params(0, self.string_for_textbox) + self.activity.text_box.set_data_params(0, self.string_for_textbox) diff --git a/sound_toolbar.py b/sound_toolbar.py index 11c165e..da65f5b 100644 --- a/sound_toolbar.py +++ b/sound_toolbar.py @@ -22,10 +22,9 @@ import pygtk import gtk import gobject -from time import * from gettext import gettext as _ -import config #This has all the globals +from config import ICONS_DIR, CAPTURE_GAIN, MIC_BOOST # Initialize logging. import logging @@ -38,7 +37,7 @@ from sugar.graphics.combobox import ComboBox from sugar.graphics.toolcombobox import ToolComboBox try: import gconf -except: +except ImportError: from sugar import profile # Initialize logging. @@ -64,10 +63,7 @@ class SoundToolbar(gtk.Toolbar): """ Initialize the toolbar controls. """ gtk.Toolbar.__init__(self) - self.wave = activity.wave - self.ag = activity.audiograb - self.textbox_copy = activity.text_box - self.ji = activity.ji + self.activity = activity self._STR_BASIC = _("Sound") + " " self._STR1 = _("Time Base") + " " @@ -87,8 +83,8 @@ class SoundToolbar(gtk.Toolbar): self.gain = 1.0 self.y_mag = 3.0 - self.capture_gain = config.CAPTURE_GAIN - self.mic_boost = config.MIC_BOOST + self.capture_gain = CAPTURE_GAIN + self.mic_boost = MIC_BOOST # self.logging_status = False self._record = None @@ -115,7 +111,8 @@ class SoundToolbar(gtk.Toolbar): self._freq_stepper_up.set_tooltip(_('Zoom out')) self._freq_stepper_up.connect('clicked', self._freq_stepper_up_cb) - self.adjustmentf = gtk.Adjustment(.5, self.LOWER, self.UPPER, 0.01, 0.1, 0) + self.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER, 0.01, + 0.1, 0) self.adjustmentf.connect("value_changed", self.cb_page_sizef) self._freq_range = gtk.HScale(self.adjustmentf) self._freq_range.set_inverted(True) @@ -150,7 +147,7 @@ class SoundToolbar(gtk.Toolbar): separator.show() self.loginterval_img = gtk.Image() - self.loginterval_img.set_from_file(config.ICONS_DIR+'sample_rate.svg') + self.loginterval_img.set_from_file(ICONS_DIR+'sample_rate.svg') self.loginterval_img_tool = gtk.ToolItem() self.loginterval_img_tool.add(self.loginterval_img) self.insert(self.loginterval_img_tool,-1) @@ -193,8 +190,9 @@ class SoundToolbar(gtk.Toolbar): # Set up Trigger Combo box self._trigger_combo = ComboBox() self.trigger = [_('None'), _('Rising Edge') , _('Falling Edge') ] - self.trigger_conf = [self.wave.TRIGGER_NONE, self.wave.TRIGGER_POS, - self.wave.TRIGGER_NEG] + self.trigger_conf = [self.activity.wave.TRIGGER_NONE, + self.activity.wave.TRIGGER_POS, + self.activity.wave.TRIGGER_NEG] self._trigger_changed_id = self._trigger_combo.connect("changed", self.update_trigger_control) @@ -213,8 +211,8 @@ class SoundToolbar(gtk.Toolbar): def record_control(self, data=None): """Depending upon the selected interval, either starts/stops a logging session, or just logs the current buffer""" - if config.LOGGING_IN_SESSION == False: - Xscale = (1.00/self.ag.get_sampling_rate()) + if self.activity.LOGGING_IN_SESSION == False: + Xscale = (1.00/self.activity.audiograb.get_sampling_rate()) Yscale = 0.0 interval = self.interval_convert() try: @@ -222,10 +220,10 @@ class SoundToolbar(gtk.Toolbar): username = client.get_string("/desktop/suagr/user/nick") except: username = profile.get_nick_name() - self.ji.start_new_session(username, Xscale, Yscale, + self.activity.ji.start_new_session(username, Xscale, Yscale, self.logginginterval_status) - self.ag.set_logging_params(True, interval, True) - config.LOGGING_IN_SESSION = True + self.activity.audiograb.set_logging_params(True, interval, True) + self.activity.LOGGING_IN_SESSION = True # self.logging_status = True self._record.set_icon('record-stop') self._record.show() @@ -233,12 +231,12 @@ class SoundToolbar(gtk.Toolbar): self._record.set_icon('media-record') self._record.show() self.record_state = False - config.LOGGING_IN_SESSION = False + self.activity.LOGGING_IN_SESSION = False self.logging_status = False else: # if self.logging_status == True: - self.ag.set_logging_params(False) - config.LOGGING_IN_SESSION = False + self.activity.audiograb.set_logging_params(False) + self.activity.LOGGING_IN_SESSION = False # self.logging_status = False self._record.set_icon('media-record') self._record.show() @@ -253,7 +251,7 @@ class SoundToolbar(gtk.Toolbar): if self.logginginterval_status == 'picture': return 0 elif self.logginginterval_status == '30second': - return 30 #2667 + return 30 #2667 elif self.logginginterval_status == '2minute': return 120 #10668 elif self.logginginterval_status == '10minute': @@ -286,7 +284,7 @@ class SoundToolbar(gtk.Toolbar): the sampling interval > 0. """ if self._record == None: return - if config.LOGGING_IN_SESSION == True: + if self.activity.LOGGING_IN_SESSION == True: self._record.set_tooltip(_('Stop sampling')) else: # No sampling in progress if (self._loginterval_combo.get_active() == 0): @@ -301,18 +299,18 @@ class SoundToolbar(gtk.Toolbar): if active == -1: return - self.wave.set_trigger(self.trigger_conf[active]) + self.activity.wave.set_trigger(self.trigger_conf[active]) return def _pauseplay_control_cb(self, data=None): """ Callback for Pause Button """ - if self.ag.get_freeze_the_display()==True: - self.ag.set_freeze_the_display(False) + if self.activity.audiograb.get_freeze_the_display()==True: + self.activity.audiograb.set_freeze_the_display(False) self._pause.set_icon('media-playback-pause-insensitive') self._pause.set_tooltip(_('Unfreeze the display')) self._pause.show() else: - self.ag.set_freeze_the_display(True) + self.activity.audiograb.set_freeze_the_display(True) self._pause.set_icon('media-playback-pause') self._pause.set_tooltip(_('Freeze the display')) self._pause.show() @@ -320,21 +318,32 @@ class SoundToolbar(gtk.Toolbar): def _timefreq_control_cb(self, data=None, time_state=True): """ Callback for Time and Freq. Buttons """ - if time_state==True and self.wave.get_fft_mode()==True: - self.wave.set_fft_mode(False) + + # Make sure the current context is for sound capture. + if self.activity.CONTEXT != 'sound': + self.activity.set_sound_context() + + if time_state==True: + self.activity.wave.set_fft_mode(False) self._time.set_icon('domain-time2') self._freq.set_icon('domain-freq') self._time.show() self._freq.show() self._update_string_for_textbox() - return False - if time_state==False and self.wave.get_fft_mode()==False: - self.wave.set_fft_mode(True) + self.activity.mode_image.set_from_file(ICONS_DIR +\ + '/domain-time2.svg') + else: + self.activity.wave.set_fft_mode(True) self._time.set_icon('domain-time') self._freq.set_icon('domain-freq2') self._time.show() self._freq.show() self._update_string_for_textbox() + self.activity.mode_image.set_from_file(ICONS_DIR +\ + '/domain-freq2.svg') + if self.activity.new_sugar_system: + self.activity.sensor_toolbar._resistance.set_icon('bias-on') + self.activity.sensor_toolbar._voltage.set_icon('bias-off') return False def _freq_stepper_up_cb(self, data=None): @@ -380,7 +389,7 @@ class SoundToolbar(gtk.Toolbar): time_div = 0.001*max(self.adjustmentf.value, 0.05) freq_div = 1000*max(self.adjustmentf.value, 0.01) - self.wave.set_div(time_div, freq_div) + self.activity.wave.set_div(time_div, freq_div) self._update_string_for_textbox() @@ -389,42 +398,39 @@ class SoundToolbar(gtk.Toolbar): def context_off(self): """When some other context is switched to and the sound context is switched off""" - self.gain, self.y_mag = self.wave.get_mag_params() - self.capture_gain = self.ag.get_capture_gain() - self.mic_boost = self.ag.get_mic_boost() - self.ag.stop_sound_device() - self.wave.set_fft_mode(False) + self.gain, self.y_mag = self.activity.wave.get_mag_params() + self.capture_gain = self.activity.audiograb.get_capture_gain() + self.mic_boost = self.activity.audiograb.get_mic_boost() + self.activity.audiograb.stop_sound_device() + self.activity.wave.set_fft_mode(False) def context_on(self): """When the sound context is switched on""" - self.ag.start_sound_device() - #self.ag.set_dc_mode(False) - #self.ag.set_bias(True) - #self.ag.set_capture_gain(self.capture_gain) - #self.ag.set_mic_boost(self.mic_boost) - self.ag.set_sensor_type("sound") - self.wave.set_fft_mode(False) - self.wave.set_mag_params(self.gain, self.y_mag) + self.activity.audiograb.start_sound_device() + self.activity.audiograb.set_sensor_type("sound") + self.activity.wave.set_fft_mode(False) + self.activity.wave.set_mag_params(self.gain, self.y_mag) self._update_string_for_textbox() self.update_trigger_control() def _update_string_for_textbox(self): """ Update the text at the bottom of the canvas """ - if self.wave.get_fft_mode() == False: + if self.activity.wave.get_fft_mode() == False: self._STR_SCALEX = self._STR_XAXIS_TEXT % \ - {'unit': self._ms, 'division': self.wave.time_div*1000} + {'unit': self._ms, + 'division': self.activity.wave.time_div*1000} else: self._STR_SCALEX = self._STR_XAXIS_TEXT % \ - {'unit': self._Hz, 'division': self.wave.freq_div} + {'unit': self._Hz, 'division': self.activity.wave.freq_div} self.string_for_textbox = "" self.string_for_textbox += (self._STR_BASIC + "\t") - if self.wave.get_fft_mode() == False: + if self.activity.wave.get_fft_mode() == False: self.string_for_textbox += self._STR1 else: self.string_for_textbox += self._STR2 - if self.wave.get_invert_state()==True: + if self.activity.wave.get_invert_state()==True: self.string_for_textbox += self._STR3 self.string_for_textbox += ("\n" + self._STR_SCALEX) - self.textbox_copy.set_data_params(0, self.string_for_textbox) + self.activity.text_box.set_data_params(0, self.string_for_textbox) diff --git a/toolbar_side.py b/toolbar_side.py index 3d7cfd2..e0b6d29 100644 --- a/toolbar_side.py +++ b/toolbar_side.py @@ -4,7 +4,7 @@ # Copyright (C) 2007, Arjun Sarwal # Copyright (C) 2009,10 Walter Bender # -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -25,8 +25,6 @@ from gettext import gettext as _ from sugar.graphics.toolbutton import ToolButton -import config - #class SideToolbar(gtk.DrawingArea): class SideToolbar(gtk.Toolbar): """ A toolbar on the side of the canvas for adjusting gain/bias """ @@ -36,14 +34,12 @@ class SideToolbar(gtk.Toolbar): def __init__(self, activity): """ Set up initial toolbars """ - # gtk.DrawingArea.__init__(self) gtk.Toolbar.__init__(self) - self.wave = activity.wave - self.ag = activity.audiograb + self.activity = activity self.show_toolbar = True - self.mode = config.CONTEXT + self.mode = 'sound' self.mode_values = {'sound':3, 'sensor':2} self.button_up = ToolButton('amp-high') @@ -54,12 +50,12 @@ class SideToolbar(gtk.Toolbar): self.adjustmenty = gtk.Adjustment(self.mode_values[self.mode], self.LOWER, self.UPPER, 0.1, 0.1, 0.0) self.adjustmenty.connect("value_changed", self._yscrollbar_cb, - self.adjustmenty) + self.adjustmenty) self.yscrollbar = gtk.VScale(self.adjustmenty) self.yscrollbar.set_draw_value(False) self.yscrollbar.set_inverted(True) self.yscrollbar.set_update_policy(gtk.UPDATE_CONTINUOUS) - + self.button_down = ToolButton('amp-low') self.button_down.set_tooltip(_('Decrease amplitude')) self.button_down.connect('clicked', self._button_down_cb) @@ -75,40 +71,32 @@ class SideToolbar(gtk.Toolbar): def _yscrollbar_cb(self, adjy, data=None): """ Callback for scrollbar """ if self.mode == 'sound': - if adjy.value <= 1.5: - self.wave.set_mag_params(1.0, adjy.value) #0dB - self.ag.set_capture_gain(0) - elif adjy.value <= 2.5: - self.wave.set_mag_params(1.9952, adjy.value*1.5) #6dB - self.ag.set_capture_gain(25) - elif adjy.value <= 3.5: - self.wave.set_mag_params(3.981, adjy.value*3.0) #12dB - self.ag.set_capture_gain(50) - else: - self.wave.set_mag_params(13.335, adjy.value*4.0) #22.5dB - self.ag.set_capture_gain(100) - self.wave.set_bias_param(0) + self.activity.wave.set_mag_params(1.0, adjy.value) + aelf.activity.audiograb.set_capture_gain(adjy.value*\ + 100/(self.UPPER-self.LOWER)) + self.activity.wave.set_bias_param(0) elif self.mode == 'sensor': - self.wave.set_bias_param(int((adjy.value-2)*300)) + self.activity.wave.set_bias_param(int(300*\ + (adjy.value - (self.UPPER-self.LOWER)/2))) self.mode_values[self.mode] = adjy.value return True def _button_up_cb(self, data=None): """Moves slider up""" - new_value = self.yscrollbar.get_value() + (self.UPPER-self.LOWER)/100.0 - if new_value <= self.UPPER: - self.yscrollbar.set_value(new_value) - else: - self.yscrollbar.set_value(self.UPPER) + new_value = self.yscrollbar.get_value() + (self.UPPER-self.LOWER)/100.0 + if new_value <= self.UPPER: + self.yscrollbar.set_value(new_value) + else: + self.yscrollbar.set_value(self.UPPER) return True def _button_down_cb(self, data=None): """Moves slider down""" - new_value = self.yscrollbar.get_value() - (self.UPPER-self.LOWER)/100.0 - if new_value >= self.LOWER: - self.yscrollbar.set_value(new_value) - else: - self.yscrollbar.set_value(self.LOWER) + new_value = self.yscrollbar.get_value() - (self.UPPER-self.LOWER)/100.0 + if new_value >= self.LOWER: + self.yscrollbar.set_value(new_value) + else: + self.yscrollbar.set_value(self.LOWER) return True def set_show_hide(self, show=True, mode='sound'): |