Late Stage Music Player
Granted I do not much listen to music these years—or too much if I'm obsessing over something like the second section of a Menuet, but that's not really what most would call listening to music. If I want some background noise there is the "music player"
#!/bin/sh
setvol 40 /mpv 100
cd ~/share/video/aquatic && exec mpv --shuffle --no-video .
and that directory has various ambient schlock linked to from somewhere, probably it was
as "Dronny Darko" was pretty easy to search for. setvol(1) is a pretty obvious wrapper around sndioctl(1) on OpenBSD, except it takes 0..100 for the volume instead of the 0.0 to 1.0 that sndioctl(1) wants, and is easier for me to type.
$ sndioctl
input.level=0.600
input.mute=0
output.level=0.549
output.mute=0
server.device=0
app/aucat0.level=1.000
app/audacit0.level=1.000
app/fluidsy0.level=1.000
app/lmms0.level=1.000
app/midipla0.level=1.000
app/mpv0.level=1.000
app/play0.level=1.000
Otherwise play(1) from the sox package sometimes gets used, but that lacks the easy spacebar to pause the playback like mpv(1) has. midiplay(1) is a custom fluidsynth wrapper that defaults to the generaluser-gs-soundfont; that and most of the rest are for music production.
My life would probably be easier if I didn't pick hard to play end-blown flutes.
Some Older Script Rediscovered in ~/bin
#!/usr/bin/env perl
#
# playmusic - plays MP3 files found in the given or otherwise current
# directory. the shuffle is modified so that some number of recently
# played files are not repeated
use 5.28.0;
use warnings;
use Curses;
use File::Find::Rule;
use Getopt::Long 'GetOptions';
use List::Util qw(all min shuffle);
use POSIX ':sys_wait_h';
use constant { CONTROL_C => chr(3) };
GetOptions( 'delay|d=i' => \my $Flag_Delay ) or exit 1;
if (@ARGV) {
for (@ARGV) {
die "no such directory '$_'\n" unless -d;
}
} else {
@ARGV = '.';
}
my %files;
@files{ File::Find::Rule->file()->name('*.mp3')->in(@ARGV) } = ();
die "no matching files found\n" unless keys %files;
my $remember = min 5, int sqrt keys %files;
my @recent;
initscr;
curs_set(0);
keypad(0);
noecho;
nodelay(1);
raw;
while (1) {
for my $f (
shuffle grep {
my $f = $_;
all { $_ ne $f } @recent
} keys %files
) {
shift @recent if @recent > $remember;
push @recent, $f;
move( 0, 0 );
clrtobot();
addstring($f);
my $pid = play($f);
my $playing = 1;
while ( 0 == waitpid( $pid, WNOHANG ) ) {
my $ch = getchar() // next;
if ( $ch eq 'q' or $ch eq CONTROL_C ) {
endwin;
my $self = getpgrp(0);
kill INT => -$self;
exit;
} elsif ( $ch eq 'r' ) {
kill INT => $pid;
endwin;
exec $^X, $0, @ARGV;
} elsif ( $ch eq 'n' ) {
kill INT => $pid;
last;
} elsif ( $ch eq ' ' ) {
kill $playing ? 'STOP' : 'CONT', $pid;
$playing ^= 1;
}
} continue {
napms(100);
}
napms( int rand $Flag_Delay ) if $Flag_Delay;
}
}
sub play {
my $pid = fork() // die "fork failed: $!\n";
if ( $pid == 0 ) {
exec qw(play -q --buffer 65536), $_[0];
die "exec failed: $!\n";
}
return $pid;
}