💾 Archived View for runjimmyrunrunyoufuckerrun.com › rc › playlist captured on 2022-01-08 at 13:39:08.

View Raw

More Information

⬅️ Previous capture (2021-12-17)

-=-=-=-=-=-=-

#!/bin/rc
# audio player for use with the following plumbing rules:

# wdir is /mnt/♫
# plumb to audio

# dst is audio
# plumb to audio
# plumb client window playlist

# data matches .+\.(pls|mp3|ogg|oga|flac|wav|opus|it|aac|m4a|au|snd|mid|mod|raw|pcm)
# arg isfile $data
# data set $file
# plumb to audio
# plumb client window playlist

# data matches ♫(https?://.+)
# data set $1
# plumb to audio
# plumb client window playlist

if(! test -f /mnt/plumb/audio){
	echo /mnt/plumb/audio not found! >[1=2]
	exit 'no plumb port for audio'
}
rfork en
fn redraw{
	if(! test -f tmp)
		sed -n '/^⏶/q;p' /dev/text >tmp
	mv tmp /dev/text
	echo '⏶ ⏷ ⏪ ⏩ 🔀 🔁 [pls] [exit]' $state
	echo ☞ $cur
	switch($cur){
	case *.mod
		<$cur{
			syscall -o read 0 buf 20
			echo
			for(i in `{seq 20 30 920}){
				syscall -o pread 0 buf 22 $i
				echo
			}
		}>[2]/dev/null
	case *.xm
		syscall -o pread 0 buf 20 17 <$cur >[2]/dev/null
		echo
	case *.^(mp3 ogg oga flac wav opus it aac m4a)
		if(test -x /bin/audio/readtags)
			audio/readtags $cur
	}
}
fn sighup sigint sigexit ⏹{
	if(! ~ $decpid '' && test -d /proc/$decpid){
		@{echo kill >/proc/$decpid/notepg}&
		wait $decpid
	}
	decpid = ''
}
fn ⏵{
	dec = ''
	if(! test -w /dev/audio)
		state = (stopped: /dev/audio busy)
	if not if(~ $cur http://* https://*){
		state = ⏹
		switch(`{hget -r 'User-Agent: play' -r 'Icy-MetaData: 0' $cur >[2]/dev/null | read -c 512 | file -m}){
		case audio/mpeg
			dec = 'hget -r ''User-Agent: play'' -r ''Icy-MetaData: 0'' $cur | audio/mp3dec'
		case audio/ogg
			dec = 'hget -r ''User-Agent: play'' -r ''Icy-MetaData: 0'' $cur | audio/oggdec'
		case *
			state = (stopped: no decoder for stream)
		}
	}
	if not if(! ~ $#cur 1 || ! test -s $cur || ! test -r $cur)
		state = (stopped: nothing to play)
	if not{
		switch($cur){
		case *.mp3
			dec = 'audio/mp3dec -s $secs < $cur'
		case *.ogg *.oga
			dec = 'audio/oggdec -s $secs < $cur'
		case *.flac
			dec = 'audio/flacdec -s $secs < $cur'
		case *.wav
			dec = 'audio/wavdec -s $secs < $cur'
		case *.opus
			dec = 'audio/opusdec -s $secs < $cur'
		case *.xm *.it *.s3m *.mod
			dec = 'audio/moddec -s $secs < $cur'
		case *.aac *.m4a
			secs = 0
			dec = 'audio/aacdec < $cur'
		case *.au *.snd
			secs = 0
			dec = 'audio/sundec < $cur'
		case *.mid
			secs = 0
			dec = 'games/midi -c < $cur'
		case *.raw *.pcm
			dec = 'cat $cur'
		case *
			plumb -w/ $cur
			state = (stopped: no decoder for that: plumbed elsewhere)
		}
		if(! ~ $dec ''){
			⏱ = `{date -u $secs}
			state = ⏸
			⏱ = `{date -n}
		}
	}
	redraw
	if(! ~ $dec ''){
		{eval $dec >/dev/audio; plumb ⏭}&
		decpid = $apid
	}
}
fn jumptodata{
	if(! ~ $data ⏵ $cur){
		{if(! ~ $cur '') echo $cur; cat /dev/text} | awk '
			/^⏶/{exit}
			found{print}
			$0 == ENVIRON["data"]{found = 1}
			!found{l[n++] = $0}
			END{for(i = 0; i < n; i++) print l[i]}
		' >tmp
		cur = $data
		secs = 0
	}
	⏹
	⏵
}
ramfs -um /mnt/♫
cd /mnt/♫
echo -n /mnt/♫ >/dev/wdir
echo -n ♫ >/dev/label
echo -n scroll >/dev/wctl
ifs = '
'
cur = ''
secs = 0
state = (stopped: plumb a track to start)
>tmp
redraw
</mnt/plumb/audio while(>/dev/null{
	read	# src
	read # dst
	read # wdir
	read	# type
	attr = `{read}
	ndata = `{read}
}){
	if(~ $attr *'action=showdata'*){
		read -c $ndata >tmp
		data = `{file -m tmp | tr / .}
		switch($data){
		case audio.flac
			data = `{sum tmp | read -c 8}^.flac
		case audio.mpeg
			data = `{sum tmp | read -c 8}^.mp3
		case audio.ogg
			data = `{sum tmp | read -c 8}^.ogg
		case audio.basic
			data = `{sum tmp | read -c 8}^.au
		case audio.midi
			data = `{sum tmp | read -c 8}^.mid
		case audio.wave
			data = `{sum tmp | read -c 8}^.wav
		case *
			data = `{sum tmp | read -c 8}^.^$data
		}
		mv tmp $data
		{if(! ~ $cur '') echo $cur; sed -n '/^⏶/q;p' /dev/text} >tmp
		cur = $data
		cat tmp >/dev/text
		⏹
		secs = 0
		⏵
	}
	if not{
		data = `{read -c $ndata}
		switch($data){
		case ⏶
			awk '/master/{print $2 + 3; exit}' /dev/volume >/dev/volume
		case ⏷
			awk '/master/{print $2 - 3; exit}' /dev/volume >/dev/volume
		case ⏪
			⏹
			secs = `{echo '[0pq]sx' $secs '30-d0>xp' | dc}
			⏵
			skip 60-
		case ⏩
			⏹
			secs = `{echo '[0pq]sx' $secs '30+d0>xp' | dc}
			⏵
		case ⏭
			cur = `{awk '
				BEGIN{prev = ENVIRON["cur"]}
				/^⏶/{print prev; exit}
				{print prev >>"tmp"; prev = $0}
			' /dev/text}
			⏹
			secs = 0
			⏵
		case 🔀
			awk '
				/^⏶/{exit}
				length{l[n++] = $0}
				END{
					srand
					while(n){
						i = int(rand() * --n)
						print l[i]
						l[i] = l[n]
					}
				}' /dev/text >tmp
			redraw
		case 🔁
			sed -n '/^⏶/q;p' /dev/text | sort -r | uniq | awk '
				$0 < ENVIRON["cur"]
				$0 > ENVIRON["cur"]{l[n++] = $0}
				END{for(i = 0; i < n; i++) print l[i]}
			' >tmp
			redraw
		case '[pls]'
			if(! ~ `{sed -n '/^⏶/q;/^[^\/]/p' /dev/text} '' || ~ $cur [~/]*)
				echo warning: temporary files in playlist!
			echo -n 'write playlist: '
			echo -n  >/dev/kbdin
			where = `{read /dev/cons}
			if(~ $where /*)
				{sed -n '/^⏶/q;p' /dev/text; if(! ~ $cur '') echo $cur} | tail -r >$where
			if not
				echo need an absolute path!
		case '[exit]'
			echo -n  >/dev/kbdin
			exit
		case ⏹
			⏹
			secs = 0
			state = ⏵
			redraw
		case ⏸
			⏹
			secs = `{echo $secs `{date -n} $⏱ -+p | dc}
			⏱ = `' '{date -u $secs}
			state = (⏵ $⏱(4))
			redraw
		case [0-9][0-9]:[0-9][0-9]:[0-9][0-9]
			⏹
			secs = `{awk 'BEGIN{split(ENVIRON["data"], t, ":"); print 60*60*t[1] + 60*t[2] + t[3]}'}
			⏵
		case image
			awk '/^image +image\/[^ ]+ +[0-9]+ +[0-9]+/{system("syscall -o pread 0 buf "$4" "$3" <"ENVIRON["cur"]" >[2]/dev/null | plumb -idimage");exit}' /dev/text
		case /*.pls
			if(test -r $data){
				{
					if(! ~ $cur '') echo $cur
					sed -n '/^⏶/q;p' /dev/text
					cat $data | {cur = `{read}; tail -r}
				}>tmp
				⏹
				secs = 0
				⏵
			}
			if not
				echo could not read playlist $data
		case ⏵ /* http://* https://*
			jumptodata
		case [0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].*
			if(test -f $data){
				echo `{{walk -es $data; echo 1048576/1+p}|dc}^MB $data^:
				echo -n 'hit enter to play or type a path to write to disk: '
				echo -n  >/dev/kbdin
				where = `{read /dev/cons}
				if(~ $where '')
					jumptodata
				if(~ $where /* && mv $data $where){
					if(~ $data $cur){
						cur = $where
						⏹
						⏵
					}
					if not{
						awk '
							/^⏶/{exit}
							{
								if($0 == ENVIRON["data"])
									print ENVIRON["where"]
								else
									print
							}
						' /dev/text >tmp
						redraw
					}
				}
			}
		case *
			echo -n received bad plumb: $data
		}
	}
}