File: singinterval.py

package info (click to toggle)
solfege 2.0.4-4
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,200 kB
  • ctags: 1,844
  • sloc: python: 12,160; xml: 5,458; ansic: 1,486; makefile: 562; sh: 233
file content (155 lines) | stat: -rw-r--r-- 7,087 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# GNU Solfege - eartraining for GNOME
# Copyright (C) 2000, 2001, 2002, 2003  Tom Cato Amundsen
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import gtk, gnome
import gu, widgets
import soundcard, mpd, mpd.musicdisplayer
import abstract, const
import statistics, statisticsviewer
import utils

class Teacher(abstract.MelodicIntervalTeacher):
    def __init__(self, exname, app):
        abstract.MelodicIntervalTeacher.__init__(self, exname, app)
        self._ignore_picky = 1
        self.m_statistics = statistics.IntervalStatistics(self)
    def get_question(self):
        s = self.m_tonika.get_octave_notename()
        last = self.m_tonika
        for i in self.m_question:
            n = mpd.Interval()
            n.set_from_int(i)
            last = last + n
            s = s + " " + last.get_octave_notename()
        return self.m_tonika, r"\staff{ \clef %s %s}" % (mpd.select_clef(s), s)
    def guessed_correct(self):
        if self.get_int('number_of_intervals=1') == 1:
            self.m_statistics.add_correct(self.m_question[0])
        self.q_status = const.QSTATUS_SOLVED
    def guessed_wrong(self):
        if self.get_int('number_of_intervals=1') == 1:
            self.m_statistics.add_wrong(self.m_question[0], None)
        # we set q_status to WRONG, just to trick the MelodicIntervalTeacher
        # .new_interval to do the work for us.
        self.q_status = const.QSTATUS_SOLVED
    def play_first_tone(self):
        if self.q_status == const.QSTATUS_NO:
            return
        assert self.m_question
        soundcard.play_note(self.get_int('config/preferred_instrument'),
                  4, 0, self.m_tonika.semitone_pitch(),
                  self.get_int('config/preferred_instrument_velocity'))
    def play_last_tone(self):
        if self.q_status == const.QSTATUS_NO:
            return
        assert self.m_question
        t = self.m_tonika
        for i in self.m_question:
            t = t + i
        soundcard.play_note(self.get_int('config/preferred_instrument'),
                  4, 0, t.semitone_pitch(),
                  self.get_int('config/preferred_instrument_velocity'))


class Gui(abstract.Gui):
    def __init__(self, teacher, window):
        abstract.Gui.__init__(self, teacher, window)
        ################
        # practise_box #
        ################
        self.g_score_displayer = mpd.musicdisplayer.MusicDisplayer(utils.play_tone)
        self.practise_box.pack_start(self.g_score_displayer)
        self.g_score_displayer.clear()
        b1 = gu.bHBox(self.practise_box, gtk.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(gtk.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(gtk.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(gtk.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(gtk.FALSE)
        self.practise_box.show_all()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        ##############
        # config_box #
        ##############
        self.g_mici = widgets.MultipleIntervalConfigWidget(self.m_exname)
        self.config_box.pack_start(self.g_mici, gtk.FALSE)
        self.config_box.show_all()
        ###############
        # statistics
        ###############
        self.setup_statisticsviewer(
           statisticsviewer.SingIntervalStatisticsViewer, _("Sing interval"))
    def _new_question(self):
        r = self.m_t.new_question(self.get_string('user/lowest_pitch'),
                                  self.get_string('user/highest_pitch'))
        if r == Teacher.OK:
            self.m_t.play_first_tone()
            q = self.m_t.get_question()
            fontsize = self.get_int('config/feta_font_size=20')
            self.g_score_displayer.display(q[1], fontsize)
            self.g_new_interval_wrong.set_sensitive(gtk.TRUE)
            self.g_repeat_tonika.set_sensitive(gtk.TRUE)
            self.g_play_answer.set_sensitive(gtk.TRUE)
            self.g_repeat_last_tone.set_sensitive(gtk.TRUE)
            self.g_new_interval_correct.grab_focus()
        elif r == Teacher.ERR_CONFIGURE:
            self.g_repeat_tonika.set_sensitive(gtk.FALSE)
            self.g_play_answer.set_sensitive(gtk.FALSE)
            self.g_repeat_last_tone.set_sensitive(gtk.FALSE)
            self.g_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):
        self.m_t.m_statistics.reset_session()
        self.g_new_interval.grab_focus()
    def on_end_practise(self):
        self.g_new_interval.show()
        self.g_new_interval_correct.hide()
        self.g_new_interval_wrong.hide()
        self.g_repeat_tonika.set_sensitive(gtk.FALSE)
        self.g_play_answer.set_sensitive(gtk.FALSE)
        self.g_repeat_last_tone.set_sensitive(gtk.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 == const.QSTATUS_NEW:
            self.m_t.guessed_wrong()
        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 == const.QSTATUS_NEW:
            self.m_t.guessed_correct()
        r = self._new_question()
        if r == Teacher.OK:
            self.g_new_interval.hide()
            self.g_new_interval_correct.show()
            self.g_new_interval_wrong.show()