def combo_factory(combo_array,
                  toolbar,
                  callback,
                  cb_arg=None,
                  tooltip=None,
                  default=None):
    '''Factory for making a toolbar combo box'''
    combo = ComboBox()
    if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
        combo.set_tooltip_text(tooltip)
    if cb_arg is not None:
        combo.connect('changed', callback, cb_arg)
    else:
        combo.connect('changed', callback)
    for i, selection in enumerate(combo_array):
        combo.append_item(i, selection, None)
    combo.show()
    toolitem = gtk.ToolItem()
    toolitem.add(combo)
    if hasattr(toolbar, 'insert'):  # the main toolbar
        toolbar.insert(toolitem, -1)
    else:  # or a secondary toolbar
        toolbar.props.page.insert(toolitem, -1)
    toolitem.show()
    if default is not None:
        combo.set_active(combo_array.index(default))
    return combo
class InstrumentToolbar(gtk.Toolbar):
    ''' The toolbar for adding new instruments '''
    def __init__(self, activity):
        gtk.Toolbar.__init__(self)
        self.activity = activity
        self.new_instruments = []

        self._name_entry = gtk.Entry()
        self._name_entry.set_text(_('my instrument'))
        self._name_entry_changed_id = self._name_entry.connect(
            'changed', self.update_name_entry)
        if hasattr(self._name_entry, 'set_tooltip_text'):
            self._name_entry.set_tooltip_text(_('Enter instrument name.'))
        self._name_entry.set_width_chars(24)
        self._name_entry.show()
        toolitem = gtk.ToolItem()
        toolitem.add(self._name_entry)
        self.insert(toolitem, -1)
        toolitem.show()

        self._notes_combo = ComboBox()
        n = 0
        for octave in range(9):
            for i in range(len(NOTES)):
                if octave == 0 and i < 9:  # Start with A0
                    continue
                self._notes_combo.append_item(n, note_octave(i, octave), None)
                n += 1
        self._notes_combo.set_active(48)  # A4
        if hasattr(self._notes_combo, 'set_tooltip_text'):
            self._notes_combo.set_tooltip_text(_('Notes'))
        self._notes_tool = ToolComboBox(self._notes_combo)
        self.insert(self._notes_tool, -1)
        self._notes_tool.show()

        self._new_note = ToolButton('list-add')
        self._new_note.show()
        self.insert(self._new_note, -1)
        self._new_note.set_tooltip(_('Add a new note.'))
        self._new_note.connect('clicked', self.new_note_cb)

    def update_name_entry(self, *args):
        ''' Add name to INSTRUMENT_DICT and combo box '''
        # Wait until a note has been added...
        return

    def new_note_cb(self, *args):
        ''' Add a new note to instrument tuning list '''
        name = self._name_entry.get_text()
        if name not in INSTRUMENT_DICT:
            INSTRUMENT_DICT[name] = []
            self.activity.tuning_toolbar.instrument.append(name)
            i = len(self.activity.tuning_toolbar.instrument)
            self.activity.tuning_toolbar.instrument_combo.append_item(
                i, name, None)
            self.new_instruments.append(name)
        i = self._notes_combo.get_active()
        freq = A0 * pow(TWELTHROOT2, i)
        if freq not in INSTRUMENT_DICT[name]:
            INSTRUMENT_DICT[name].append(freq)
def _combo_factory(options, tooltip, toolbar, callback, default=0):
    ''' Combo box factory '''
    combo = ComboBox()
    if hasattr(combo, 'set_tooltip_text'):
        combo.set_tooltip_text(tooltip)
    combo.connect('changed', callback)
    for i, option in enumerate(options):
        combo.append_item(i, option.replace('-', ' '), None)
    combo.set_active(default)
    combo.show()
    tool = ToolComboBox(combo)
    tool.show()
    toolbar.insert(tool, -1)
    return combo
Exemplo n.º 4
0
def combo_factory(combo_array, default, tooltip, callback, toolbar):
    '''Factory for making a toolbar combo box'''
    my_combo = ComboBox()
    if hasattr(my_combo, 'set_tooltip_text'):
        my_combo.set_tooltip_text(tooltip)

    my_combo.connect('changed', callback)

    for i, s in enumerate(combo_array):
        my_combo.append_item(i, s, None)

    tool = ToolComboBox(my_combo)
    if hasattr(toolbar, 'insert'):  # the main toolbar
        toolbar.insert(tool, -1)
    else:  # or a secondary toolbar
        toolbar.props.page.insert(tool, -1)
    tool.show()
    my_combo.set_active(default)
    return my_combo
Exemplo n.º 5
0
def combo_factory(combo_array, toolbar, callback, cb_arg=None,
                  tooltip=None, default=None):
    '''Factory for making a toolbar combo box'''
    combo = ComboBox()
    if tooltip is not None and hasattr(combo, 'set_tooltip_text'):
        combo.set_tooltip_text(tooltip)
    if cb_arg is not None:
        combo.connect('changed', callback, cb_arg)
    else:
        combo.connect('changed', callback)
    for i, selection in enumerate(combo_array):
        combo.append_item(i, selection, None)
    combo.show()
    toolitem = gtk.ToolItem()
    toolitem.add(combo)
    if hasattr(toolbar, 'insert'):  # the main toolbar
        toolbar.insert(toolitem, -1)
    else:  # or a secondary toolbar
        toolbar.props.page.insert(toolitem, -1)
    toolitem.show()
    if default is not None:
        combo.set_active(combo_array.index(default))
    return combo
Exemplo n.º 6
0
class SensorToolbar(gtk.Toolbar):
    ''' The toolbar for specifiying the sensor: sound, resitance, or
    voltage '''

    LOWER = 0.0
    UPPER = 1.0
    STR_DC_R = \
        _("Resistive sensor (connect sensor to pink 'Mic In' on left side \
of XO)"       ) + ' '
    STR_DC_V = \
        _("Voltage sensor (connect sensor to pink 'Mic In' on left side \
of XO)"       ) + ' '
    STR_AC = _('Sound') + ' '
    STR_RESISTANCE = _('Resistance') + ' (' + _('Ohms') + ') '
    STR_VOLTAGE = _('Voltage') + ' (' + _('Volts') + ') '
    STR_TIME = _('Time Base') + ' '
    STR_FREQUENCY = _('Frequency Base') + ' '
    STR_INVERT = ' ' + _('Invert') + ' '
    STR_XAXIS_TEXT = _('X Axis Scale: 1 division = %(division)s %(unit)s')
    # TRANSLATORS: This is milli seconds.
    MS = _('ms')
    # TRANSLATORS: This is Hertz, so 1/second.
    HZ = _('Hz')

    def __init__(self, activity, channels):
        ''' By default, start with resistance mode '''

        gtk.Toolbar.__init__(self)

        self.activity = activity
        self._channels = channels
        self._lock_radio_buttons = False
        self._radio_button_pushed = False
        self.values = []
        for i in range(self._channels):
            self.values.append('')

        self.string_for_textbox = ''

        self.gain = 1.0
        self.y_mag = 3.0
        self.capture_gain = CAPTURE_GAIN
        self.mic_boost = MIC_BOOST

        self.mode = 'sound'

        # Set up Time-domain Button
        self.time = RadioToolButton(group=None)
        self.time.set_named_icon('media-audio')
        self.insert(self.time, -1)
        self.time.set_tooltip(_('Sound'))
        self.time.connect('clicked', self.analog_resistance_voltage_mode_cb,
                          'sound')

        # Set up Resistance Button
        self.resistance = RadioToolButton(group=self.time)
        self.resistance.set_named_icon('resistance')
        if _is_xo(self.activity.hw):
            self.insert(self.resistance, -1)
        self.resistance.show()
        self.resistance.set_tooltip(_('Resistance Sensor'))
        self.resistance.connect('clicked',
                                self.analog_resistance_voltage_mode_cb,
                                'resistance')

        # Set up Voltage Button
        self.voltage = RadioToolButton(group=self.time)
        self.voltage.set_named_icon('voltage')
        if _is_xo(self.activity.hw):
            self.insert(self.voltage, -1)
        self.voltage.set_tooltip(_('Voltage Sensor'))
        self.voltage.connect('clicked', self.analog_resistance_voltage_mode_cb,
                             'voltage')

        separator = gtk.SeparatorToolItem()
        separator.props.draw = True
        self.insert(separator, -1)

        self._log_interval_combo = ComboBox()
        self.interval = [
            _('1/10 second'),
            _('1 second'),
            _('30 seconds'),
            _('5 minutes'),
            _('30 minutes')
        ]

        if hasattr(self._log_interval_combo, 'set_tooltip_text'):
            self._log_interval_combo.set_tooltip_text(_('Sampling interval'))

        self._interval_changed_id = self._log_interval_combo.connect(
            'changed', self.log_interval_cb)

        for i, s in enumerate(self.interval):
            self._log_interval_combo.append_item(i, s, None)
            if s == _('1 second'):
                self._log_interval_combo.set_active(i)

        self._log_interval_tool = ToolComboBox(self._log_interval_combo)
        self.insert(self._log_interval_tool, -1)
        self.logging_interval_status = '1 second'

        # Set up Logging/Stop Logging Button
        self._record = ToolButton('media-record')
        self.insert(self._record, -1)
        self._record.set_tooltip(_('Start Recording'))
        self._record.connect('clicked', self.record_control_cb)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)

        # Set up Trigger Combo box
        self.trigger_combo = ComboBox()
        self.trigger = [_('None'), _('Rising Edge'), _('Falling Edge')]
        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)
        for i, s in enumerate(self.trigger):
            self.trigger_combo.append_item(i, s, None)
        self.trigger_combo.set_active(0)
        if hasattr(self.trigger_combo, 'set_tooltip_text'):
            self.trigger_combo.set_tooltip_text(_('Create a trigger'))
        self._trigger_tool = ToolComboBox(self.trigger_combo)
        self.insert(self._trigger_tool, -1)

        self.show_all()

    def add_frequency_slider(self, toolbar):
        ''' Either on the Sound toolbar or the Main toolbar '''
        self._freq_stepper_up = ToolButton('freq-high')
        self._freq_stepper_up.set_tooltip(_('Zoom out'))
        self._freq_stepper_up.connect('clicked', self._freq_stepper_up_cb)
        self.activity.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER,
                                                   0.01, 0.1, 0)
        self.activity.adjustmentf.connect('value_changed', self.cb_page_sizef)
        self._freq_range = gtk.HScale(self.activity.adjustmentf)
        self._freq_range.set_inverted(True)
        self._freq_range.set_draw_value(False)
        self._freq_range.set_update_policy(gtk.UPDATE_CONTINUOUS)
        self._freq_range.set_size_request(120, 15)

        self._freq_stepper_down = ToolButton('freq-low')
        self._freq_stepper_down.set_tooltip(_('Zoom in'))
        self._freq_stepper_down.connect('clicked', self._freq_stepper_down_cb)

        self._freq_range_tool = gtk.ToolItem()
        self._freq_range_tool.add(self._freq_range)

        toolbar.insert(self._freq_stepper_up, -1)
        toolbar.insert(self._freq_range_tool, -1)
        toolbar.insert(self._freq_stepper_down, -1)
        return

    def update_trigger_control(self, *args):
        ''' Callback for trigger control '''
        if self.activity.wave.get_fft_mode():
            self.trigger_combo.set_active(self.activity.wave.TRIGGER_NONE)
        active = self.trigger_combo.get_active()
        if active == -1:
            return

        self.activity.wave.set_trigger(self.trigger_conf[active])
        return

    def analog_resistance_voltage_mode_cb(self,
                                          button=None,
                                          mode_to_set='sound'):
        ''' Callback for Analog/Resistance/Voltage Buttons '''
        if self._lock_radio_buttons:
            logging.debug('mode selector locked')
            self._radio_button_pushed = True
            return
        if self.mode == mode_to_set:
            logging.debug('mode already set to %s' % mode_to_set)
            return
        self._lock_radio_buttons = True
        if self.activity.CONTEXT == 'sound':
            self.sound_context_off()
        else:
            self.sensor_context_off()

        # Force time domain when switching modes
        if self.activity.wave.get_fft_mode():
            self.activity.timefreq_control()
        # Turn off logging when switching modes
        if self.activity.audiograb.we_are_logging:
            self.record_control_cb()

        self.set_mode(mode_to_set)
        if mode_to_set == 'sound':
            self.set_sound_context()
        elif mode_to_set == 'resistance':
            self.set_sensor_context()
        elif mode_to_set == 'voltage':
            self.set_sensor_context()
        self.update_string_for_textbox()
        return False

    def unlock_radio_buttons(self):
        ''' Enable radio button selection '''
        logging.debug('unlocking radio buttons')
        if self._radio_button_pushed:
            if self.mode == 'sound':
                self.time.set_active(True)
            elif self.mode == 'resistance':
                self.resistance.set_active(True)
            elif self.mode == 'voltage':
                self.voltage.set_active(True)
        self._lock_radio_buttons = False
        self._radio_button_pushed = False

    def set_mode(self, mode='sound'):
        ''' Set the mixer settings to match the current mode. '''
        self.mode = mode
        self.activity.audiograb.set_sensor_type(self.mode)
        for i in range(self._channels):
            self.values[i] = 0.0
        return

    def get_mode(self):
        ''' Get the mixer settings. '''
        return self.mode

    def _freq_stepper_up_cb(self, button=None):
        ''' Moves the horizontal zoom slider to the left one notch,
        where one notch is 1/100 of the total range. This correspond
        to zooming out as a larger number of Hertz or milliseconds
        will be represented by the same space on the screen. '''
        new_value = self._freq_range.get_value() +\
                    (self.UPPER - self.LOWER) / 100.0
        if new_value <= self.UPPER:
            self._freq_range.set_value(new_value)
        else:
            self._freq_range.set_value(self.UPPER)

    def _freq_stepper_down_cb(self, button=None):
        ''' Moves the horizontal zoom slider to the right one notch,
        where one notch is 1/100 of the total range. This corresponds
        to zooming in. '''
        new_value = self._freq_range.get_value() -\
                    (self.UPPER - self.LOWER) / 100.0
        if new_value >= self.LOWER:
            self._freq_range.set_value(new_value)
        else:
            self._freq_range.set_value(self.LOWER)

    def cb_page_sizef(self, button=None):
        ''' Callback to scale the frequency range (zoom in and out) '''
        if self._update_page_size_id:
            gobject.source_remove(self._update_page_size_id)
        self._update_page_size_id =\
            gobject.timeout_add(250, self.update_page_size)
        return True

    def update_page_size(self):
        ''' Set up the scaling of the display. '''
        self._update_page_size_id = None
        new_value = round(self.activity.adjustmentf.value * 100.0) / 100.0
        if self.activity.adjustmentf.value != new_value:
            self.activity.adjustmentf.value = new_value
            return False
        time_div = 0.001 * max(self.activity.adjustmentf.value, 0.05)
        freq_div = 1000 * max(self.activity.adjustmentf.value, 0.01)
        self.activity.wave.set_div(time_div, freq_div)
        self.update_string_for_textbox()
        return False

    def set_sound_context(self):
        ''' Called when analog sensing is selected '''
        self.set_show_hide_windows(mode='sound')
        gobject.timeout_add(500, self.sound_context_on)
        self.activity.CONTEXT = 'sound'

    def set_sensor_context(self):
        ''' Called when digital sensing is selected '''
        self.set_show_hide_windows(mode='sensor')
        gobject.timeout_add(500, self.sensor_context_on)
        self.activity.CONTEXT = 'sensor'

    def set_show_hide_windows(self, mode='sound'):
        ''' Shows the appropriate window identified by the mode '''
        self.activity.wave.set_context_on()
        for i in range(self._channels):
            self.activity.side_toolbars[i].set_show_hide(True, mode)

    def sensor_context_off(self):
        ''' Called when a DC sensor is no longer selected '''
        # self.activity.audiograb.pause_grabbing()
        self.activity.audiograb.stop_grabbing()

    def sensor_context_on(self):
        ''' Called when a DC sensor is selected '''
        self.update_string_for_textbox()
        self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE)
        # self.activity.audiograb.resume_grabbing()
        self.activity.audiograb.start_grabbing()
        return False

    def sound_context_off(self):
        ''' Called when an analog sensor is no longer selected '''
        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_grabbing()

    def sound_context_on(self):
        ''' Called when an analog sensor is selected '''
        self.activity.wave.set_mag_params(self.gain, self.y_mag)
        self.update_string_for_textbox()
        self.update_trigger_control()
        self.activity.audiograb.start_grabbing()
        return False

    def set_sample_value(self, value='', channel=0):
        ''' Write a sample value to the textbox. '''
        gtk.threads_enter()
        self.values[channel] = value
        self.update_string_for_textbox()
        gtk.threads_leave()
        return

    def record_control_cb(self, button=None):
        ''' Depending upon the selected interval, does either a logging
        session, or just logs the current buffer. '''
        if self.activity.audiograb.we_are_logging:
            self.activity.audiograb.set_logging_params(start_stop=False)
            self._record.set_icon('media-record')
            self._record.show()
            self._record.set_tooltip(_('Start Recording'))
        else:
            Xscale = (1.00 / self.activity.audiograb.get_sampling_rate())
            Yscale = 0.0
            interval = self.interval_convert()
            username = self.activity.nick
            if self.activity.wave.get_fft_mode():
                self.activity.data_logger.start_new_session(
                    username,
                    Xscale,
                    Yscale,
                    _(self.logging_interval_status),
                    channels=self._channels,
                    mode='frequency')
            else:
                self.activity.data_logger.start_new_session(
                    username,
                    Xscale,
                    Yscale,
                    _(self.logging_interval_status),
                    channels=self._channels,
                    mode=self.mode)
            self.activity.audiograb.set_logging_params(start_stop=True,
                                                       interval=interval,
                                                       screenshot=False)
            self._record.set_icon('record-stop')
            self._record.show()
            self._record.set_tooltip(_('Stop Recording'))
            self.activity.new_recording = True

    def interval_convert(self):
        ''' Converts interval string to an integer that denotes the
        number of times the audiograb buffer must be called before a
        value is written.  When set to 0, the whole of current buffer
        will be written. '''
        interval_dictionary = {
            '1/10 second': 0.1,
            '1 second': 1,
            '30 seconds': 30,
            '5 minutes': 300,
            '30 minutes': 1800
        }
        try:
            return interval_dictionary[self.logging_interval_status]
        except ValueError:
            logging.error('logging interval status = %s' %\
                              (str(self.logging_interval_status)))
            return 0

    def log_interval_cb(self, combobox):
        ''' Callback from the Logging Interval Combo box: sets status '''
        if self._log_interval_combo.get_active() != -1:
            intervals = [
                '1/10 second', '1 second', '30 seconds', '5 minutes',
                '30 minutes'
            ]
            self.logging_interval_status = \
                              intervals[self._log_interval_combo.get_active()]

    def update_string_for_textbox(self):
        ''' Update the status field at the bottom of the canvas. '''
        if self.activity.CONTEXT == 'butia':
            string_for_textbox = ''
        else:
            if self.mode == 'resistance':
                string_for_textbox = (self.STR_DC_R + '\n')
                string_for_textbox += self.STR_RESISTANCE
            elif self.mode == 'voltage':
                string_for_textbox = (self.STR_DC_V + '\n')
                string_for_textbox += self.STR_VOLTAGE
            else:
                string_for_textbox = (self.STR_AC + '\t')
            if self.activity.wave.get_fft_mode():
                scalex = self.STR_XAXIS_TEXT % {
                    'unit': self.HZ,
                    'division': self.activity.wave.freq_div
                }
                string_for_textbox += self.STR_FREQUENCY
                string_for_textbox += ('\n' + scalex)
            elif self.mode == 'sound':
                scalex = self.STR_XAXIS_TEXT % {
                    'unit': self.MS,
                    'division': self.activity.wave.time_div * 1000
                }
                string_for_textbox += self.STR_TIME
                string_for_textbox += ('\n' + scalex)
            else:
                for i in range(self._channels):
                    string_for_textbox += '\t(%s)' % (self.values[i])
        invert = False
        for i in range(self._channels):
            if self.activity.wave.get_invert_state(channel=i):
                invert = True
        if invert:
            string_for_textbox += self.STR_INVERT
        self.activity.text_box.set_label(string_for_textbox)
class SoundToolbar(gtk.Toolbar):
    """ Set up the toolbar for audio (analog) capture mode """

    SAMPLE_NOW = _('Capture now')
    SAMPLE_30_SEC = _('Every 30 sec.')
    SAMPLE_2_MIN = _('Every 2 min.')
    SAMPLE_10_MIN = _('Every 10 min.')
    SAMPLE_30_MIN = _('Every 30 min.')

    LOWER = 0.0
    UPPER = 1.0

    def __init__(self, activity):
        """ Initialize the toolbar controls. """
        gtk.Toolbar.__init__(self)

        self.activity = activity

        self._STR_BASIC = _('Sound') + ' '
        self._STR1 = _('Time Base') + ' '
        self._STR2 = _('Frequency Base') + ' '
        self._STR3 = ' ' + _('Invert') + ' '
        self._STR_SCALEX = ""
        self._STR_XAXIS_TEXT = \
            _('X Axis Scale: 1 division = %(division)s %(unit)s')
        # TRANSLATORS: This is milli seconds.
        self._ms = _('ms')
        # TRANSLATORS: This is Hertz, so 1/second.
        self._Hz = _('Hz')

        self._update_page_size_id = None

        self.string_for_textbox = ""

        self.gain = 1.0
        self.y_mag = 3.0
        self.capture_gain = CAPTURE_GAIN
        self.mic_boost = MIC_BOOST

        # self.logging_status = False
        self._record = None

        # Set up Time-domain Button
        self.time = ToolButton('domain-time2')
        self.insert(self.time, -1)
        self.time.set_tooltip(_('Time Base'))
        self.time.connect('clicked', self._timefreq_control_cb, True)

        # Set up Frequency-domain Button
        self.freq = ToolButton('domain-freq')
        self.insert(self.freq, -1)
        self.freq.show()
        self.freq.set_tooltip(_('Frequency Base'))
        self.freq.connect('clicked', self._timefreq_control_cb, False)

        # Set up Frequency-control Slider and corresponding buttons
        if not self.activity.has_toolbarbox:
            self.add_frequency_slider(self)

        # Set up the Pause Button
        self._pause = ToolButton('media-playback-pause')
        self.insert(self._pause, -1)
        self._pause.set_tooltip(_('Freeze the display'))
        self._pause.connect('clicked', self._pauseplay_control_cb)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)
            separator.show()

        self.loginterval_img = gtk.Image()
        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)

        # Set up the Logging-interval Combo box
        self._loginterval_combo = ComboBox()
        self.interval = [
            _(self.SAMPLE_NOW),
            _(self.SAMPLE_30_SEC),
            _(self.SAMPLE_2_MIN),
            _(self.SAMPLE_10_MIN),
            _(self.SAMPLE_30_MIN)
        ]

        if hasattr(self._loginterval_combo, 'set_tooltip_text'):
            self._loginterval_combo.set_tooltip_text(_('Sampling interval'))

        self._interval_changed_id = self._loginterval_combo.connect(
            'changed', self.loginterval_control)

        for i, s in enumerate(self.interval):
            self._loginterval_combo.append_item(i, s, None)
            if s == self.SAMPLE_NOW:
                self._loginterval_combo.set_active(i)

        self._loginterval_tool = ToolComboBox(self._loginterval_combo)
        self.insert(self._loginterval_tool, -1)
        self.logginginterval_status = 'picture'

        # Set up Start/Stop Logging Button
        self._record = ToolButton('media-record')
        self.insert(self._record, -1)
        self._record.set_tooltip(_('Capture sample now'))

        self._record.connect('clicked', self.record_control)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)

        # Set up Trigger Combo box
        self._trigger_combo = ComboBox()
        self.trigger = [_('None'), _('Rising Edge'), _('Falling Edge')]
        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)

        for i, s in enumerate(self.trigger):
            self._trigger_combo.append_item(i, s, None)
        self._trigger_combo.set_active(0)

        if hasattr(self._trigger_combo, 'set_tooltip_text'):
            self._trigger_combo.set_tooltip_text(_('Create a trigger'))

        self._trigger_tool = ToolComboBox(self._trigger_combo)
        self.insert(self._trigger_tool, -1)
        self.show_all()

        return

    def add_frequency_slider(self, toolbar):
        """ Either on the Sound toolbar or the Main toolbar """
        self._freq_stepper_up = ToolButton('freq-high')
        self._freq_stepper_up.set_tooltip(_('Zoom out'))
        self._freq_stepper_up.connect('clicked', self._freq_stepper_up_cb)

        self.activity.adjustmentf = gtk.Adjustment(0.5, self.LOWER, self.UPPER,
                                                   0.01, 0.1, 0)
        self.activity.adjustmentf.connect('value_changed', self.cb_page_sizef)
        self._freq_range = gtk.HScale(self.activity.adjustmentf)
        self._freq_range.set_inverted(True)
        self._freq_range.set_draw_value(False)
        self._freq_range.set_update_policy(gtk.UPDATE_CONTINUOUS)
        self._freq_range.set_size_request(120, 15)

        self._freq_stepper_down = ToolButton('freq-low')
        self._freq_stepper_down.set_tooltip(_('Zoom in'))
        self._freq_stepper_down.connect('clicked', self._freq_stepper_down_cb)

        self._freq_range_tool = gtk.ToolItem()
        self._freq_range_tool.add(self._freq_range)

        toolbar.insert(self._freq_stepper_up, -1)
        toolbar.insert(self._freq_range_tool, -1)
        toolbar.insert(self._freq_stepper_down, -1)

        return

    def _set_icon_ready(self):
        self._record.set_icon('media-record')
        self._record.show()
        return False

    def _set_icon_stop(self):
        self._record.set_icon('record-stop')
        self._record.show()
        return False

    def record_control_delayed(self, data=None):
        """Depending upon the selected interval, either starts/stops
        a logging session, or just logs the current buffer"""
        if not self.activity.LOGGING_IN_SESSION:
            Xscale = (1.00 / self.activity.audiograb.get_sampling_rate())
            Yscale = 0.0
            interval = self.interval_convert()
            username = self.activity.nick
            self.activity.ji.start_new_session(username, Xscale, Yscale,
                                               self.logginginterval_status)
            self.activity.audiograb.set_logging_params(True, interval, True)
            self.activity.LOGGING_IN_SESSION = True
            self._set_icon_stop()
            if interval == 0:
                # Flash the stop button when grabbing just one image
                gobject.timeout_add(250, self._set_icon_ready)
                self.record_state = False
                self.activity.LOGGING_IN_SESSION = False
                self.logging_status = False
        else:
            self.activity.audiograb.set_logging_params(False)
            self.activity.LOGGING_IN_SESSION = False
            self._set_icon_ready()
        self._set_record_button_tooltip()
        return False

    def record_control(self, data=None):
        self._record.palette.popdown()
        gtk.gdk.flush()
        gobject.timeout_add(10, self.record_control_delayed, data)

    def interval_convert(self):
        """Converts picture/time interval to an integer that denotes the number
        of times the audiograb buffer must be called before a value is written.
        When set to 0, the whole of current buffer will be written
        1second= about 66 ticks at 48khz sampling"""
        if self.logginginterval_status == 'picture':
            return 0
        elif self.logginginterval_status == '30second':
            return 30  #2667
        elif self.logginginterval_status == '2minute':
            return 120  #10668
        elif self.logginginterval_status == '10minute':
            return 600  #53340
        elif self.logginginterval_status == '30minute':
            return 1800  #160000

    def loginterval_control(self, combobox):
        """ The combo box has changed. Set the logging interval
        status correctly and then set the tooltip on the record
        button properly depending upon whether logging is currently
        in progress or not. """
        if (self._loginterval_combo.get_active() != -1):
            if (self._loginterval_combo.get_active() == 0):
                self.logginginterval_status = 'picture'
            elif (self._loginterval_combo.get_active() == 1):
                self.logginginterval_status = '30second'
            elif (self._loginterval_combo.get_active() == 2):
                self.logginginterval_status = '2minute'
            elif (self._loginterval_combo.get_active() == 3):
                self.logginginterval_status = '10minute'
            elif (self._loginterval_combo.get_active() == 4):
                self.logginginterval_status = '30minute'
            self._set_record_button_tooltip()
        return

    def _set_record_button_tooltip(self):
        """ Determines the tool tip for the record button. The tool tip
        text depends upon whether sampling is currently on and whether
        the sampling interval > 0. """
        if self._record == None:
            return
        if self.activity.LOGGING_IN_SESSION:
            self._record.set_tooltip(_('Stop sampling'))
        else:  # No sampling in progress
            if (self._loginterval_combo.get_active() == 0):
                self._record.set_tooltip(_('Capture sample now'))
            else:
                self._record.set_tooltip(_('Start sampling'))
        return

    def update_trigger_control(self, *args):
        """ Callback for trigger control """
        active = self._trigger_combo.get_active()
        if active == -1:
            return

        self.activity.wave.set_trigger(self.trigger_conf[active])
        return

    def _pauseplay_control_cb(self, data=None):
        """ Callback for Pause Button """
        if self.activity.audiograb.get_freeze_the_display():
            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.activity.audiograb.set_freeze_the_display(True)
            self._pause.set_icon('media-playback-pause')
            self._pause.set_tooltip(_('Freeze the display'))
            self._pause.show()
        return False

    def _timefreq_control_cb(self, data=None, time_state=True):
        """ Callback for Time and Freq. Buttons """

        # Make sure the current context is for sound capture.
        if self.activity.CONTEXT != 'sound':
            self.activity.set_sound_context()

        if time_state:
            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()
            if self.activity.has_toolbarbox:
                self.activity.label_button.set_icon('domain-time2')
                self.activity.label_button.set_tooltip(_('Time Base'))
        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()
            if self.activity.has_toolbarbox:
                self.activity.label_button.set_icon('domain-freq2')
                self.activity.label_button.set_tooltip(_('Frequency Base'))
        if self.activity.has_toolbarbox and \
                hasattr(self.activity, 'sensor_toolbar'):
            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):
        """Moves the horizontal zoom slider to the left one notch, where
        one notch is 1/100 of the total range. This correspond to zooming
        out as a larger number of Hertz or milliseconds will be
        represented by the same space on the screen."""
        new_value = self._freq_range.get_value() +\
                    (self.UPPER - self.LOWER) / 100.0
        if new_value <= self.UPPER:
            self._freq_range.set_value(new_value)
        else:
            self._freq_range.set_value(self.UPPER)

    def _freq_stepper_down_cb(self, data=None):
        """Moves the horizontal zoom slider to the right one notch, where
        one notch is 1/100 of the total range. This corresponds to zooming
        in."""
        new_value = self._freq_range.get_value() -\
                    (self.UPPER - self.LOWER) / 100.0
        if new_value >= self.LOWER:
            self._freq_range.set_value(new_value)
        else:
            self._freq_range.set_value(self.LOWER)

    def cb_page_sizef(self, data=None):
        """ Callback to scale the frequency range (zoom in and out) """
        if self._update_page_size_id:
            gobject.source_remove(self._update_page_size_id)
        self._update_page_size_id =\
            gobject.timeout_add(250, self.update_page_size)
        return True

    def update_page_size(self):
        """ Set up the scaling of the display """
        self._update_page_size_id = None

        new_value = round(self.activity.adjustmentf.value * 100.0) / 100.0
        if self.activity.adjustmentf.value != new_value:
            self.activity.adjustmentf.value = new_value
            return False

        time_div = 0.001 * max(self.activity.adjustmentf.value, 0.05)
        freq_div = 1000 * max(self.activity.adjustmentf.value, 0.01)

        self.activity.wave.set_div(time_div, freq_div)

        self._update_string_for_textbox()

        return False

    def context_off(self):
        """When some other context is switched to and the sound context 
        is switched off"""
        print "context off: gain and y_mag were %f and %f" %\
            (self.gain, self.y_mag)
        self.gain, self.y_mag = self.activity.wave.get_mag_params()
        print "context off: gain and y_mag are %f and %f" %\
            (self.gain, self.y_mag)
        self.capture_gain = self.activity.audiograb.get_capture_gain()
        self.mic_boost = self.activity.audiograb.get_mic_boost()
        print "context off: capture gain %s and mic boost %s" %\
              (str(self.capture_gain), str(self.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.activity.audiograb.start_sound_device()
        self.activity.audiograb.set_sensor_type('sound')
        self.activity.wave.set_fft_mode(False)
        print "context on: gain and y_mag are %f and %f" %\
              (self.gain, self.y_mag)
        self.activity.wave.set_mag_params(self.gain, self.y_mag)
        self._update_string_for_textbox()
        self.update_trigger_control()
        return False

    def _update_string_for_textbox(self):
        """ Update the text at the bottom of the canvas """
        if not self.activity.wave.get_fft_mode():
            self._STR_SCALEX = self._STR_XAXIS_TEXT % \
                {'unit': self._ms,
                 'division': self.activity.wave.time_div*1000}
        else:
            self._STR_SCALEX = self._STR_XAXIS_TEXT % \
                {'unit': self._Hz, 'division': self.activity.wave.freq_div}

        self.string_for_textbox = ""
        self.string_for_textbox += (self._STR_BASIC + '\t')
        if not self.activity.wave.get_fft_mode():
            self.string_for_textbox += self._STR1
        else:
            self.string_for_textbox += self._STR2
        if self.activity.wave.get_invert_state():
            self.string_for_textbox += self._STR3
        self.string_for_textbox += ('\n' + self._STR_SCALEX)
        self.activity.text_box.set_data_params(0, self.string_for_textbox)
class SensorToolbar(gtk.Toolbar):
    """ The toolbar for resitance and voltage sensors """
    __gsignals__ = {
        'add-media': (gobject.SIGNAL_RUN_FIRST, None, [object]),
        'add-opened': (gobject.SIGNAL_RUN_FIRST, None, [object])
    }

    def __init__(self, activity):
        """ By default, start with resistance mode """

        gtk.Toolbar.__init__(self)

        self.mode = 'resistance'

        self._STR_BASIC = \
        _("Sensors, DC (connect sensor to pink 'Mic In' on left side of XO)") \
        + ' '
        self._STR_R = _('Bias/Offset Enabled') + ' ' + _('Ohms') + ' '
        self._STR_V = _('Bias/Offset Disabled') + ' ' + _('Volts') + ' '
        self._STR_I = ' ' + _('Invert') + ' '

        self.string_for_textbox = ""

        self.activity = activity
        self.activity.audiograb.set_sensor(self)

        # Set up Resistance Button
        if self.activity.has_toolbarbox:
            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'))
        self.resistance.connect('clicked', self.set_resistance_voltage_mode,
                                'resistance')

        # Set up Voltage Button
        self.voltage = ToolButton('bias-off')
        self.insert(self.voltage, -1)
        self.voltage.set_tooltip(_('Voltage Sensor'))
        self.voltage.connect('clicked', self.set_resistance_voltage_mode,
                             'voltage')

        # Set up Invert Button
        self._invert = ToolButton('invert')
        self.insert(self._invert, -1)
        self._invert.set_tooltip(_('Invert'))
        self._invert.connect('clicked', self._invert_control_cb)
        self.activity.wave.set_invert_state(False)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = True
        self.insert(separator, -1)

        self.audiobutton = ToolButton('add-icon')
        self.insert(self.audiobutton, -1)
        self.audiobutton.show()
        self.audiobutton.set_tooltip('Close Sound')
        self.audiobutton.connect('clicked', self.addAudio)
        self.connect('add-media', self.addThisAudio)

        self.insert(separator, -1)
        self.insert(separator, -1)

        self.openedbutton = ToolButton('delete-icon')
        self.insert(self.openedbutton, -1)
        self.openedbutton.show()
        self.openedbutton.set_tooltip('Open Sound')
        self.openedbutton.connect('clicked', self.addOpenedAudio)
        self.connect('add-opened', self.addThisOpenedAudio)

        self.insert(separator, -1)
        self.insert(separator, -1)

        # Set up Logging Interval combo box
        self.loginterval_img = gtk.Image()
        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)

        self._loginterval_combo = ComboBox()
        self.interval = [
            _('1/10 second'),
            _('1 second'),
            _('30 seconds'),
            _('5 minutes'),
            _('30 minutes')
        ]

        if hasattr(self._loginterval_combo, 'set_tooltip_text'):
            self._loginterval_combo.set_tooltip_text(_('Sampling interval'))

        self._interval_changed_id = self._loginterval_combo.connect(
            "changed", self.loginterval_control)

        for i, s in enumerate(self.interval):
            self._loginterval_combo.append_item(i, s, None)
            if s == _('1 second'):
                self._loginterval_combo.set_active(i)

        self._loginterval_tool = ToolComboBox(self._loginterval_combo)
        self.insert(self._loginterval_tool, -1)
        self.logginginterval_status = '1 second'

        # Set up Logging/Stop Logging Button
        self._record = ToolButton('media-record')
        self.insert(self._record, -1)
        self._record.set_tooltip(_('Start Recording'))
        self._record.connect('clicked', self.record_control)

        self.show_all()

    def addAudio(self, button):
        #self.activity.showFileLoadBlocker(True)
        fp = FilePicker()
        dOb = fp.show()
        if (dOb != None):
            if (dOb.file_path != None):
                self.emit('add-media', dOb)
        #self.activity.showFileLoadBlocker(False)

    def addOpenedAudio(self, button):
        fp = FilePicker()
        dOb = fp.show()
        if (dOb != None):
            if (dOb.file_path != None):
                self.emit('add-opened', dOb)

    def addThisAudio(self, ot, datastoreOb):
        self.activity.closedSound = datastoreOb
        #self.activity.playsound.setLocation("file://"+datastoreOb.file_path)
        #self.activity.playsound.play()

    def addThisOpenedAudio(self, ot, datastoreOb):
        self.activity.openedSound = datastoreOb

    def set_sample_value(self, label=None):
        """ Write a sample value to the textbox """
        gtk.threads_enter()
        self._update_string_for_textbox(label)
        gtk.threads_leave()
        return

    def record_control(self, data=None):
        """Depending upon the selected interval, does either
        a logging session, or just logs the current buffer"""

        if not self.activity.LOGGING_IN_SESSION:
            Xscale = (1.00 / self.activity.audiograb.get_sampling_rate())
            Yscale = 0.0
            interval = self.interval_convert()
            username = self.activity.nick
            print "calling start new session"
            self.activity.ji.start_new_session(username, Xscale, Yscale,
                                               _(self.logginginterval_status))
            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:
            self.activity.audiograb.set_logging_params(False)
            self.activity.LOGGING_IN_SESSION = False
            self._record.set_icon('media-record')
            self._record.show()
            self._record.set_tooltip(_('Start Recording'))

    def interval_convert(self):
        """Converts interval string to an integer that denotes the number
        of times the audiograb buffer must be called before a value is written.
        When set to 0, the whole of current buffer will be written"""
        interval_dictionary = {
            '1/10 second': 0.1,
            '1 second': 1,
            '30 seconds': 30,
            '5 minutes': 300,
            '30 minutes': 1800
        }
        try:
            return interval_dictionary[self.logginginterval_status]
        except ValueError:
            logging.error('logging interval status = %s' %\
                              (str(self.logginginterval_status)))
            return 0

    def loginterval_control(self, combobox):
        """ Callback from the Logging Interval Combo box: sets status """
        if self._loginterval_combo.get_active() != -1:
            intervals = [
                '1/10 second', '1 second', '30 seconds', '5 minutes',
                '30 minutes'
            ]
            self.logginginterval_status = \
                              intervals[self._loginterval_combo.get_active()]

    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')
            self.voltage.set_icon('bias-off')
            self.resistance.show()
            self.voltage.show()
            self._update_string_for_textbox()
            if self.activity.has_toolbarbox:
                self.activity.label_button.set_icon('bias-on2')
                self.activity.label_button.set_tooltip(_('Resistance Sensor'))
        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()
            if self.activity.has_toolbarbox:
                self.activity.label_button.set_icon('bias-off2')
                self.activity.label_button.set_tooltip(_('Voltage Sensor'))
        else:
            logging.error('unknown mode %s' % (mode_to_set))
        if self.activity.has_toolbarbox:
            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.activity.wave.get_invert_state():
            self.activity.wave.set_invert_state(False)
            self._invert.set_icon('invert')
            self._invert.show()
        else:
            self.activity.wave.set_invert_state(True)
            self._invert.set_icon('invert2')
            self._invert.show()
        self._update_string_for_textbox()
        return False

    def set_mode(self, mode='resistance'):
        """ Set the mixer settings to match the current mode. """
        self.mode = mode
        self.activity.audiograb.set_sensor_type(self.mode)
        return

    def context_off(self):
        """ Called when sensor toolbar is no longer selected. """
        self.activity.audiograb.pause_grabbing()

    def context_on(self):
        """ Called when sensor toolbar is selected. """
        self.activity.audiograb.resume_grabbing()
        self.activity.audiograb.set_sensor_type(self.mode)
        self._update_string_for_textbox()
        self.activity.wave.set_trigger(self.activity.wave.TRIGGER_NONE)
        return False

    def _update_string_for_textbox(self, value=None):
        """ Update the status field at the bottom of the canvas. """
        self.string_for_textbox = ""
        self.string_for_textbox += (self._STR_BASIC + "\n")
        if self.mode == 'resistance':
            self.string_for_textbox += self._STR_R
        else:
            self.string_for_textbox += self._STR_V
        if self.activity.wave.get_invert_state():
            self.string_for_textbox += self._STR_I
        if value is not None:
            self.string_for_textbox += '\t(%s)' % (str(value))
        self.activity.text_box.set_data_params(0, self.string_for_textbox)
class TuningToolbar(gtk.Toolbar):
    ''' The toolbar for tuning instruments '''
    def __init__(self, activity):
        gtk.Toolbar.__init__(self)

        self.activity = activity
        self._show_tuning_line = False
        self._updating_note = True
        self._tuning_tool = None

        # Set up Instrument Combo box
        self.instrument_combo = ComboBox()
        self.instrument = [_('None')]
        for k in INSTRUMENT_DICT.keys():
            self.instrument.append(k)
        self._instrument_changed_id = self.instrument_combo.connect(
            'changed', self.update_instrument_control)
        for i, instrument in enumerate(self.instrument):
            self.instrument_combo.append_item(i, instrument, None)
        self.instrument_combo.set_active(0)
        if hasattr(self.instrument_combo, 'set_tooltip_text'):
            self.instrument_combo.set_tooltip_text(_('Tune an instrument.'))
        self._instrument_tool = ToolComboBox(self.instrument_combo)
        self.insert(self._instrument_tool, -1)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)

        self._notes_combo = ComboBox()
        n = 0
        for octave in range(9):
            for i in range(len(NOTES)):
                if octave == 0 and i < 9:  # Start with A0
                    continue
                self._notes_combo.append_item(n, note_octave(i, octave), None)
                n += 1
        self._notes_combo.set_active(48)  # A4
        self._notes_changed_id = self._notes_combo.connect(
            'changed', self.update_note)
        if hasattr(self._notes_combo, 'set_tooltip_text'):
            self._notes_combo.set_tooltip_text(_('Notes'))
        self._notes_tool = ToolComboBox(self._notes_combo)
        self.insert(self._notes_tool, -1)

        # The entry is used to display a note or for direct user input
        self._freq_entry = gtk.Entry()
        self._freq_entry.set_text('440')  # A
        self._freq_entry_changed_id = self._freq_entry.connect(
            'changed', self.update_freq_entry)
        if hasattr(self._freq_entry, 'set_tooltip_text'):
            self._freq_entry.set_tooltip_text(
                _('Enter a frequency to display.'))
        self._freq_entry.set_width_chars(8)
        self._freq_entry.show()
        toolitem = gtk.ToolItem()
        toolitem.add(self._freq_entry)
        self.insert(toolitem, -1)
        toolitem.show()

        self._new_tuning_line = ToolButton('tuning-tools')
        self._new_tuning_line.show()
        self.insert(self._new_tuning_line, -1)
        self._new_tuning_line.set_tooltip(_('Show tuning line.'))
        self._new_tuning_line.connect('clicked', self.tuning_line_cb)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)

        self._harmonic = ToolButton('harmonics')
        self._harmonic.show()
        self.insert(self._harmonic, -1)
        self._harmonic.set_tooltip(_('Show harmonics.'))
        self._harmonic.connect('clicked', self.harmonic_cb)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = True
            self.insert(separator, -1)

        self._play_tone = ToolButton('media-playback-start')
        self._play_tone.show()
        self.insert(self._play_tone, -1)
        self._play_tone.set_tooltip(_('Play a note.'))
        self._play_tone.connect('clicked', self.play_cb)

        if self.activity.has_toolbarbox:
            separator = gtk.SeparatorToolItem()
            separator.props.draw = False
            separator.set_expand(True)
            self.insert(separator, -1)

        self.label = gtk.Label('')
        self.label.set_use_markup(True)
        self.label.show()
        toolitem = gtk.ToolItem()
        toolitem.add(self.label)
        self.insert(toolitem, -1)
        toolitem.show()

        self.show_all()

    def update_note(self, *args):
        ''' Calculate the frequency based on note combo '''
        if not hasattr(self, '_freq_entry'):  # Still setting up toolbar
            return
        i = self._notes_combo.get_active()
        freq = A0 * pow(TWELTHROOT2, i)
        self._updating_note = True
        self._freq_entry.set_text('%0.3f' % (freq))
        self.label.set_markup(
            SPAN % (style.COLOR_WHITE.get_html(),
                    note_octave(index_to_note(i), index_to_octave(i))))
        if self._show_tuning_line:
            self.activity.wave.tuning_line = freq
        return

    def update_tuning_control(self, *args):
        ''' Update note '''
        if not hasattr(self, '_freq_entry'):  # Still setting up toolbar?
            return
        instrument = self.instrument[self.instrument_combo.get_active()]
        if not instrument in INSTRUMENT_DICT:
            return
        if self.tuning[self._tuning_combo.get_active()] == _('All notes'):
            self._notes_combo.set_active(
                freq_index(INSTRUMENT_DICT[instrument][0]))
            self.activity.wave.instrument = instrument
            self.activity.wave.tuning_line = 0.0
            self._new_tuning_line.set_icon('tuning-tools')
            self._new_tuning_line.set_tooltip(_('Show tuning line.'))
            self._show_tuning_line = False
        else:
            freq = INSTRUMENT_DICT[instrument][self._tuning_combo.get_active()
                                               - 1]  # All notes is 0
            self._notes_combo.set_active(
                freq_index(INSTRUMENT_DICT[instrument][
                    self._tuning_combo.get_active() - 1]))
            self.activity.wave.instrument = None
            self.activity.wave.tuning_line = freq
            self._new_tuning_line.set_icon('tuning-tools-off')
            self._new_tuning_line.set_tooltip(_('Hide tuning line.'))
            self._show_tuning_line = True
        self._updating_note = False

    def update_freq_entry(self, *args):
        # Calcualte a note from a frequency
        if not self._updating_note:  # Only if user types in a freq.
            try:
                freq = float(self._freq_entry.get_text())
                # Only consider notes in piano range
                if freq < A0 * 0.97:
                    self.label.set_text('< A0')
                    return
                if freq > C8 * 1.03:
                    self.label.set_text('> C8')
                    return
                self.label.set_markup(freq_note(freq, flatsharp=True))
            except ValueError:
                return
        self._updating_note = False

    def update_instrument_control(self, *args):
        ''' Callback for instrument control '''
        instrument = self.instrument[self.instrument_combo.get_active()]
        if self._tuning_tool is not None:
            self.remove(self._tuning_tool)
        if instrument == _('None'):
            self.activity.wave.instrument = None
            if hasattr(self, '_notes_tool'):
                self.insert(self._notes_tool, 2)
            return
        self.remove(self._notes_tool)
        self.activity.wave.instrument = instrument
        # If we are not already in freq. base, switch.
        if not self.activity.wave.get_fft_mode():
            self.activity.timefreq_control()
        # Add a Tuning Combo box for this instrument
        self._tuning_combo = ComboBox()
        self.tuning = [_('All notes')]
        for f in INSTRUMENT_DICT[instrument]:
            self.tuning.append(freq_note(f))
        self._tuning_changed_id = self._tuning_combo.connect(
            'changed', self.update_tuning_control)
        for i, s in enumerate(self.tuning):
            self._tuning_combo.append_item(i, s, None)
        self._tuning_combo.set_active(0)
        if hasattr(self._tuning_combo, 'set_tooltip_text'):
            self._tuning_combo.set_tooltip_text(instrument)
        self._tuning_tool = ToolComboBox(self._tuning_combo)
        self.insert(self._tuning_tool, 1)
        self._tuning_combo.show()
        self._tuning_tool.show()
        self.show_all()

    def harmonic_cb(self, *args):
        ''' Callback for harmonics control '''
        self.activity.wave.harmonics = not self.activity.wave.harmonics
        if self.activity.wave.harmonics:
            self._harmonic.set_icon('harmonics-off')
            self._harmonic.set_tooltip(_('Hide harmonics.'))
            if self.activity.wave.instrument is None and \
               self.activity.wave.tuning_line == 0.0:
                self._load_tuning_line()
        else:
            self._harmonic.set_icon('harmonics')
            self._harmonic.set_tooltip(_('Show harmonics.'))

    def tuning_line_cb(self, *args):
        ''' Callback for tuning insert '''
        if self._show_tuning_line:
            self.activity.wave.tuning_line = 0.0
            self._new_tuning_line.set_icon('tuning-tools')
            self._new_tuning_line.set_tooltip(_('Show tuning line.'))
            self._show_tuning_line = False
        else:
            self._load_tuning_line()

    def _load_tuning_line(self):
        ''' Read the freq entry and use value to set tuning line '''
        freq = self._freq_entry.get_text()
        try:
            self.activity.wave.tuning_line = float(freq)
            if freq < 0:
                freq = -freq
            self._new_tuning_line.set_icon('tuning-tools-off')
            self._new_tuning_line.set_tooltip(_('Hide tuning line.'))
            self._show_tuning_line = True
        except ValueError:
            self.activity.wave.tuning_line = 0.0
            self._freq_entry.set_text('0')
        # If we are not already in freq. base, switch.
        if not self.activity.wave.get_fft_mode():
            self.activity.timefreq_control()

    def play_cb(self, *args):
        ''' Save settings, turn off display, and then play a tone at
        the current frequency '''
        freq = float(self._freq_entry.get_text())
        channels = []
        for c in range(self.activity.audiograb.channels):
            channels.append(self.activity.wave.get_visibility(channel=c))
            self.activity.wave.set_visibility(False, channel=c)
        wave_status = self.activity.wave.get_active()
        self.activity.wave.set_context_off()
        self.activity.wave.set_active(False)
        gobject.timeout_add(200, self.play_sound, freq, channels, wave_status)

    def play_sound(self, freq, channels, wave_status):
        ''' Play the sound and then restore wave settings '''
        if hasattr(subprocess, 'check_output'):
            try:
                output = subprocess.check_output([
                    'speaker-test', '-t', 'sine', '-l', '1', '-f',
                    '%f' % (freq)
                ])
            except subprocess.CalledProcessError:
                log.warning('call to speaker-test failed?')
        else:
            import commands
            (status, output) = commands.getstatusoutput(
                'speaker-test -t sine -l 1 -f %f' % (freq))
            if status != 0:
                log.warning('call to speaker-test failed?')
        for c in range(self.activity.audiograb.channels):
            self.activity.wave.set_visibility(channels[c], channel=c)
        self.activity.wave.set_context_on()
        self.activity.wave.set_active(wave_status)
Exemplo n.º 10
0
class ButiaToolbar(gtk.Toolbar):
    ''' The toolbar for specifiying the sensor: temp, distance, 
    light or gray '''
    def __init__(self, activity, channels):

        #Se utiliza para contralar que no se ejecute dos veces
        self._butia_context_id = None

        gtk.Toolbar.__init__(self)
        self.activity = activity
        self._channels = channels

        self.mode = 'butia'

        # Set up Sensores Button
        self.time = RadioToolButton(group=None)

        # Mantiene la lista de botones (de sensores)
        # agregados a la ButiaToolbar
        self.lista_sensores_button = []

        self.we_are_logging = False
        self._log_this_sample = False
        self._logging_timer = None
        self._logging_counter = 0
        self._image_counter = 0
        self._logging_interval = 0
        self._channels_logged = []
        self._busy = False
        self._take_screenshot = True

        # BUTIA Se detectan sensores
        log.debug('se agrega el boton refrescar')
        self.refrescar_button = RadioToolButton(group=None)
        self.refrescar_button.set_named_icon('recargar')
        self.refrescar_button.connect('clicked', self.update_buttons)
        self.insert(self.refrescar_button, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = True
        self.insert(separator, -1)

        self.detect_sensors()
        self.load_buttons()

        separator = gtk.SeparatorToolItem()
        separator.props.draw = True
        self.insert(separator, -1)

        self._log_interval_combo = ComboBox()
        self.interval = [
            _('1/10 second'),
            _('1 second'),
            _('30 seconds'),
            _('5 minutes'),
            _('30 minutes')
        ]

        if hasattr(self._log_interval_combo, 'set_tooltip_text'):
            self._log_interval_combo.set_tooltip_text(_('Sampling interval'))

        self._interval_changed_id = self._log_interval_combo.connect(
            'changed', self.log_interval_cb)

        for i, s in enumerate(self.interval):
            self._log_interval_combo.append_item(i, s, None)
            if s == _('1 second'):
                self._log_interval_combo.set_active(i)

        self._log_interval_tool = ToolComboBox(self._log_interval_combo)
        self.insert(self._log_interval_tool, -1)
        self.logging_interval_status = '1 second'

        # Set up Logging/Stop Logging Button
        self._record = ToolButton('media-record')
        self.insert(self._record, -1)
        self._record.set_tooltip(_('Start Recording'))
        self._record.connect('clicked', self.record_control_cb)

        self.show_all()

# BUTIA Busca modulos conectados y pregunta si son sensores

    def detect_sensors(self):
        self.robot = butiaAPI.robot()
        log.debug('listando modulos detectados:')
        modules = self.robot.get_modules_list()
        self.sensores = []
        log.debug(modules)
        for i in range(len(modules)):
            if self.is_sensor(modules[i]):
                log.debug(modules[i] + ' es sensor!')
                self.sensores.append(modules[i])
            else:
                log.debug(modules[i] + ' no es sensor!')
        self.sensores.sort()
        log.debug('sensores: ')
        log.debug(self.sensores)

    # BUTIA determina si el modulo que le pasan es sensor! !
    def is_sensor(self, module):
        is_sensor = 0
        descripcion = 'A'
        #log.debug('DESCRIBIENDO: '+ module)
        descripcion = self.robot.doCommand('DESCRIBE ' + module)
        if descripcion == -1:
            return 0
        #log.debug(descripcion)
        is_sensor = descripcion.count(
            'returns={[1]') and module != 'display' and module != 'butia'
        return is_sensor

#BUTIA Cargo los botones para cada sensor detectado

    def load_buttons(self):
        self.lista_sensores_button = []
        for i in range(len(self.sensores)):
            self.sensor = self.sensores[i]
            log.debug('agregando boton para : ' + self.sensor)
            #radio_tool_button = 0
            radio_tool_button = RadioToolButton(group=self.time)
            icono = self.sensor.strip('0123456789:')
            radio_tool_button.set_named_icon(icono)
            radio_tool_button.set_tooltip(_(self.sensor))
            if self.sensor.count('temp'):
                #determino el numero de sensor y lo paso por parametro.
                #log.debug('el sensor  '+ self.sensor + 'es el numero '+ self.get_sensor_number(self.sensor) )
                radio_tool_button.connect('clicked', self.click_temp_button,
                                          self.get_sensor_number(self.sensor))
            elif self.sensor.count('dist'):
                #log.debug('el sensor  '+ self.sensor + 'es el numero '+ self.get_sensor_number(self.sensor) )
                radio_tool_button.connect('clicked', self.click_dist_button,
                                          self.get_sensor_number(self.sensor))
            elif self.sensor.count('grey'):
                #log.debug('el sensor  '+ self.sensor + 'es el numero '+ self.get_sensor_number(self.sensor) )
                radio_tool_button.connect('clicked', self.click_grises_button,
                                          self.get_sensor_number(self.sensor))
            elif self.sensor.count('light'):
                #log.debug('el sensor  '+ self.sensor + 'es el numero '+ self.get_sensor_number(self.sensor) )
                radio_tool_button.connect('clicked', self.click_luz_button,
                                          self.get_sensor_number(self.sensor))
            self.insert(radio_tool_button, 2)
            self.lista_sensores_button.append(radio_tool_button)

    def update_buttons(self, button=None):
        for s in self.lista_sensores_button:
            self.remove(s)

        self.detect_sensors()
        self.load_buttons()

        self.show_all()

    def get_sensor_number(self, sensor):
        number = 0
        sensor_trunked = sensor.strip('0123456789')
        number = sensor.strip(sensor_trunked)
        log.debug('sensor number :' + sensor.strip(sensor))
        return number

    # BUTIA metodos para leen sensores
    def read_temp_from_bobot_server(self, num=0):
        #log.debug('**********Sensando temperature' + str(num)+ '***********')
        value = 0
        value = self.robot.callModule('temp:' + str(num), 'getValue')
        #log.debug('temperature : ' + value)
        return value

    def read_dist_from_bobot_server(self, num=0):
        #log.debug('**********Sensando distance'+ str(num) + '******************')
        value = 0
        #value = self.robot.getDistance(num)
        value = self.robot.callModule('distanc:' + str(num), 'getValue')
        #log.debug('distance = ' + str(value))
        return value

    def read_grises_from_bobot_server(self, num=0):
        #log.debug('**********Sensando grises'+ str(num) + '******************')
        value = '0'
        value = self.robot.callModule('grey:' + str(num), 'getValue')
        #log.debug('grey = ' + str(value))
        return value

    def read_luz_from_bobot_server(self, num=0):
        #log.debug('**********Sensando luz '+ str(num) + '******************')
        value = '0'
        value = self.robot.callModule('ligth:' + str(num), 'getValue')
        #log.debug('grey = ' + str(value))
        return value

    def read_sensor_from_bobot_server(self, num):
        log.debug('**********Read Sensor ***********')
        return 0

    def click_button(self, button=None):
        log.debug('********** clicka botton ***********')
        self.set_butia_context()
        return False

    def click_temp_button(self, button=None, num='0'):
        log.debug('********** clickea botton temp ***********')
        self.mode = 'temperatura'
        self.read_sensor_from_bobot_server = self.read_temp_from_bobot_server
        self.set_butia_context(num)
        return False

    def click_dist_button(self, button=None, num='0'):
        log.debug('********** clickea botton dist ***********')
        self.mode = 'distancia'
        self.read_sensor_from_bobot_server = self.read_dist_from_bobot_server
        self.activity.limpiar_canales()
        self.set_butia_context(num)
        return False

    def click_grises_button(self, button=None, num='0'):
        log.debug('********** clickea botton grises ***********')
        self.mode = 'grises'
        self.read_sensor_from_bobot_server = self.read_grises_from_bobot_server
        self.activity.limpiar_canales()
        self.set_butia_context(num)
        return False

    def click_luz_button(self, button=None, num='0'):
        log.debug('********** clickea botton luz ***********')
        self.mode = 'luz'
        self.read_sensor_from_bobot_server = self.read_luz_from_bobot_server
        self.activity.limpiar_canales()
        self.set_butia_context(num)
        return False

    def set_butia_context(self, num='0'):
        self.activity.audiograb.stop_grabbing()
        if self._butia_context_id:
            gobject.source_remove(self._butia_context_id)
        self._butia_context_id =\
                  gobject.timeout_add(50,self.butia_context_on,num)

    def butia_context_on(self, num='0'):
        bufChannelTmp = []

        #Si esta el boton de pause activada no se agregar el nuevo valor
        if self.activity.audiograb.get_freeze_the_display():
            bufChannelTmp.append(self.read_sensor_from_bobot_server(num))
            for i in range(self.activity.audiograb.channels):
                self.activity.wave.new_buffer(bufChannelTmp, i)
                if self.we_are_logging:
                    self.logging_to_file(bufChannelTmp, i)

        if self.activity.CONTEXT == 'butia':
            return True
        else:
            return False

    def logging_to_file(self, data_buffer, channel):
        if self.we_are_logging:
            if self._logging_counter == MAX_LOG_ENTRIES:
                self._logging_counter = 0
                self.we_are_logging = False
                self.activity.data_logger.stop_session()
            else:
                if self._logging_interval == 0:
                    self._emit_for_logging(data_buffer, channel=channel)
                    self._log_this_sample = False
                    self.we_are_logging = False
                    self.activity.data_logger.stop_session()
                elif self._log_this_sample:
                    # Sample channels in order
                    if self.activity.audiograb._channels_logged.index(
                            False) == channel:
                        self.activity.audiograb._channels_logged[
                            channel] = True
                        self._emit_for_logging(data_buffer, channel=channel)
                        # Have we logged every channel?
                        if self.activity.audiograb._channels_logged.count(
                                True) == self.activity.audiograb.channels:
                            self._log_this_sample = False
                            for i in range(self.activity.audiograb.channels):
                                self.activity.audiograb._channels_logged[
                                    i] = False
                            self._logging_counter += 1

    def _emit_for_logging(self, data_buffer, channel=0):
        '''Sends the data for logging'''
        if not self._busy:
            self._busy = True
            if self._take_screenshot:
                if self.activity.data_logger.take_screenshot(
                        self._image_counter):
                    self._image_counter += 1
                else:
                    log.debug('failed to take screenshot %d' %
                              (self._logging_counter))
                self._busy = False
                return

            value_string = data_buffer[0]

            if self.activity.audiograb.channels > 1:
                self.activity.data_logger.write_value(
                    value_string,
                    channel=channel,
                    sample=self._logging_counter)
            else:
                self.activity.data_logger.write_value(
                    value_string, sample=self._logging_counter)
            self._busy = False
        else:
            log.debug('skipping sample %d.%d' %
                      (self._logging_counter, channel))

    def _sample_now(self):
        ''' Log the current sample now. This method is called from the
        _logging_timer object when the interval expires. '''
        self._log_this_sample = True
        self._make_timer()

    def _make_timer(self):
        ''' Create the next timer that will trigger data logging. '''
        self._logging_timer = Timer(self._logging_interval, self._sample_now)
        self._logging_timer.start()

    def record_control_cb(self, button=None):
        ''' Depending upon the selected interval, does either a logging
        session, or just logs the current buffer. '''
        if self.we_are_logging:
            self.set_logging_params(start_stop=False)
            self._record.set_icon('media-record')
            self._record.show()
            self._record.set_tooltip(_('Start Recording'))
        else:
            Xscale = 0.0
            Yscale = 0.0
            interval = self.interval_convert()
            username = self.activity.nick
            if self.activity.wave.get_fft_mode():
                self.activity.data_logger.start_new_session(
                    username,
                    Xscale,
                    Yscale,
                    _(self.logging_interval_status),
                    channels=self._channels,
                    mode='frequency')
            else:
                self.activity.data_logger.start_new_session(
                    username,
                    Xscale,
                    Yscale,
                    _(self.logging_interval_status),
                    channels=self._channels,
                    mode=self.mode)
            self.set_logging_params(start_stop=True,
                                    interval=interval,
                                    screenshot=False)
            self._record.set_icon('record-stop')
            self._record.show()
            self._record.set_tooltip(_('Stop Recording'))
            self.activity.new_recording = True

    def set_logging_params(self,
                           start_stop=False,
                           interval=0,
                           screenshot=True):
        ''' Configures for logging of data: starts or stops a session;
        sets the logging interval; and flags if screenshot is taken. '''
        self.we_are_logging = start_stop
        self._logging_interval = interval
        if not start_stop:
            if self._logging_timer:
                self._logging_timer.cancel()
                self._logging_timer = None
                self._log_this_sample = False
                self._logging_counter = 0
        elif interval != 0:
            self._make_timer()
        self._take_screenshot = screenshot
        self._busy = False

    def interval_convert(self):
        ''' Converts interval string to an integer that denotes the
        number of times the audiograb buffer must be called before a
        value is written.  When set to 0, the whole of current buffer
        will be written. '''
        interval_dictionary = {
            '1/10 second': 0.1,
            '1 second': 1,
            '30 seconds': 30,
            '5 minutes': 300,
            '30 minutes': 1800
        }
        try:
            return interval_dictionary[self.logging_interval_status]
        except ValueError:
            logging.error('logging interval status = %s' %\
                              (str(self.logging_interval_status)))
            return 0

    def log_interval_cb(self, combobox):
        ''' Callback from the Logging Interval Combo box: sets status '''
        if self._log_interval_combo.get_active() != -1:
            intervals = [
                '1/10 second', '1 second', '30 seconds', '5 minutes',
                '30 minutes'
            ]
            self.logging_interval_status = \
                              intervals[self._log_interval_combo.get_active()]

    def take_screenshot(self):
        ''' Capture the current screen to the Journal '''
        log.debug('taking a screenshot %d' % (self._logging_counter))
        self.set_logging_params(start_stop=True, interval=0, screenshot=True)