# GNU Solfege - eartraining for GNOME
# Copyright (C) 2000, 2001, 2002  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 os

import gtk, gnome
import gu, widgets
import mpd, mpd.musicdisplayer
import abstract, const, lessonfile
from i18n import _
from soundcard.rat import Rat
import soundcard
import utils
import configureoutput

class Teacher(abstract.LessonbasedTeacher):
    def __init__(self, exname, app):
        abstract.LessonbasedTeacher.__init__(self, exname, app, const.USE_DICTATION)
        self.lessonfileclass = lessonfile.DictationLessonfile
        self.parse_lessonfile()
        #to please abstract.LessonParser
        self.q_status = const.QSTATUS_NEW
    def parse_lessonfile(self):
        abstract.LessonbasedTeacher.parse_lessonfile(self)

class Gui(abstract.LessonbasedGui):
    def __init__(self, teacher, window):
        abstract.LessonbasedGui.__init__(self, teacher, window)
        self.m_key_bindings = {'play_ak': self.play,
                               'show_ak': self.show_answer}
        ################
        # practise_box #
        ################
        self.g_question_title = gu.bLabel(self.practise_box, "")

        self.g_music_displayer = mpd.musicdisplayer.MusicDisplayer(utils.play_tone)
        self.g_music_displayer.set_usize(-1, 150)
        self.g_music_displayer.show()
        self.practise_box.pack_start(self.g_music_displayer)
        ###############
        # action_area #
        ###############
        self.g_partbox = gu.bHBox(self.practise_box, gtk.FALSE)
        b = gnome.ui.GnomeStockButton("Back")
        b.connect('clicked', self.select_previous)
        b.show()
        if configureoutput.WITH_GNOME:
            b.children()[0].children()[0].children()[1].hide()
        self.action_area.pack_start(b, gtk.FALSE)
        b = gnome.ui.GnomeStockButton("Forward")
        b.show()
        b.connect('clicked', self.select_next)
        if configureoutput.WITH_GNOME:
            b.children()[0].children()[0].children()[1].hide()
        self.action_area.pack_start(b, gtk.FALSE)
        self.g_play = gu.bButton(self.action_area, _("Play the whole music"),
                                 self.play)
        self.g_show = gu.bButton(self.action_area, _("Show"), self.show_answer)
        ##############
        # config_box #
        ##############
        self.g_lessonfile_selector = widgets.SelectLessonfileWidget(
              self.m_t, self.g_win, self.update_gui_after_lessonfile_change)
        self.g_lessonfile_selector.show()
        self.config_box.pack_start(self.g_lessonfile_selector)
        self.update_gui_after_lessonfile_change()
    def select_previous(self, widget):
        self.m_t.m_P.select_previous()
        self.display_start_of_music()
        self._update()
    def select_next(self, widget):
        self.m_t.m_P.select_next()
        self.display_start_of_music()
        self._update()
    def play(self, widget=None):
        self.m_t.play_question()
    def on_end_practise(self):
        self.update_gui_after_lessonfile_change()
    def show_answer(self, widget=None):
        if self.m_t.m_P:
            self.g_music_displayer.display(self.m_t.m_P.get_music(),
                            self.get_int('config/feta_font_size=20'))
    def _update(self):
        """
        Updates the buttons above the action_area where you have
        one or more buttons with a small note pixmap on. Each of the
        buttons will play one part of the music in the question.
        """
        self.g_question_title.set_text(self.m_t.m_P.get_name())
        # tmp func used as callback function
        def f(w, start, end, self=self):
            track = mpd.music_to_track(self.m_t.m_P.get_music(),
                       self.get_int('config/preferred_instrument_velocity'),
                       start, end)
            apply(track.prepend_bpm, self.m_t.m_P.get_tempo())
            track.prepend_patch(0, self.get_int('config/preferred_instrument'))
            soundcard.synth.play_track(track)
        self.g_partbox.foreach(lambda o: o.destroy())
        # if the user selects a collection without lessonfiles, or if
        # the lessonfile was invalid, m_P could be None
        if self.m_t.m_P:
            v = self.m_t.m_P.get_breakpoints()
            if v == []:
                # we display one button that will play the whole music if
                # there are not breakpoints in the music
                btn = self.create_pixmap_button()
                btn.connect('clicked', f, None, None)
                btn.show()
                self.g_partbox.pack_start(btn)
                return
            tmp = [Rat(0, 1)] + v + [Rat(2**30, 1)]
            for i in range(len(tmp) - 1):
                btn = self.create_pixmap_button()
                btn.show()
                btn.connect('clicked', f, tmp[i], tmp[i+1])
                self.g_partbox.pack_start(btn)
    def display_start_of_music(self):
        fontsize = self.get_int('config/feta_font_size=20')
        try:
            if self.m_t.m_P.get_clue_music():
                self.g_music_displayer.display(self.m_t.m_P.get_clue_music(),
                                               fontsize)
            elif self.m_t.m_P.get_clue_end():
                self.g_music_displayer.display_range(self.m_t.m_P.get_music(),
                               fontsize, Rat(0, 1), self.m_t.m_P.get_clue_end())
            else:
                self.g_music_displayer.display(self.m_t.m_P.get_music(),
                                               fontsize, mpd.FIRST)
        except mpd.musicalpitch.InvalidNotenameException, n:
            gnome.ui.GnomeErrorDialog(
                    "In lessonfile '%s':\n Invalid notename: %s" % (
                    self.get_string('lessonfile'), n.m_notename) )
    def update_gui_after_lessonfile_change(self):
        self.m_t.q_status = const.QSTATUS_NEW
        if self.m_t.m_P:
            self.action_area.set_sensitive(gtk.TRUE)
            self.display_start_of_music()
        else:
            self.action_area.set_sensitive(gtk.FALSE)
            self.g_music_displayer.clear()
        self._update()
        self.g_win.set_title("Solfege - " + self.get_pretty_name())
    def create_pixmap_button(self):
        pix, mask = gtk.create_pixmap_from_xpm(self, None,
                os.path.join("xpm", "rhythm-c4.xpm"))
        pixmap = gtk.GtkPixmap(pix, mask)
        btn = gtk.GtkButton()
        btn.add(pixmap)
        pixmap.show()
        return btn

