/**
 * File:
 *   volume.ycp
 *
 * Module:
 *   Sound
 *
 * Summary:
 *   Module where an attemp of inserting module is provided,
 *   if everything goes well adjusting volume is done here
 *   otherwise error message is displayed
 *
 * Authors:
 *   Dan Vesely <dan@suse.cz>
 *   Dan Meszaros <dmeszar@suse.cz>
 *
 *
 * $Id: volume.ycp 22634 2005-03-16 16:09:33Z lslezak $
 *
 * Steps:
 *        1. try to insert kernel module
 *        2. on succes unmute and volume dialog
 *        3. on fail display error message
 */

{

    textdomain "sound";
    import "Wizard";
    import "Popup";
    import "Label";
    import "Mode";
    import "Report";

    import "Sound";

    include "sound/joy_dialog.ycp";
    include "sound/volume_routines.ycp"; // PlayTest, setVolume
    include "sound/routines.ycp"; // FontsInstalled, HasFonts, InstallFonts

    /**
     *	UI controls for volume setting dialog
     *
     *  @param save_entry map with card info
     *  @param vol initial volume (0-100)
     *  @return term volume dialog contents
     */
    define term VolumeCon (map save_entry , integer vol) ``{

	term slider = `IntField(`id(`volume), `opt(`notify),
	    // volume slider label
	    _("&Volume"), 0, 100, vol);

	if (UI::HasSpecialWidget(`Slider))
	{
	    slider = `Slider (`id(`volume), `opt(`notify),
		// volume slider label
		_("&Volume"), 0, 100, vol);
	}

	term con = `HBox (
	    `HSpacing (3),
	    `VBox (
		`VSpacing (),
		`Top (`VBox(
		    // dialog title
		    `Left(`Label(_("Settings for sound card"))),
		    `Label (`opt(`outputField), save_entry["model"]:"")
		)),
		// frame label
		`Frame(_("Volume adjust and test"), `HBox(
		    `HSpacing (),
		    `VBox (
			`VSpacing (0.5),
			slider,
			`VSpacing (),
			// Test - button label
			`PushButton (`id (`test), `opt(`key_F6), _("&Test")),
			`VSpacing (0.5),
			// message label
			`Label(_("Press 'Test' to start playing sound sample")),
			`VSpacing (0.5)
		    ),
		    `HSpacing ()
		)),
		`VStretch ()
	    ),
	    `HSpacing (3)
	);
	return con;
    }

    /**
     * This dialog simply reads user input and calls apropriate set funtion
     *
     * @param finish show 'finish' button instead of 'next'
     * @return symbol next dialog
     */
    define symbol VolumeDialog (map save_entry, boolean finish,
				       integer card_id) ``{

	string help_text	= Sound::STRINGS["VolumeDialog"]:"";
	integer vol		= 50;
	term con		= VolumeCon(save_entry, vol);

	// dialog title
	Wizard::SetContents (_("Sound card volume"), con, help_text, true,true);

	if (Mode::config())
	{
	    UI::ChangeWidget(`id(`test), `Enabled, false);
	}

	if (finish)
	{
	    Wizard::SetNextButton(`next, Label::FinishButton() );
	}

	if (HasFonts(save_entry) && !FontsInstalled())
	{
	    /* Sound fonts installation */
	    InstallFonts("", false);
	}

	string modname = save_entry["module"]:"snd-dummy";
	string master_elem = Sound::db_modules[modname, "main_volume"]:"Master";
        setVolume (master_elem, card_id, vol);
	// some cards use Headphone instead of Master (bug #26539):
	setVolume ("Headphone", card_id, vol);
	// some systems have only one speaker (#46555)
	setVolume ("Master Mono", card_id, vol);
	// some systems use Front (#72971)
	setVolume ("Front", card_id, vol);

	symbol ui = nil;
	do
	{
	    ui = (symbol) UI::UserInput ();

	    if (ui == `volume)
	    {
		vol = (integer) UI::QueryWidget(`id(`volume), `Value );
		setVolume (master_elem, card_id, vol);
		setVolume ("Headphone", card_id, vol);
		setVolume ("Master Mono", card_id, vol);
		setVolume ("Front", card_id, vol);
	    }
	    else if (ui == `test)
	    {
		if (!Mode::test())
		{
		    string msg = PlayTest(card_id);
		    if (msg != "")
		    {
			Popup::Message (msg);
		    }
		}
	    }
	    else if (ui == `next && Sound::conf_joystick)
	    {
		symbol ret = joy_dialog(card_id, `next);
		if (ret == `back)
		{
		    con = VolumeCon(save_entry, vol);
		    // dialog header
		    Wizard::SetContents (_("Sound card volume"), con,
			help_text, true, true);
		    continue;
		}
		else
		{
		    ui = ret;
		    break;
		}
	    }
	    else if (ui == `abort || ui == `cancel)
	    {
		if (ReallyAbort())
		{
		    ui = `abort;
		    break;
		}
	    }
	} while (!contains([`back, `next, `cancel, `joystick], ui));
	return ui;
    }

    /**
     * shows error message in wizard
     * @param save_entry card config
     * @param err error string to be shown
     * @param finish show 'finish' button instead of 'next'
     * @return symbol `back | `cancel
     */
    define symbol ErrorDialog (map save_entry, string err, boolean finish) ``{

	y2debug("%1", save_entry);

	if (!Sound::use_ui) // used by cmd-line handlers
	{
	    Report::Error (err);
	    return `back;
	}
	string help_text	= Sound::STRINGS["ErrorDialog"]:"";
	string additional	= "";

	if (save_entry["module"]:"" == "snd-cs461x")
	{
	    // error message
	    additional = "\n\n" + _("Please try to configure this sound card manually 
using the \"Cirrus Logic CS4232\" or \"Cirrus 
Logic CS4236\" driver and configure 
its parameters using the 'Advanced setup'.");
	}

	term con = `HVCenter (
	    `VBox (
		// error message
		`Label (_("An error occured during the installation of")),
		`VSpacing (),
		`Label (`opt(`outputField), save_entry["model"]:""),
		`VSpacing (),
		`Label (err + additional)
	    )
	);

	// dialog title
	Wizard::SetContents (Label::ErrorMsg(), con, help_text, true, false);
	if (finish)
	{
	    Wizard::SetNextButton(`next, Label::FinishButton() );
	}

	UI::SetFocus(`id(`back));

	symbol ui = nil;
	repeat
	{
	    ui =  (symbol)UI::UserInput ();
            if (ui == `cancel || ui == `abort)
            {
                if (ReallyAbort())
                {
                    return `abort;
                }
            }

	} until ((ui == `back) || ui == `cancel);

	return ui;
    }

/**
 * shows volume dialog for normal setup or success dialog for quick setup
 * in case of failure show error dialog with 'next' button disabled
 * @param save_entry card config
 * @param card_id id of currently donfigured card
 * @param finish show 'finish' button instead of 'next'
 * @param quick quick/normal config
 * @param save_info config of previuosly configured cards
 * @return map result and next dialog
 */
define map sound_volume (map save_entry, integer card_id, boolean finish,
				boolean quick, list save_info) ``{

    Sound::LoadDatabase (true);

    boolean need_restart	= true;
    string err_msg		= "";
    list<map> modules_conf_backup	= Sound::modules_conf;

    if (Sound::use_ui) Wizard::DisableAbortButton();

    if (Sound::use_ui)
    {
        stop_programs();
    }

    // create new (temporary) modules.conf
    list<map> new_save = [];
    if (card_id >= size(save_info))
    {
	new_save = (list<map>) add(save_info, save_entry);
    }
    else
    {
	integer pos = -1;
	new_save = maplist (map card, (list<map>) save_info, ``{
	    pos = pos + 1;
	    return (pos == card_id) ? save_entry : card;
	});
    }

    Sound::modules_conf = new_save;

    // now restart sound system with new (current) card
    if (!Mode::config() && !Mode::autoinst())
    {
	sound_stop();
	sound_start_tmp(true);
	err_msg = check_module(save_entry, card_id);
    }

    symbol ui = nil;

    if (size (err_msg) > 0)
    {
	ui = ErrorDialog (save_entry, err_msg, finish);
    }
    else
    {
	string modname = save_entry["module"]:"snd-dummy";

	if (!Mode::config() && !Mode::autoinst())
	{
	    Sound::InitMixer(card_id, modname);
	}
	if (!quick)
	{
	    while (true)
	    {
		ui = VolumeDialog (save_entry, finish, card_id);
		if (ui != `joystick)
		{
		    break;
		}
		symbol s = joy_dialog (card_id, `next);
		if (s == `abort || s == `cancel)
		{
		    ui = `abort;
		    break;
		}
	    }
	}
	else
	{
	    string master_elem = Sound::db_modules[modname, "main_volume"]:"Master";

	    setVolume (master_elem, card_id, Sound::default_volume);
	    setVolume ("Headphone", card_id, Sound::default_volume);
	    setVolume ("Front", card_id, Sound::default_volume);

	    map devs = Sound::db_modules[modname, "mixer"]:$[];
	    if (haskey (devs, "PCM"))
	    {
		setVolume ("PCM", card_id, Sound::default_volume);
	    }
	    if (haskey (devs, "Master Mono"))
	    {
		setVolume ("Master Mono", card_id, Sound::default_volume);
	    }

	    if (Sound::conf_joystick == true && Sound::use_ui)
	    {
		joy_dialog(card_id, `next);
	    }
	    ui = `next;
	}
	if (!Mode::config() && !Mode::autoinst())
	    storeVolume(card_id);
    }

    Sound::modules_conf = modules_conf_backup;

    if (ui == `back || ui == `cancel || ui == `abort)
    {
	if (!Mode::config() && !Mode::autoinst())
	{
	    sound_stop();
	    sound_start_tmp(true);
	}
    }
    else
    {
	// reset pointers to card table
	Sound::curr_driver = "";
	Sound::curr_vendor = "";
	Sound::curr_model = "";
    }

    if (!Mode::config() && !Mode::autoinst())
    {
	SCR::Execute(.audio.alsa.restore, 0 ,0);
	SCR::Execute(.target.bash, "/usr/bin/killall aplay 2> /dev/null", $[]);
    }
    if (Sound::use_ui)
    {
	Wizard::RestoreNextButton();
    }

    return $["ui" : ui, "return" : size (err_msg) == 0];
}

}//EOF
