/* 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(); } }