From 4419fac56154a1cc39bca7b6abd0c80c6e0b3194 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 5 Dec 2015 13:00:45 +1300 Subject: Move scripts into bin subdir --- bin/mpdlrc | 154 +++++++++++++++++++++++++++++++++++++++++++++++++ bin/mpdlrc-notify-send | 16 +++++ mpdlrc | 154 ------------------------------------------------- mpdlrc-notify-send | 16 ----- 4 files changed, 170 insertions(+), 170 deletions(-) create mode 100755 bin/mpdlrc create mode 100755 bin/mpdlrc-notify-send delete mode 100755 mpdlrc delete mode 100755 mpdlrc-notify-send diff --git a/bin/mpdlrc b/bin/mpdlrc new file mode 100755 index 0000000..b127c1c --- /dev/null +++ b/bin/mpdlrc @@ -0,0 +1,154 @@ +#!/usr/bin/env perl + +# +# mpdlrc -- Print timed lyrics from an LRC file for MPD's currently playing +# song line-by-line to stdout. See README.markdown. +# +# Author: Tom Ryder +# Copyright: 2015 +# +package Sanctum::Mpdlrc; + +# Force me to write this properly +use strict; +use warnings; +use utf8; +use autodie qw(:all); + +# Require a few modules +use Carp; +use Const::Fast; +use Net::MPD; +use Time::HiRes qw(sleep); + +# Require at least Perl 5.12 +use 5.012; + +# Specify version number +our $VERSION = 0.1; + +# Specify some constants to appease Perl::Critic +const my $SECONDS_PER_MINUTE => 60; +const my $HUNDREDTHS_PER_SECOND => 100; + +# Connect to MPD, or give up and cry +my $mpd = Net::MPD->connect() + or croak('Failed to connect to MPD'); + +# We declare the PID outside of the main loop so we can kill it on subsequent +# iterations of the loop, should we need to restart the process. +my $pid; + +# Use UTF-8 for output, because forëigñ charåcters āre ìmpørtánt +binmode STDOUT, ':encoding(utf8)'; +STDOUT->autoflush(1); + +# Loop waiting for MPD events +MPD: while (1) { + + # Get the current status + my $status = $mpd->update_status(); + + # If there's a song playing, we'll try and spit some lyrics + if ( $status->{state} eq 'play' ) { + + # Get details about the current song + my $song = $mpd->current_song(); + + # Fork a new process + $pid = fork; + + # This block should only be run by the fork + if ( !$pid ) { + + # Build the expected filename for the lyric file from the song's + # author and title + my $lfn = sprintf '%s/.lyrics/%s - %s.lrc', $ENV{HOME}, + @{$song}{qw(Artist Title)}; + + # If no such file exists, we have failed + if ( !-e $lfn ) { + exit 1; + } + + # Read a lyrics queue object from the file, providing it with the + # elapsed time (i.e. telling it how far into the song we already + # are) + my $lyrics = read_lyrics_queue( $lfn, $status->{elapsed} ); + + # Step through the lyrics queue object, sleeping the required + # amount of time before printing each line of text to stdout + foreach my $lyric ( @{$lyrics} ) { + sleep $lyric->{delay}; + printf {*STDOUT} "%s\n", $lyric->{text}; + } + + # We, the fork, are done! + exit; + } + } + + # Wait for something else to happen to the player, whether or not there's a + # forked process going + $mpd->idle('player'); + + # Something important happened; kill any running lyric processes + if ($pid) { + kill 'INT', $pid; + } +} + +# Subroutine to read lyrics from the given filename and return a queue object +# specifying a list of lyrics to display and how long to wait before displaying +# each line +sub read_lyrics_queue { + my ( $lfn, $elapsed ) = @_; + $elapsed //= 0; + + # Read the file into a list of lines + open my $lfh, q{<:encoding(utf8)}, $lfn; + my @lines = readline $lfh; + close $lfh; + + # Start a list of lyric hashrefs + my @lyrics; + + # Read each line + LINE: foreach my $line (@lines) { + + # Get rid of trailing newlines + chomp $line; + + # If the line is in LRC format, we'll queue it up + if ( $line =~ m{\[(\d+):(\d+)[.](\d+)\](.+)}msx ) { + + # Read minutes, seconds, hundredth-seconds, and text from the + # matches in the line + my ( $min, $sec, $hsec, $text ) = ( $1, $2, $3, $4 ); + + # Flatten out the times into a number of seconds, fractional + # (that's why we need sleep() from Time::HiRes) + my $tsec = + ( $min * $SECONDS_PER_MINUTE ) + + $sec + + ( $hsec / $HUNDREDTHS_PER_SECOND ); + + # If the lyric is yet to be displayed, i.e. we haven't already + # passed the appropriate point in the song, queue it up and + # increment the elapsed time for queuing up the next lyric, if any + if ( $tsec > $elapsed ) { + my $lyric = { + delay => $tsec - $elapsed, + text => $text, + }; + push @lyrics, $lyric; + $elapsed += $lyric->{delay}; + } + + } + } + + # Return a reference to the built lyric object + return \@lyrics; +} + diff --git a/bin/mpdlrc-notify-send b/bin/mpdlrc-notify-send new file mode 100755 index 0000000..977cf1b --- /dev/null +++ b/bin/mpdlrc-notify-send @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# Check we have the two programs we need +hash mpdlrc || exit +hash notify-send || exit + +# Read the priority and timeout from the environment, or set default values +priority=${MPDLC_PRIORITY:-low} +timeout=${MPDLC_TIMEOUT:-2000} + +# Loop over each line output by mpdlrc (which will need to be somewhere in your +# PATH) and pass it to notify-send(1) +while IFS= read -r lyric ; do + notify-send -u "$priority" -t "$timeout" "$lyric" +done < <(mpdlrc) + diff --git a/mpdlrc b/mpdlrc deleted file mode 100755 index b127c1c..0000000 --- a/mpdlrc +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env perl - -# -# mpdlrc -- Print timed lyrics from an LRC file for MPD's currently playing -# song line-by-line to stdout. See README.markdown. -# -# Author: Tom Ryder -# Copyright: 2015 -# -package Sanctum::Mpdlrc; - -# Force me to write this properly -use strict; -use warnings; -use utf8; -use autodie qw(:all); - -# Require a few modules -use Carp; -use Const::Fast; -use Net::MPD; -use Time::HiRes qw(sleep); - -# Require at least Perl 5.12 -use 5.012; - -# Specify version number -our $VERSION = 0.1; - -# Specify some constants to appease Perl::Critic -const my $SECONDS_PER_MINUTE => 60; -const my $HUNDREDTHS_PER_SECOND => 100; - -# Connect to MPD, or give up and cry -my $mpd = Net::MPD->connect() - or croak('Failed to connect to MPD'); - -# We declare the PID outside of the main loop so we can kill it on subsequent -# iterations of the loop, should we need to restart the process. -my $pid; - -# Use UTF-8 for output, because forëigñ charåcters āre ìmpørtánt -binmode STDOUT, ':encoding(utf8)'; -STDOUT->autoflush(1); - -# Loop waiting for MPD events -MPD: while (1) { - - # Get the current status - my $status = $mpd->update_status(); - - # If there's a song playing, we'll try and spit some lyrics - if ( $status->{state} eq 'play' ) { - - # Get details about the current song - my $song = $mpd->current_song(); - - # Fork a new process - $pid = fork; - - # This block should only be run by the fork - if ( !$pid ) { - - # Build the expected filename for the lyric file from the song's - # author and title - my $lfn = sprintf '%s/.lyrics/%s - %s.lrc', $ENV{HOME}, - @{$song}{qw(Artist Title)}; - - # If no such file exists, we have failed - if ( !-e $lfn ) { - exit 1; - } - - # Read a lyrics queue object from the file, providing it with the - # elapsed time (i.e. telling it how far into the song we already - # are) - my $lyrics = read_lyrics_queue( $lfn, $status->{elapsed} ); - - # Step through the lyrics queue object, sleeping the required - # amount of time before printing each line of text to stdout - foreach my $lyric ( @{$lyrics} ) { - sleep $lyric->{delay}; - printf {*STDOUT} "%s\n", $lyric->{text}; - } - - # We, the fork, are done! - exit; - } - } - - # Wait for something else to happen to the player, whether or not there's a - # forked process going - $mpd->idle('player'); - - # Something important happened; kill any running lyric processes - if ($pid) { - kill 'INT', $pid; - } -} - -# Subroutine to read lyrics from the given filename and return a queue object -# specifying a list of lyrics to display and how long to wait before displaying -# each line -sub read_lyrics_queue { - my ( $lfn, $elapsed ) = @_; - $elapsed //= 0; - - # Read the file into a list of lines - open my $lfh, q{<:encoding(utf8)}, $lfn; - my @lines = readline $lfh; - close $lfh; - - # Start a list of lyric hashrefs - my @lyrics; - - # Read each line - LINE: foreach my $line (@lines) { - - # Get rid of trailing newlines - chomp $line; - - # If the line is in LRC format, we'll queue it up - if ( $line =~ m{\[(\d+):(\d+)[.](\d+)\](.+)}msx ) { - - # Read minutes, seconds, hundredth-seconds, and text from the - # matches in the line - my ( $min, $sec, $hsec, $text ) = ( $1, $2, $3, $4 ); - - # Flatten out the times into a number of seconds, fractional - # (that's why we need sleep() from Time::HiRes) - my $tsec = - ( $min * $SECONDS_PER_MINUTE ) + - $sec + - ( $hsec / $HUNDREDTHS_PER_SECOND ); - - # If the lyric is yet to be displayed, i.e. we haven't already - # passed the appropriate point in the song, queue it up and - # increment the elapsed time for queuing up the next lyric, if any - if ( $tsec > $elapsed ) { - my $lyric = { - delay => $tsec - $elapsed, - text => $text, - }; - push @lyrics, $lyric; - $elapsed += $lyric->{delay}; - } - - } - } - - # Return a reference to the built lyric object - return \@lyrics; -} - diff --git a/mpdlrc-notify-send b/mpdlrc-notify-send deleted file mode 100755 index 977cf1b..0000000 --- a/mpdlrc-notify-send +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -# Check we have the two programs we need -hash mpdlrc || exit -hash notify-send || exit - -# Read the priority and timeout from the environment, or set default values -priority=${MPDLC_PRIORITY:-low} -timeout=${MPDLC_TIMEOUT:-2000} - -# Loop over each line output by mpdlrc (which will need to be somewhere in your -# PATH) and pass it to notify-send(1) -while IFS= read -r lyric ; do - notify-send -u "$priority" -t "$timeout" "$lyric" -done < <(mpdlrc) - -- cgit v1.2.3