jukeboxのメインスクリプト
#!/bin/sh ####################### # # Simple MP3 Jukebox # KAWAMATA, Yoshihiro # kaw@on.rim.or.jp # ####################### #===== # utility functions / routines #===== # terminate process # terminate () { [ $# -ne 0 ] && echo "$@" rm -rf ctrl/playing [ -r ctrl/finish ] && . ctrl/finish } # trap for ^C # trap 'terminate "Aborted by user" ; exit' 2 # check flags, # fetch a file, # play it # # Usage: play_one_action { local_file | URL } # play_one_action () { [ $# -eq 0 ] && return # halt, reboot or exit # if [ -f ctrl/halt ]; then terminate "Halting..." rm -f ctrl/halt /sbin/shutdown -hp now sleep 86400 elif [ -f ctrl/reboot ]; then terminate "Rebooting..." rm -f ctrl/reboot /sbin/shutdown -r now sleep 86400 elif [ -f ctrl/restart ]; then terminate "Restarting script..." rm -f ctrl/restart exec $progfile elif [ -f ctrl/exit ]; then terminate "Exiting..." rm -f ctrl/exit exit fi # clean non-MP3 file and empty directories under spool # if [ -f ctrl/clean ]; then echo "Clearning dirs..." rm -f ctrl/clean find $src $dest oneshot oneshot_finished -type f \! \( -iname '*.mp3' -o -iname '*.url' \) -print0 | xargs -0 rm -f for d in $src $dest oneshot oneshot_finished; do (cd $d && find . -type d -print | sort -r | xargs rmdir >/dev/null 2>&1) done fi # pause playing # if [ -f ctrl/pause ]; then echo "Pausing..." while [ -f ctrl/pause ]; do sleep 15 done fi # play MP3 file # # ... invoke MP3 player with high priority # case "$1" in http://*.mp3|ftp://*.mp3) # # Cats are buffers against network stall. # Please adjust its numbers, if necessary. # echo "$1" > ctrl/playing/contents ftp -o - "$1" |cat|cat|cat| nice -n -15 /usr/local/bin/mpg123 $opts - ;; *.[Mm][Pp]3) if [ -f "$1" ]; then echo "$1" > ctrl/playing/contents nice -n -15 /usr/local/bin/mpg123 $opts "$1" else echo "Cannot find $1" fi ;; esac } # move played file to another directory. # directory hierarchy preserved. # # Usage: movefile srcpath desttop # movefile () { [ $# -lt 2 ] && return [ -f $1 ] || return destdir=$2/${1#*/} destdir=${destdir%[^/]*} if [ -d $destdir ]; then mv $1 $destdir else su mp3play -c "mkdir -p $destdir" && mv $1 $destdir fi } #===== # Running code from here #===== # Base and current directory is where script placed. # progfile=$0 cd `dirname $progfile` || exit 1 # check if another player running # if mkdir ctrl/playing; then date > ctrl/playing/started chmod 0755 ctrl/playing else echo "Another player running" exit 1 fi # remove stale files # rm -f ctrl/exit ctrl/reboot ctrl/halt # user initialization # [ -r ctrl/init ] && . ctrl/init #===== # main loop ... play MP3 and its control #===== while :; do # parameters to MP3 player # unset opts [ -f ctrl/mpg123opts ] && opts=`cat ctrl/mpg123opts` # We have two spool directories for infinite loop # ... spool0 and spool1. # # set direction of file movement # between two spools # when every MP3 file played # if [ -f ctrl/reverse ]; then src=spool1 dest=spool0 else src=spool0 dest=spool1 fi # playlist is symlink to spool for playing. # rm -f playlist ln -s $src playlist # for every MP3 files # control and/or playing # # xNOPLAY is a sentinel to run inner loop # for playfile in xNOPLAY `find $src -type f \( -iname '*.mp3' -o -iname '*.u rl' \) | sort`; do # retrieve resource location # case "$playfile" in *.[Uu][Rr][Ll]) mp3reslist=`cat $playfile` ;; *.[Mm][Pp]3|xNOPLAY) mp3reslist=$playfile ;; esac # for every MP3 resource ... # for mp3res in $mp3reslist; do # perform one shot playlist # while :; do for oneshot in xNOPLAY `find oneshot -type f \( -iname '*.mp3' -o -iname '*.u rl' \) | sort`; do # retrieve resource location # case "$oneshot" in *.[Uu][Rr][Ll]) oneshot_mp3res=`cat $oneshot` ;; *.[Mm][Pp]3|xNOPLAY) oneshot_mp3res=$oneshot ;; esac for os_mp3 in $oneshot_mp3res; do # check if resource file removed # if [ -f $oneshot ]; then play_one_action $os_mp3 fi # rescan all contents # if [ -f ctrl/rescan ]; then echo "Rescanning playlist..." break 5 fi done movefile $oneshot oneshot_finished done [ X"$oneshot" = XxNOPLAY ] && break done play_one_action $mp3res # restart at current spool # if [ -f ctrl/rescan ]; then echo "Rescanning playlist..." break 2 fi done # move played file to the other spool # movefile $playfile $dest done # pause when no MP3 files in spools # if [ X"$playfile$oneshot" = XxNOPLAYxNOPLAY ]; then noplay=Z$noplay echo "No file to play : $noplay" if [ $noplay = ZZ ]; then echo "Now sleeping for 60 secs..." sleep 60 noplay="" fi else noplay="" fi # role change of spools # (not changing when rescan) # if [ -f ctrl/rescan ]; then rm -f ctrl/rescan else if [ -f ctrl/reverse ]; then rm -f ctrl/reverse else touch ctrl/reverse fi fi done
kqueue / kevent というものを初めて使ってみた;
#include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <sys/types.h> #include <sys/event.h> #include <sys/time.h> main () { /* * Open current working directory */ DIR *d; int dfd; int err; if (!(d = opendir("."))) { perror("opendir"); exit(1); } /* * create and register kernel event queue */ int kq; struct kevent kev; if ((kq = kqueue()) == -1) { perror("kqueue"); closedir(d); exit(1); } EV_SET(&kev, dirfd(d), EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE, 0, NULL); if (kevent(kq, &kev, 1, NULL, 0, NULL) < 0) { perror("kevent on register"); closedir(d); exit(1); } int retval; /* * then go monitoring */ if (0 < kevent(kq, NULL, 0, &kev, 1, NULL)) { printf("dir changed.\n"); } else { perror("kevent on nofity"); closedir(d); exit(1); } /* * normal exit */ closedir(d); exit(0); }