# 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 __main__

from i18n import _

import configureoutput
import errno, sys
import shutil

import soundcard, mpd
import lessonfile
import os
import cfg, utils

class SolfegeApp(cfg.ConfigUtils):
    def __init__(self, argv, ui):
        cfg.ConfigUtils.__init__(self, 'solfege-app')
        self.m_argv = argv
        self.m_ui = ui
        self.check_rcfile()
        self.check_statistics()
        self.m_teachers = {}
        self.lessonfile_manager = lessonfile.LessonFileManager()
        self.setup_sound()
    def check_rcfile(self):
        # The [app] version variable say  the oldest rc version
        # this function can convert to a version this version of
        # Solfege can handle.
        #
        # First figure out what file to replace
        if sys.platform == "win32":
            fn = "~/solfegerc%s.%s"
        else:
            fn = "~/.solfegerc%s.%s"
        fn = fn % (configureoutput.MAJOR_VERSION,
                   configureoutput.MINOR_VERSION)
        if sys.platform == "win32":
            # FIXME this version number has to be updated in sync with
            # Makefile.in
            ver = "1.1.3"
        else:
            ver = "0.7.34"
        if utils.compare_version_strings(
                 cfg.get_string("app/version"), ver) == -1:
            if os.path.isfile("debian-solfege.py.in"):
                # we are running the program from the source dir
                # without installing. Also windows users go here.
                shutil.copyfile("default.config", os.path.expanduser(fn))
                #FIXME use cfg.*
                cfg.reread_data()
            else:
                cfg.drop_user_config()
        if __main__.rc_copied:
            # some checks if we have upgraded an old rcfile from 1.0.x
            # or 1.1.x 
            if cfg.get_string("id-tone/new_ak") == "":
                cfg.set_string("id-tone/new_ak", "<ctrl>n")
            if cfg.get_string("id-tone/give_up_ak") == "":
                cfg.set_string("id-tone/give_up_ak", "<ctrl>g")
            cfg.set_bool("gui/development_menu_visible", 0)
        cfg.set_string('app/version', configureoutput.VERSION_STRING)
    def check_statistics(self):
        # the devel series are fresh and no history to care about
        return
        if cfg.get_string("app/version") < "0.7.21":
            print "Deleting all your statistics because of compatibility issues."
            if os.path.exists(os.path.expanduser("~/.solfege/")):
                shutil.rmtree(os.path.expanduser("~/.solfege/"))
        elif cfg.get_string("app/version") < "0.7.33":
            print "Deleting the identify-scale statistics because there was one"
            print "of the keys to the statistics code was changed. Such nasty"
            print "changes will not happen in the stable 1.0.x series."
            if os.path.exists(os.path.expanduser("~/.solfege0.7/identify-scale")):
                shutil.rmtree(os.path.expanduser("~/.solfege0.7/identify-scale/"))
    def setup_sound(self):
        if sys.platform == 'win32' and \
                    cfg.get_string("sound/type") == "sequencer-device":
            # just in case c:\home\solfegercX.Y is wrong
            cfg.set_string("sound/type", "winsynth")
        if '--no-sound' in self.m_argv \
           or cfg.get_string("sound/type") == "fake-synth":
            soundcard.initialise_using_fake_synth('--verbose-sound-init' in self.m_argv)
        elif cfg.get_string("sound/type") == "winsynth":
            soundcard.initialise_winsynth(cfg.get_int("sound/synth_number"),
                      verbose_init='--verbose-sound-init' in self.m_argv)
        elif cfg.get_string("sound/type") == "external-midiplayer":
            soundcard.initialise_external_midiplayer(
                    cfg.get_string("sound/commandline"),
                    verbose_init='--verbose-sound-init' in self.m_argv)
        elif cfg.get_string("sound/type") == '':
            self.m_ui.display_error_message(
"""You should configure sound
from the 'Sound' page of
the preferences window.
""")
        elif cfg.get_string("sound/type") == "sequencer-device":
            if not configureoutput.HAVE_LINUX_AWE_VOICE_H and \
               cfg.get_string("sound/card_info") == "awe":
                       cfg.set_string("sound/card_info", "");
            try:
                soundcard.initialise_devicefile(
                             cfg.get_string("sound/device_file"),
                             cfg.get_int("sound/synth_number"),
                             cfg.get_string("sound/card_info"),
                             verbose_init='--verbose-sound-init' in self.m_argv)
            except (soundcard.SoundInitException, OSError), e:
                if e == None:
                    self.m_ui.display_error_message(
"""You should configure sound
from the 'Sound' page of
the preferences window.
""")
                else:
                    self.display_sound_init_error_message(e)
    def display_sound_init_error_message(self, e):
        if isinstance(e, soundcard.SoundInitException):
            self.m_ui.display_error_message(
            """%s""" % e)
        elif e.errno == errno.EACCES:
            self.m_ui.display_error_message(
"""The sound init failed: %s
The errno EACCES indicates that you don't have write
permission to the device.""" % e)
        elif e.errno == errno.EBUSY:
            self.m_ui.display_error_message(
"""The sound init failed: %s
It seems like some other program is using the device. You
should try to quit that other program and restart Solfege."""
 % e)
        else:
            self.m_ui.display_error_message(
"""The sound init failed: %s
It seems like your kernel don't have the correct
sound modules installed, or that they are wrongly
configured. You can check the 'Sound' page in the
preferences window, but I don't think anything there
can help you. (This program need better sound init
code to handle situations like this.)"""
 % errno.errorcode[e.errno])
    def play_happy_sound(self):
        mpd.play_music(r"\staff\relative c'{c16 e g a}", 180, 8,
               cfg.get_int('config/preferred_instrument_velocity'))
    def play_sad_sound(self):
        mpd.play_music(r"\staff\relative c'{<c,,8 cis>", 80, 58,
               cfg.get_int('config/preferred_instrument_velocity'))
    def please_help_me(self):
        if self.m_ui.m_viewer != 'docviewer':
            self.handle_href('%s-help.html' % self.m_ui.m_viewer)
    def handle_href(self, href):
        protocol, action, fn, lessoncollection, lessonfile, config = \
           utils.parse_url(href)
        if protocol == None:
            self.m_ui.display_docfile(fn)
        elif protocol == 'solfege':
            if action == 'all-lessonfiles':
                self.m_ui.display_html(self.lessonfile_manager.m_htmldoc)
                self.m_ui.m_history.add('solfege:all-lessonfiles')
            else:
                if not self.m_teachers.has_key(fn):
                    n = utils.exercise_name_to_module_name(fn)
                    exec("import %s" % n)
                    self.m_teachers[fn] = locals()[n].Teacher(fn, self)
                    # if we don't have a teacher, then the Gui has not been
                    # initialized either
                    self.m_ui.initialise_exercise(self.m_teachers[fn])
                    self.m_teachers[fn].g_view = self.m_ui.box_dict[fn]
                self.m_teachers[fn].configure_exercise(lessoncollection, lessonfile, config)
                self.m_ui.activate_exercise(href)
        elif protocol == 'http':
            os.system(self.get_string("config/web_browser") % href)
        elif protocol == 'mailto':
            os.system(self.get_string("config/mua") % href)
        else:
            print "unknown link type", protocol
    def quit_program(self):
        cfg.sync()
        for k in self.m_teachers.keys():
            if self.m_teachers[k].m_statistics is not None:
                self.m_teachers[k].m_statistics.save_data()
        if soundcard.synth:
            soundcard.synth.close()


