def __init__(self, teacher):
        abstract.IntervalGui.__init__(self, teacher)
        self.std_buttons_add(('give_up', self.give_up))
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                                                   self.g_config_grid, 0, 0)

        self.add_lock_to_key_gui(row=4)
        self._add_auto_new_question_gui(row=5)
        self._create_select_inputwidget_gui(row=6)
        self.g_config_grid.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Melodic interval"))
        self.select_inputwidget()

        def _f(watchvar):
            # The variables being watched by this function will change
            # when we switch lesson files or when we are in expert mode and
            # the user configures the exercise manually. We only have to run
            # end|start_exercise here in expert mode because it is called
            # automatically when we change lesson file.
            if self.m_t.m_custom_mode:
                self.on_end_practise()

        for i in range(self.get_int('maximum_number_of_intervals')):
            self.add_watch('ask_for_intervals_%i' % i, _f)
        self.add_watch('number_of_intervals', _f)
    def __init__(self, teacher):
        abstract.IntervalGui.__init__(self, teacher)
        self.std_buttons_add(('give_up', self.give_up))
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                self.g_config_grid, 0, 0)

        self.add_lock_to_key_gui(row=4)
        self._add_auto_new_question_gui(row=5)
        self._create_select_inputwidget_gui(row=6)
        self.g_config_grid.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Melodic interval"))
        self.select_inputwidget()

        def _f(watchvar):
            # The variables being watched by this function will change
            # when we switch lesson files or when we are in expert mode and
            # the user configures the exercise manually. We only have to run
            # end|start_exercise here in expert mode because it is called
            # automatically when we change lesson file.
            if self.m_t.m_custom_mode:
                self.on_end_practise()
        for i in range(self.get_int('maximum_number_of_intervals')):
            self.add_watch('ask_for_intervals_%i' % i, _f)
        self.add_watch('number_of_intervals', _f)
Exemple #3
0
 def __init__(self, teacher):
     abstract.Gui.__init__(self, teacher)
     ################
     # practise_box #
     ################
     self.g_score_displayer = mpd.MusicDisplayer()
     self.practise_box.pack_start(self.g_score_displayer, True, True, 0)
     self.g_score_displayer.clear()
     b1 = gu.bHBox(self.practise_box, False)
     self.g_new_interval_correct = gu.bButton(
         b1, _("_New interval,\nlast was correct"), self.new_question)
     self.g_new_interval_wrong = gu.bButton(
         b1, _("New interval,\nlast was _wrong"), self.new_last_was_wrong)
     self.g_new_interval = gu.bButton(b1, _("_New interval"),
                                      self.new_question)
     self.g_new_interval_wrong.set_sensitive(False)
     self.g_repeat_tonika = gu.bButton(
         self.action_area,
         _("_Repeat first tone"),
         lambda _o, self=self: self.m_t.play_first_tone())
     self.g_repeat_tonika.set_sensitive(False)
     self.g_play_answer = gu.bButton(
         self.action_area,
         _("_Play answer"),
         lambda _o, self=self: self.m_t.play_question())
     self.g_play_answer.set_sensitive(False)
     self.g_repeat_last_tone = gu.bButton(
         self.action_area,
         _("Play _last tone"),
         lambda _o, self=self: self.m_t.play_last_tone())
     self.g_repeat_last_tone.set_sensitive(False)
     self.practise_box.show_all()
     self.g_new_interval_correct.hide()
     self.g_new_interval_wrong.hide()
     ###############
     # config_grid #
     ###############
     self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                                                self.g_config_grid, 0, 0)
     ###############
     # statistics
     ###############
     self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                 _("Sing interval"))
 def __init__(self, teacher):
     abstract.Gui.__init__(self, teacher)
     ################
     # practise_box #
     ################
     self.g_score_displayer = mpd.musicdisplayer.MusicDisplayer()
     self.practise_box.pack_start(self.g_score_displayer)
     self.g_score_displayer.clear()
     b1 = gu.bHBox(self.practise_box, False)
     self.g_new_interval_correct = gu.bButton(b1,
             _("_New interval,\nlast was correct"), self.new_question)
     self.g_new_interval_wrong = gu.bButton(b1,
             _("New interval,\nlast was _wrong"), self.new_last_was_wrong)
     self.g_new_interval = gu.bButton(b1,
            _("_New interval"), self.new_question)
     self.g_new_interval_wrong.set_sensitive(False)
     self.g_repeat_tonika = gu.bButton(self.action_area,
                  _("_Repeat first tone"),
                  lambda _o, self=self: self.m_t.play_first_tone())
     self.g_repeat_tonika.set_sensitive(False)
     self.g_play_answer = gu.bButton(self.action_area,
                  _("_Play answer"),
                  lambda _o, self=self: self.m_t.play_question())
     self.g_play_answer.set_sensitive(False)
     self.g_repeat_last_tone = gu.bButton(self.action_area,
        _("Play _last tone"), lambda _o, self=self: self.m_t.play_last_tone())
     self.g_repeat_last_tone.set_sensitive(False)
     self.practise_box.show_all()
     self.g_new_interval_correct.hide()
     self.g_new_interval_wrong.hide()
     ##############
     # config_box #
     ##############
     self.g_mici = MultipleIntervalConfigWidget(self.m_exname)
     self.config_box.pack_start(self.g_mici, False)
     self.config_box.show_all()
     ###############
     # statistics
     ###############
     self.setup_statisticsviewer(
        statisticsviewer.PercentagesStatisticsViewer, _("Sing interval"))
Exemple #5
0
class Gui(abstract.Gui):
    lesson_heading = _("Sing the interval")

    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        ################
        # practise_box #
        ################
        self.g_score_displayer = mpd.MusicDisplayer()
        self.practise_box.pack_start(self.g_score_displayer, True, True, 0)
        self.g_score_displayer.clear()
        b1 = gu.bHBox(self.practise_box, False)
        self.g_new_interval_correct = gu.bButton(
            b1, _("_New interval,\nlast was correct"), self.new_question)
        self.g_new_interval_wrong = gu.bButton(
            b1, _("New interval,\nlast was _wrong"), self.new_last_was_wrong)
        self.g_new_interval = gu.bButton(b1, _("_New interval"),
                                         self.new_question)
        self.g_new_interval_wrong.set_sensitive(False)
        self.g_repeat_tonika = gu.bButton(
            self.action_area,
            _("_Repeat first tone"),
            lambda _o, self=self: self.m_t.play_first_tone())
        self.g_repeat_tonika.set_sensitive(False)
        self.g_play_answer = gu.bButton(
            self.action_area,
            _("_Play answer"),
            lambda _o, self=self: self.m_t.play_question())
        self.g_play_answer.set_sensitive(False)
        self.g_repeat_last_tone = gu.bButton(
            self.action_area,
            _("Play _last tone"),
            lambda _o, self=self: self.m_t.play_last_tone())
        self.g_repeat_last_tone.set_sensitive(False)
        self.practise_box.show_all()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                                                   self.g_config_grid, 0, 0)
        ###############
        # statistics
        ###############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Sing interval"))

    def _new_question(self):
        try:
            r = self.m_t.new_question(self.get_string('user/lowest_pitch'),
                                      self.get_string('user/highest_pitch'))
        except Teacher.ConfigureException as e:
            solfege.win.display_error_message2(
                _("Exercise configuration problem"), str(e))
            return
        if r == Teacher.OK:
            self.m_t.play_first_tone()
            self.g_score_displayer.display_score(self.m_t.get_question())
            self.g_new_interval_wrong.set_sensitive(True)
            self.g_repeat_tonika.set_sensitive(True)
            self.g_play_answer.set_sensitive(True)
            self.g_repeat_last_tone.set_sensitive(True)
            self.g_new_interval_correct.grab_focus()
        elif r == Teacher.ERR_CONFIGURE:
            self.g_repeat_tonika.set_sensitive(False)
            self.g_play_answer.set_sensitive(False)
            self.g_repeat_last_tone.set_sensitive(False)
            solfege.win.display_error_message(
                _("The exercise has to be better configured.\nClick 'Reset to default values' on the config\npage if you don't know how to do this."
                  ))
            self.g_score_displayer.clear()
        return r

    def on_start_practise(self):
        # First, we have to empty the cfg database because we will
        # copy the values from the lesson header.
        for i in range(self.get_int('maximum_number_of_intervals')):
            self.set_list('ask_for_intervals_%i' % i, [])
        # If ask_for_intervals_0 is not set, then we run in custom_mode
        # where the user configure the exercise on her own.
        if self.m_t.m_P.header.ask_for_intervals_0:
            for i in range(self.get_int('maximum_number_of_intervals')):
                if 'ask_for_intervals_%i' % i in self.m_t.m_P.header:
                    self.set_list(
                        'ask_for_intervals_%i' % i,
                        self.m_t.m_P.header['ask_for_intervals_%i' % i])
                else:
                    break
            self.set_int('number_of_intervals', i)
        # This exercise will be in expert mode when the lesson file
        # does not specify which questions to ask. It will ignore
        # the setting in the preferences window
        self.m_t.m_custom_mode = bool(
            not self.m_t.m_P.header.ask_for_intervals_0)
        super(Gui, self).on_start_practise()
        if self.m_t.m_custom_mode:
            self.g_mici.show()
        else:
            self.g_mici.hide()
            self.m_t.m_statistics.reset_session()
        self.g_statview.g_heading.set_text(
            "%s - %s" % (_("Sing interval"), self.m_t.m_P.header.title))
        self.handle_config_grid_visibility()
        self.g_new_interval.grab_focus()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()

    def on_end_practise(self):
        self.g_new_interval.show()
        self.g_repeat_tonika.set_sensitive(False)
        self.g_play_answer.set_sensitive(False)
        self.g_repeat_last_tone.set_sensitive(False)
        self.m_t.end_practise()
        self.g_score_displayer.clear()

    def new_last_was_wrong(self, widget=None):
        if self.m_t.q_status == self.QSTATUS_NEW:
            self.m_t.guessed_wrong()
            if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
                self.do_test_complete()
                return
        self._new_question()

    def new_question(self,
                     widget=None):  # called by 'new last was correct' and from
        # teacher when we get a new question automatically.
        if self.m_t.q_status == self.QSTATUS_NEW:
            self.m_t.guessed_correct()
            if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
                self.do_test_complete()
                return
        try:
            r = self._new_question()
        except Exception as e:
            if not self.standard_exception_handler(e):
                raise
            return
        if r == Teacher.OK:
            self.g_new_interval.hide()
            self.g_new_interval_correct.show()
            self.g_new_interval_wrong.show()

    def enter_test_mode(self):
        self.m_saved_q_auto = self.get_bool('new_question_automatically')
        self.m_saved_s_new = self.get_float('seconds_before_new_question')
        self.set_bool('new_question_automatically', True)
        self.set_float('seconds_before_new_question', 0.5)
        self.m_t.enter_test_mode()
        self.g_new_interval.set_label(_("_Start test"))
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        self.g_cancel_test.show()

    def exit_test_mode(self):
        self.set_bool('new_question_automatically', self.m_saved_q_auto)
        self.set_float('seconds_before_new_question', self.m_saved_s_new)
        self.m_t.exit_test_mode()
        self.g_new_interval.show()
        self.g_new_interval.set_label(_("_New interval"))
        self.g_new_interval_wrong.hide()
        self.g_new_interval_correct.hide()
Exemple #6
0
class Gui(abstract.Gui):
    lesson_heading = _("Sing the interval")

    def __init__(self, teacher):
        abstract.Gui.__init__(self, teacher)
        ################
        # practise_box #
        ################
        self.g_score_displayer = mpd.MusicDisplayer()
        self.practise_box.pack_start(self.g_score_displayer, True, True, 0)
        self.g_score_displayer.clear()
        b1 = gu.bHBox(self.practise_box, False)
        self.g_new_interval_correct = gu.bButton(b1,
                _("_New interval,\nlast was correct"), self.new_question)
        self.g_new_interval_wrong = gu.bButton(b1,
                _("New interval,\nlast was _wrong"), self.new_last_was_wrong)
        self.g_new_interval = gu.bButton(b1,
               _("_New interval"), self.new_question)
        self.g_new_interval_wrong.set_sensitive(False)
        self.g_repeat_tonika = gu.bButton(self.action_area,
                     _("_Repeat first tone"),
                     lambda _o, self=self: self.m_t.play_first_tone())
        self.g_repeat_tonika.set_sensitive(False)
        self.g_play_answer = gu.bButton(self.action_area,
                     _("_Play answer"),
                     lambda _o, self=self: self.m_t.play_question())
        self.g_play_answer.set_sensitive(False)
        self.g_repeat_last_tone = gu.bButton(self.action_area,
           _("Play _last tone"), lambda _o, self=self: self.m_t.play_last_tone())
        self.g_repeat_last_tone.set_sensitive(False)
        self.practise_box.show_all()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname, self.g_config_grid, 0, 0)
        ###############
        # statistics
        ###############
        self.setup_statisticsviewer(
           statisticsviewer.StatisticsViewer, _("Sing interval"))

    def _new_question(self):
        try:
            r = self.m_t.new_question(self.get_string('user/lowest_pitch'),
                                      self.get_string('user/highest_pitch'))
        except Teacher.ConfigureException as e:
            solfege.win.display_error_message2(_("Exercise configuration problem"), str(e))
            return
        if r == Teacher.OK:
            self.m_t.play_first_tone()
            self.g_score_displayer.display_score(self.m_t.get_question())
            self.g_new_interval_wrong.set_sensitive(True)
            self.g_repeat_tonika.set_sensitive(True)
            self.g_play_answer.set_sensitive(True)
            self.g_repeat_last_tone.set_sensitive(True)
            self.g_new_interval_correct.grab_focus()
        elif r == Teacher.ERR_CONFIGURE:
            self.g_repeat_tonika.set_sensitive(False)
            self.g_play_answer.set_sensitive(False)
            self.g_repeat_last_tone.set_sensitive(False)
            solfege.win.display_error_message(_("The exercise has to be better configured.\nClick 'Reset to default values' on the config\npage if you don't know how to do this."))
            self.g_score_displayer.clear()
        return r

    def on_start_practise(self):
        # First, we have to empty the cfg database because we will
        # copy the values from the lesson header.
        for i in range(self.get_int('maximum_number_of_intervals')):
            self.set_list('ask_for_intervals_%i' % i, [])
        # If ask_for_intervals_0 is not set, then we run in custom_mode
        # where the user configure the exercise on her own.
        if self.m_t.m_P.header.ask_for_intervals_0:
            for i in range(self.get_int('maximum_number_of_intervals')):
                if 'ask_for_intervals_%i' % i in self.m_t.m_P.header:
                    self.set_list('ask_for_intervals_%i' % i,
                      self.m_t.m_P.header['ask_for_intervals_%i' % i])
                else:
                    break
            self.set_int('number_of_intervals', i)
        # This exercise will be in expert mode when the lesson file
        # does not specify which questions to ask. It will ignore
        # the setting in the preferences window
        self.m_t.m_custom_mode = bool(
                      not self.m_t.m_P.header.ask_for_intervals_0)
        super(Gui, self).on_start_practise()
        if self.m_t.m_custom_mode:
            self.g_mici.show()
        else:
            self.g_mici.hide()
            self.m_t.m_statistics.reset_session()
        self.g_statview.g_heading.set_text("%s - %s" % (_("Sing interval"), self.m_t.m_P.header.title))
        self.handle_config_grid_visibility()
        self.g_new_interval.grab_focus()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()

    def on_end_practise(self):
        self.g_new_interval.show()
        self.g_repeat_tonika.set_sensitive(False)
        self.g_play_answer.set_sensitive(False)
        self.g_repeat_last_tone.set_sensitive(False)
        self.m_t.end_practise()
        self.g_score_displayer.clear()

    def new_last_was_wrong(self, widget=None):
        if self.m_t.q_status == self.QSTATUS_NEW:
            self.m_t.guessed_wrong()
            if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
                self.do_test_complete()
                return
        self._new_question()

    def new_question(self, widget=None):  # called by 'new last was correct' and from
                 # teacher when we get a new question automatically.
        if self.m_t.q_status == self.QSTATUS_NEW:
            self.m_t.guessed_correct()
            if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
                self.do_test_complete()
                return
        try:
            r = self._new_question()
        except Exception as e:
            if not self.standard_exception_handler(e):
                raise
            return
        if r == Teacher.OK:
            self.g_new_interval.hide()
            self.g_new_interval_correct.show()
            self.g_new_interval_wrong.show()

    def enter_test_mode(self):
        self.m_saved_q_auto = self.get_bool('new_question_automatically')
        self.m_saved_s_new = self.get_float('seconds_before_new_question')
        self.set_bool('new_question_automatically', True)
        self.set_float('seconds_before_new_question', 0.5)
        self.m_t.enter_test_mode()
        self.g_new_interval.set_label(_("_Start test"))
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        self.g_cancel_test.show()

    def exit_test_mode(self):
        self.set_bool('new_question_automatically', self.m_saved_q_auto)
        self.set_float('seconds_before_new_question', self.m_saved_s_new)
        self.m_t.exit_test_mode()
        self.g_new_interval.show()
        self.g_new_interval.set_label(_("_New interval"))
        self.g_new_interval_wrong.hide()
        self.g_new_interval_correct.hide()
class Gui(abstract.IntervalGui):
    lesson_heading = _("Identify the interval")

    def __init__(self, teacher):
        abstract.IntervalGui.__init__(self, teacher)
        self.std_buttons_add(('give_up', self.give_up))
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                self.g_config_grid, 0, 0)

        self.add_lock_to_key_gui(row=4)
        self._add_auto_new_question_gui(row=5)
        self._create_select_inputwidget_gui(row=6)
        self.g_config_grid.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Melodic interval"))
        self.select_inputwidget()

        def _f(watchvar):
            # The variables being watched by this function will change
            # when we switch lesson files or when we are in expert mode and
            # the user configures the exercise manually. We only have to run
            # end|start_exercise here in expert mode because it is called
            # automatically when we change lesson file.
            if self.m_t.m_custom_mode:
                self.on_end_practise()
        for i in range(self.get_int('maximum_number_of_intervals')):
            self.add_watch('ask_for_intervals_%i' % i, _f)
        self.add_watch('number_of_intervals', _f)

    def give_up(self, _o=None):
        if self.m_t.q_status == self.QSTATUS_WRONG:
            if len(self.m_t.m_question) == 1:
                s = utils.int_to_intervalname(self.m_t.m_question[0], False, True)
            else:
                s = "+".join([utils.int_to_intervalname(q, True, True) for q in self.m_t.m_question])
            self.g_flashbar.push(s)
            self.m_t.give_up()
            self.std_buttons_give_up()
            self.g_input.mark_note(int(self.m_t.m_tonika + self.m_t.m_question[0]), 2)

    def get_interval_input_list(self):
        v = []
        for x in range(self.get_int('number_of_intervals')):
            for i in self.get_list('ask_for_intervals_%i' % x):
                if not (abs(i) in v):
                    v.append(abs(i))
        v.sort()
        return v

    def click_on_interval(self, mouse_button, interval, midi_int):
        """The key bindings are also directed here.
        """
        if mouse_button == 3 and not solfege.app.m_test_mode \
                and self.get_int('number_of_intervals') == 1:
            if not self.m_t.m_tonika:
                return
            i = mpd.Interval()
            if (not midi_int  # buttons interface does not set midi_int. And
                             # since it assumes all intervals go up, we have
                             # to check and set the direction.
                and self.m_t.m_question[0] < 0):
                i.set_from_int(-interval)
            else:
                i.set_from_int(interval)
            n = self.m_t.m_tonika + i
            track = utils.new_track()
            track.note(4, self.m_t.m_tonika.semitone_pitch())
            track.note(4, n.semitone_pitch())
            soundcard.synth.play_track(track)
            return
        if mouse_button not in (1, self.keyboard_accel):
            return
        if solfege.app.m_test_mode and self.m_t.q_status == self.QSTATUS_NO:
            self.g_flashbar.flash(_("Click 'Start test' to begin."))
            return
        if solfege.app.m_test_mode:
            self.g_new.hide()
        if self.m_t.q_status == self.QSTATUS_NO:
            self.g_flashbar.flash(_("Click 'New interval' to begin."))
            return
        if midi_int:
            # midi_int is only set when we use some of the instrument widgets,
            # not when we use the buttons interface.
            utils.play_note(4, midi_int)
        if self.m_t.q_status == self.QSTATUS_GIVE_UP:
            return
        if self.m_t.q_status == self.QSTATUS_SOLVED:
            self.g_flashbar.flash(_("You have already identified this interval"))
            return
        if not (mpd.interval.min_interval < interval <= mpd.interval.max_interval):
            self.g_flashbar.flash(_("Ignoring intervals greater than double octave."))
            self.g_input.forget_last_tone()
            return
        self.m_answer.append(interval)
        d = self.m_t.m_question[len(self.m_answer) - 1]
        md = d // d
        if self.g_input.know_directions():
            md = 1
        if not self.msg:
            self.msg = utils.int_to_intervalname(interval * md, 1, 1) + "+ ..."
        else:
            self.msg = self.msg[:-4]
            self.msg = self.msg + utils.int_to_intervalname(interval * md, 1, 1) + "+ ..."
        self.g_flashbar.push(self.msg)
        if len(self.m_answer) == self.m_number_of_intervals_in_question:
            if self.m_t.guess_answer(self.m_answer,
                                     self.g_input.know_directions()):
                self.g_flashbar.clear()
                self.g_flashbar.flash(_("Correct"))
                self.std_buttons_answer_correct()
            else:
                self.g_flashbar.clear()
                self.g_flashbar.flash(_("Wrong"))
                if self.get_bool("config/auto_repeat_question_if_wrong_answer"):
                    self.m_t.play_question()
                self.std_buttons_answer_wrong()
            self.m_answer = []
            self.g_input.set_first_note(self.m_t.m_tonika)
            self.msg = ""
        if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
            self.do_test_complete()
            return

    def new_question(self, _o=None):
        self.msg = ""
        self.m_number_of_intervals_in_question \
               = self.get_int('number_of_intervals')
        self.m_answer = []
        if hasattr(self.g_input, 'use_users_vocal_range'):
            low = self.get_string('user/lowest_pitch')
            high = self.get_string('user/highest_pitch')
        else:
            low = self.g_input.m_lowest_tone
            high = self.g_input.m_highest_tone
        try:
            ret = self.m_t.new_question(low, high)
        except Teacher.ConfigureException as e:
            self.g_flashbar.clear()
            solfege.win.display_error_message2(_("Exercise configuration problem"), str(e))
            self.g_repeat.set_sensitive(False)
        else:
            if ret == Teacher.ERR_PICKY:
               self.g_flashbar.flash(_("You have to solve this question first."))
            self.g_input.set_first_note(self.m_t.m_tonika)

            def exception_cleanup():
                self.m_t.end_practise()
                self.std_buttons_exception_cleanup()
            try:
                self.m_t.play_question()
            except Exception as e:
                if not self.standard_exception_handler(e, exception_cleanup):
                    raise
                return
            self.std_buttons_new_question()
            self.g_flashbar.clear()
            # inputwidget 0 is always the buttons.
            if self.get_int('inputwidget') == 0:
                self.g_input.grab_focus_first_sensitive_button()

    def on_start_practise(self):
        self.m_t.start_practise()
        super(Gui, self).on_start_practise()
        if self.m_t.m_custom_mode:
            self.g_mici.show()
        else:
            self.m_t.m_statistics.reset_session()
            self.g_mici.hide()
        self.g_statview.g_heading.set_text("%s - %s" % (_("Melodic interval"), self.m_t.m_P.header.title))
        self.std_buttons_start_practise()
        if solfege.app.m_test_mode:
            self.g_flashbar.delayed_flash(self.short_delay,
                _("Click 'Start test' to begin."))
        else:
            self.g_flashbar.delayed_flash(self.short_delay,
                _("Click 'New interval' to begin."))

    def on_end_practise(self):
        self.m_t.end_practise()
        self.std_buttons_end_practise()
        self.g_input.clear()
        self.g_flashbar.clear()

    def enter_test_mode(self):
        self.m_saved_q_auto = self.get_bool('new_question_automatically')
        self.m_saved_s_new = self.get_float('seconds_before_new_question')
        self.set_bool('new_question_automatically', True)
        self.set_float('seconds_before_new_question', 0.5)
        self.m_t.enter_test_mode()
        self.g_new.set_label(_("_Start test"))
        self.g_cancel_test.show()
        self.g_give_up.hide()

    def exit_test_mode(self):
        self.set_bool('new_question_automatically', self.m_saved_q_auto)
        self.set_float('seconds_before_new_question', self.m_saved_s_new)
        self.m_t.exit_test_mode()
        self.g_new.show()
        self.g_new.set_label(_("_New interval"))
        self.g_give_up.show()
class Gui(abstract.IntervalGui):
    lesson_heading = _("Identify the interval")

    def __init__(self, teacher):
        abstract.IntervalGui.__init__(self, teacher)
        self.std_buttons_add(('give_up', self.give_up))
        ###############
        # config_grid #
        ###############
        self.g_mici = MultipleIntervalConfigWidget(self.m_exname,
                                                   self.g_config_grid, 0, 0)

        self.add_lock_to_key_gui(row=4)
        self._add_auto_new_question_gui(row=5)
        self._create_select_inputwidget_gui(row=6)
        self.g_config_grid.show_all()
        ##############
        # statistics #
        ##############
        self.setup_statisticsviewer(statisticsviewer.StatisticsViewer,
                                    _("Melodic interval"))
        self.select_inputwidget()

        def _f(watchvar):
            # The variables being watched by this function will change
            # when we switch lesson files or when we are in expert mode and
            # the user configures the exercise manually. We only have to run
            # end|start_exercise here in expert mode because it is called
            # automatically when we change lesson file.
            if self.m_t.m_custom_mode:
                self.on_end_practise()

        for i in range(self.get_int('maximum_number_of_intervals')):
            self.add_watch('ask_for_intervals_%i' % i, _f)
        self.add_watch('number_of_intervals', _f)

    def give_up(self, _o=None):
        if self.m_t.q_status == self.QSTATUS_WRONG:
            if len(self.m_t.m_question) == 1:
                s = utils.int_to_intervalname(self.m_t.m_question[0], False,
                                              True)
            else:
                s = "+".join([
                    utils.int_to_intervalname(q, True, True)
                    for q in self.m_t.m_question
                ])
            self.g_flashbar.push(s)
            self.m_t.give_up()
            self.std_buttons_give_up()
            self.g_input.mark_note(
                int(self.m_t.m_tonika + self.m_t.m_question[0]), 2)

    def get_interval_input_list(self):
        v = []
        for x in range(self.get_int('number_of_intervals')):
            for i in self.get_list('ask_for_intervals_%i' % x):
                if not (abs(i) in v):
                    v.append(abs(i))
        v.sort()
        return v

    def click_on_interval(self, mouse_button, interval, midi_int):
        """The key bindings are also directed here.
        """
        if mouse_button == 3 and not solfege.app.m_test_mode \
                and self.get_int('number_of_intervals') == 1:
            if not self.m_t.m_tonika:
                return
            i = mpd.Interval()
            if (not midi_int  # buttons interface does not set midi_int. And
                    # since it assumes all intervals go up, we have
                    # to check and set the direction.
                    and self.m_t.m_question[0] < 0):
                i.set_from_int(-interval)
            else:
                i.set_from_int(interval)
            n = self.m_t.m_tonika + i
            track = utils.new_track()
            track.note(4, self.m_t.m_tonika.semitone_pitch())
            track.note(4, n.semitone_pitch())
            soundcard.synth.play_track(track)
            return
        if mouse_button not in (1, self.keyboard_accel):
            return
        if solfege.app.m_test_mode and self.m_t.q_status == self.QSTATUS_NO:
            self.g_flashbar.flash(_("Click 'Start test' to begin."))
            return
        if solfege.app.m_test_mode:
            self.g_new.hide()
        if self.m_t.q_status == self.QSTATUS_NO:
            self.g_flashbar.flash(_("Click 'New interval' to begin."))
            return
        if midi_int:
            # midi_int is only set when we use some of the instrument widgets,
            # not when we use the buttons interface.
            utils.play_note(4, midi_int)
        if self.m_t.q_status == self.QSTATUS_GIVE_UP:
            return
        if self.m_t.q_status == self.QSTATUS_SOLVED:
            self.g_flashbar.flash(
                _("You have already identified this interval"))
            return
        if not (mpd.interval.min_interval < interval <=
                mpd.interval.max_interval):
            self.g_flashbar.flash(
                _("Ignoring intervals greater than double octave."))
            self.g_input.forget_last_tone()
            return
        self.m_answer.append(interval)
        d = self.m_t.m_question[len(self.m_answer) - 1]
        md = d // d
        if self.g_input.know_directions():
            md = 1
        if not self.msg:
            self.msg = utils.int_to_intervalname(interval * md, 1, 1) + "+ ..."
        else:
            self.msg = self.msg[:-4]
            self.msg = self.msg + utils.int_to_intervalname(
                interval * md, 1, 1) + "+ ..."
        self.g_flashbar.push(self.msg)
        if len(self.m_answer) == self.m_number_of_intervals_in_question:
            if self.m_t.guess_answer(self.m_answer,
                                     self.g_input.know_directions()):
                self.g_flashbar.clear()
                self.g_flashbar.flash(_("Correct"))
                self.std_buttons_answer_correct()
            else:
                self.g_flashbar.clear()
                self.g_flashbar.flash(_("Wrong"))
                if self.get_bool(
                        "config/auto_repeat_question_if_wrong_answer"):
                    self.m_t.play_question()
                self.std_buttons_answer_wrong()
            self.m_answer = []
            self.g_input.set_first_note(self.m_t.m_tonika)
            self.msg = ""
        if solfege.app.m_test_mode and self.m_t.m_P.is_test_complete():
            self.do_test_complete()
            return

    def new_question(self, _o=None):
        self.msg = ""
        self.m_number_of_intervals_in_question \
               = self.get_int('number_of_intervals')
        self.m_answer = []
        if hasattr(self.g_input, 'use_users_vocal_range'):
            low = self.get_string('user/lowest_pitch')
            high = self.get_string('user/highest_pitch')
        else:
            low = self.g_input.m_lowest_tone
            high = self.g_input.m_highest_tone
        try:
            ret = self.m_t.new_question(low, high)
        except Teacher.ConfigureException as e:
            self.g_flashbar.clear()
            solfege.win.display_error_message2(
                _("Exercise configuration problem"), str(e))
            self.g_repeat.set_sensitive(False)
        else:
            if ret == Teacher.ERR_PICKY:
                self.g_flashbar.flash(
                    _("You have to solve this question first."))
            self.g_input.set_first_note(self.m_t.m_tonika)

            def exception_cleanup():
                self.m_t.end_practise()
                self.std_buttons_exception_cleanup()

            try:
                self.m_t.play_question()
            except Exception as e:
                if not self.standard_exception_handler(e, exception_cleanup):
                    raise
                return
            self.std_buttons_new_question()
            self.g_flashbar.clear()
            # inputwidget 0 is always the buttons.
            if self.get_int('inputwidget') == 0:
                self.g_input.grab_focus_first_sensitive_button()

    def on_start_practise(self):
        self.m_t.start_practise()
        super(Gui, self).on_start_practise()
        if self.m_t.m_custom_mode:
            self.g_mici.show()
        else:
            self.m_t.m_statistics.reset_session()
            self.g_mici.hide()
        self.g_statview.g_heading.set_text(
            "%s - %s" % (_("Melodic interval"), self.m_t.m_P.header.title))
        self.std_buttons_start_practise()
        if solfege.app.m_test_mode:
            self.g_flashbar.delayed_flash(self.short_delay,
                                          _("Click 'Start test' to begin."))
        else:
            self.g_flashbar.delayed_flash(self.short_delay,
                                          _("Click 'New interval' to begin."))

    def on_end_practise(self):
        self.m_t.end_practise()
        self.std_buttons_end_practise()
        self.g_input.clear()
        self.g_flashbar.clear()

    def enter_test_mode(self):
        self.m_saved_q_auto = self.get_bool('new_question_automatically')
        self.m_saved_s_new = self.get_float('seconds_before_new_question')
        self.set_bool('new_question_automatically', True)
        self.set_float('seconds_before_new_question', 0.5)
        self.m_t.enter_test_mode()
        self.g_new.set_label(_("_Start test"))
        self.g_cancel_test.show()
        self.g_give_up.hide()

    def exit_test_mode(self):
        self.set_bool('new_question_automatically', self.m_saved_q_auto)
        self.set_float('seconds_before_new_question', self.m_saved_s_new)
        self.m_t.exit_test_mode()
        self.g_new.show()
        self.g_new.set_label(_("_New interval"))
        self.g_give_up.show()