/* lirccrc sample 2
   This sample illustrates a more advanced usage of lirccd. It
   implements an music player, allowing the user to use his/her remote
   control to control mpg123/ogg123. I have used it myself with great
   success.
   It also has a scheduling mode, allowing the user to program a
   wake-up call.
 */

global edit = "", files = array();
global child = -1, curfile = 0;
global dieaction = 1;
global volume = 100;

function say(str)
{
    /* This line uses the Festival text-to-speech system. I highly
       recommend it. Note that \c is the escape sequence for double
       quotes, not \". */
    exec("echo \c" + str + "\c | text2wave | sox -t .wav - -t ossdsp /dev/dsp &");
}

function died(id)
{
    if(dieaction == 1)
    {
	if((++curfile) >= (int)files)
	    curfile = 0;
	restart(1);
    }
    if(dieaction == 2)
	restart(1);
    if(dieaction == 3)
    {
	curfile = rand((int)files);
	restart(1);
    }
}

function killcur()
{
    if(child >= 0)
    {
	if(running(child))
	    killchild(child);
	discardchild(child);
	child = -1;
    }
}

function restart(force)
{
    var running;
    
    if(child >= 0)
    {
	running = running(child);
	killcur();
    } else {
	running = 0;
    }
    if(running || force)
    {
	if(curfile < 0)
	{
	    curfile = ((int)files) - 1;
	    say("Negative song number");
	}
	if(curfile >= (int)files)
	{
	    curfile = 0;
	    say("Song number overflow");
	}
	ext = strend(files[curfile], strrchr(files[curfile], "."));
	if(ext == ".mp3")
	    child = execarray("mpg123", array("mpg123", "-o", "oss", "-q", files[curfile]));
	if(ext == ".MP3")
	    child = execarray("mpg123", array("mpg123", "-o", "oss", "-q", files[curfile]));
	if(ext == ".ogg")
	    child = execarray("ogg123", array("ogg123", "-d", "oss", "-q", files[curfile]));
	childnotify(child, "died");
    }
}

function init()
{
    dirs = expand(file(getenv("HOME") + "/.mp3/dirs"), "\n");
    for(i = 0; i < (int)dirs; i++)
    {
	files += glob(dirs[i] + "/*.mp3", 0);
	files += glob(dirs[i] + "/*.MP3", 0);
	files += glob(dirs[i] + "/*.ogg", 0);
    }
}

function volalarm(id)
{
    exec("aumix -v" + (string)(volume = 100));
}

function playalarm(id)
{
    restart(1);
}

function stopalarm(id)
{
    killcur();
}

bind recursively "[0-9]"
{
    edit += button;
    say(button);
}

bind recursively "Chan_Last" edit = "";

bind "Play"
{
    if(edit)
    {
	curfile = (int)edit;
	edit = "";
    } else if(dieaction == 3) {
	curfile = rand((int)files);
    }
    restart(1);
}

bind "Stop"
{
    if(child == -1)
	curfile = 0;
    else
	killcur();
}

bind "Rewind"
{
    if((--curfile) < 0)
	curfile = (int)files - 1;
    restart(0);
}

bind "FF"
{
    if((++curfile) >= (int)files)
	curfile = 0;
    restart(0);
}

bind "Redo"
{
    if((++dieaction) > 3)
	dieaction = 0;
    if(dieaction == 0)
	say("Stop");
    if(dieaction == 1)
	say("Continue");
    if(dieaction == 2)
	say("Repeat");
    if(dieaction == 3)
	say("Random");
}

bind "Vol\\+"
{
    if(volume += 5 > 100)
	volume = 100;
    exec("aumix -v" + (string)volume);
}

bind "Vol-"
{
    if(volume -= 5 < 0)
	volume = 0;
    exec("aumix -v" + (string)volume);
}

bind recursively "Preview" say(pipe("date +%H:%M:%S"));

bind "Next"
{
    say((string)curfile + " -- " + strend(files[curfile], strrchr(files[curfile], "/") + 1));
}

bind "^L$" subtree
{
    say("Scheduling mode");
    bind "Play"
    {
	hour = (int)edit / 100;
	min = (int)edit - (hour * 100);
	alarm(mktime(-1, -1, -1, hour, min, 0), "playalarm");
	say("Playback scheduled at " + (string)hour + ":" + (string)min);
	edit = "";
    }
    bind "Stop"
    {
	hour = (int)edit / 100;
	min = (int)edit - (hour * 100);
	alarm(mktime(-1, -1, -1, hour, min, 0), "stopalarm");
	say("Stop scheduled at " + (string)hour + ":" + (string)min);
	edit = "";
    }
    bind "Vol\\+"
    {
	hour = (int)edit / 100;
	min = (int)edit - (hour * 100);
	alarm(mktime(-1, -1, -1, hour, min, 0), "volalarm");
	say("Volume raise scheduled at " + (string)hour + ":" + (string)min);
	edit = "";
    }
    bind "Undo"
    {
	say("Exit scheduling");
	endbinding();
    }
}

