#!/usr/bin/python
#
# Orca
#
# Copyright 2004-2006 Sun Microsystems Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library 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
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

"""Permits the user to set up preferences for orca using speech prompts
and a command line interface.
"""

import os, commands, sys, time
import pprint

import orca.settings

from orca.acss import ACSS
from orca.orca_i18n import _  # for gettext support

# Create the user's .orca directory
#
orcadir = os.path.join(os.environ["HOME"], ".orca")
try:
    os.chdir(orcadir)
except:
    print _("Creating .orca directory.")
    try:
        os.mkdir(orcadir)
    except:
        # [[[TODO: WDW - need to print a message and fail here.]]]
        #
        pass
        
# Create a new settings file
#
settingsFileName = os.path.join(orcadir, "user-settings.py")
settings = open(settingsFileName, "w")
settings.writelines("# user-settings.py - custom Orca settings\n")
settings.writelines("# Initially generated by orca-setup\n")
settings.writelines("\n")
settings.writelines("import re\n")
settings.writelines("\n")
settings.writelines("import orca.debug as debug\n")
settings.writelines("from orca.acss import ACSS\n")
settings.writelines("\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_OFF)\n")
settings.writelines("debug.setDebugLevel(debug.LEVEL_SEVERE)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_WARNING)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_INFO)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_CONFIGURATION)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_FINE)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_FINER)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_FINEST)\n")
settings.writelines("#debug.setDebugLevel(debug.LEVEL_ALL)\n")
settings.writelines("\n")
settings.writelines("#debug.setEventDebugLevel(debug.LEVEL_OFF)\n")
settings.writelines("#debug.setEventDebugFilter(None)\n")
settings.writelines("#debug.setEventDebugFilter(re.compile('[\S]*focus|[\S]*activ'))\n")
settings.writelines("#debug.setEventDebugFilter(re.compile('nomatch'))\n")
settings.writelines("#debug.setEventDebugFilter(re.compile('[\S]*:accessible-name'))\n")

settings.writelines("\n")
settings.writelines("#f = open('debug.out', 'w', 0)\n")
settings.writelines("#debug.setDebugFile(f)\n")
settings.writelines("\n")

# Speech setup
#
import orca.speech as speech
import orca.speechserver as speechserver

servers = []

def sayAndPrint(text, stop=False, getInput=False):
    """Prints the given text.  In addition, if the text field
    is not None, speaks the given text, optionally interrupting
    anything currently being spoken.
    
    Arguments:
    - text: the text to print and speak
    - stop: if True, interrupt any speech currently being spoken
    - getInput: if True, elicits raw input from the user and returns it

    Returns raw input from the user if getInput is True.
    """
    
    if stop:
	speech.stop()

    speech.speak(text)

    if getInput:
        return raw_input(text)
    else:
        print text        

def setupSpeech():
    """Sets up speech support.  If speech setup is successful and the
    user wants it, writes speech settings to the setting file and returns
    True.  If speech is not available, or the user doesn't want speech,
    returns False.
    """
    
    global servers

    # Use this because callbacks will often hang when not running
    # with bonobo main in use.
    #
    orca.settings.enableSpeechCallbacks = False

    factories = speech.getSpeechServerFactories()
    if len(factories) == 0:
        print _("Speech is unavailable.")
        return False

    speech.init()
    speech.speak(_("Welcome to Orca setup."))

    workingFactories = []
    for factory in factories:
        try:
	    infos = factory.SpeechServer.getSpeechServerInfos()
	    workingFactories.append([factory, infos])
	except:
	    pass

    if len(workingFactories) == 0:
        print _("Speech is unavailable.")
        return False
    elif len(workingFactories) > 1:    
        speech.speak(_("Select desired speech system."))
	choices = {}
	i = 1
        for workingFactory in workingFactories:
	    choices[i] = workingFactory
	    sayAndPrint(_("%d. %s") 
		        % (i, workingFactory[0].SpeechServer.getFactoryName()))
	    i += 1
	choice = int(sayAndPrint(_("Enter choice: "), False, True))
        if (choice <= 0) or (choice >= i):	
            sayAndPrint(_("Speech will not be used.\n"))
            return False
	[factory, infos] = choices[choice]
    else:
	[factory, infos] = workingFactories[0]

    for info in infos:
        try:
	    server = factory.SpeechServer.getSpeechServer(info)
	    if server:
	        servers.append(server)
        except:
            pass

    if len(servers) == 0:
        sayAndPrint(_("No servers available.\n"))
        sayAndPrint(_("Speech will not be used.\n"))
        return False
    if len(servers) > 1:
        speech.speak(_("Select desired speech server."))
	i = 1
	choices = {}
        for server in servers:
	    sayAndPrint(_("%d. %s") % (i, server.getInfo()[0]))
	    choices[i] = server
	    i += 1
	choice = int(sayAndPrint(_("Enter choice: "), False, True))
        if (choice <= 0) or (choice >= i):	
            sayAndPrint(_("Speech will not be used.\n"))
            return False
	server = choices[choice]
    else:
	server = servers[0]

    families = server.getVoiceFamilies()
    if len(families) == 0:
        sayAndPrint(_("No voices available.\n"))
        sayAndPrint(_("Speech will not be used.\n"))
        return False
    if len(families) > 1:
        speech.speak(_("Select desired voice."))
	i = 1
	choices = {}
        for family in families:
            name = family[speechserver.VoiceFamily.NAME]
            acss = ACSS({ACSS.FAMILY : family})
            sayAndPrint(_("%d. %s") % (i, name))
	    choices[i] = acss
	    i += 1
	choice = int(sayAndPrint(_("Enter choice: "), False, True))
        if (choice <= 0) or (choice >= i):	
            sayAndPrint(_("Speech will not be used.\n"))
            return False
	defaultACSS = choices[choice]
    else:
        defaultACSS = ACSS({ACSS.FAMILY : families[0]})

    uppercaseACSS = ACSS({ACSS.AVERAGE_PITCH : 6})
    hyperlinkACSS = ACSS({ACSS.AVERAGE_PITCH : 2})

    voices = {
	orca.settings.DEFAULT_VOICE   : defaultACSS,
	orca.settings.UPPERCASE_VOICE : uppercaseACSS,
	orca.settings.HYPERLINK_VOICE : hyperlinkACSS
    }

    settings.writelines(orca.settings.SPEECH_SERVER_FACTORY + " = '" \
			+ factory.__name__ + "'\n")
    settings.writelines(orca.settings.SPEECH_SERVER_INFO + " = " \
			+ repr(server.getInfo()) + "\n")

    settings.writelines(orca.settings.VOICES + " = {\n")
    for voice in voices:
	settings.writelines("     '%s' : ACSS(" % voice)
        settings.writelines(pprint.pformat(voices[voice]) + "),\n")
    settings.writelines("}\n\n")
	
    keyEcho = sayAndPrint(_("Use key echo?  Enter y or n: "), True, True)
    if keyEcho[0:1] == 'Y' or keyEcho[0:1] == 'y':
        settings.writelines(orca.settings.USE_KEY_ECHO + " = True\n")
    else:
        settings.writelines(orca.settings.USE_KEY_ECHO + " = False\n")

    settings.writelines(orca.settings.USE_SPEECH + " = True\n")
    return True

def setupBraille():
    """Sets up Braille support.  If Braille is available and the user
    wants it, returns True.  If Braille is unavailable or the user
    doesn't want it, returns False.
    """

    working = False
    try:
        import orca.braille as braille
        working = braille.init()
	braille.shutdown()
    except:
        pass

    if working:
        useBraille = sayAndPrint(
            _("Braille support appears to work, use it?  Enter y or n. "),
            False,
            True)

        if useBraille[0:1] == 'Y' or useBraille[0:1] == 'y':
            return True
        else:
            return False
    else:
        return False

def enableAccessibility():
    """Enables the GNOME accessibility flag.  Users need to log out and
    then back in for this to take effect."""

    alreadyEnabled = commands.getoutput(\
	"gconftool-2 --get /desktop/gnome/interface/accessibility")
    if alreadyEnabled != "true":
        os.system("gconftool-2 --type bool --set " \
		  + "/desktop/gnome/interface/accessibility true")

        sayAndPrint("Accessibility support for GNOME has been enabled.")
        sayAndPrint("You need to log out and log back in for the change "\
                    +"to take effect.")

useSpeech = setupSpeech()
if useSpeech == False:
    settings.writelines(orca.settings.USE_SPEECH + " = False\n")
    settings.writelines(orca.settings.USE_KEY_ECHO + " = False\n")

# We'll always enable braille for now.  Orca will recover gracefully
# if it cannot connect to BrlTTY.
#
settings.writelines(orca.settings.USE_BRAILLE + " = True\n")
    
#useBraille = setupBraille()
#if useBraille:
#    settings.writelines(orca.settings.USE_BRAILLE + " = True\n")
#else:
#    settings.writelines(orca.settings.USE_BRAILLE + " = False\n")



enableAccessibility()

sayAndPrint("Orca setup finished.\n", True)

for server in servers:
    server.shutdown()

speech.shutdown()
