aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2015-12-04 22:18:44 +1300
committerTom Ryder <tom@sanctum.geek.nz>2015-12-04 22:20:58 +1300
commit429db356903983bb464028f6292a801a1483c178 (patch)
treedfe8c037eb1749a4a9e840e7ead13c150c331bc7
downloadmpdlrc-429db356903983bb464028f6292a801a1483c178.tar.gz
mpdlrc-429db356903983bb464028f6292a801a1483c178.zip
First commit
-rw-r--r--Darkthrone - To Walk The Infernal Fields.lrc34
-rw-r--r--LICENSE157
-rw-r--r--README.markdown25
-rwxr-xr-xmpdlrc149
4 files changed, 365 insertions, 0 deletions
diff --git a/Darkthrone - To Walk The Infernal Fields.lrc b/Darkthrone - To Walk The Infernal Fields.lrc
new file mode 100644
index 0000000..f006e5f
--- /dev/null
+++ b/Darkthrone - To Walk The Infernal Fields.lrc
@@ -0,0 +1,34 @@
+[00:35.36]From the abode of demons
+[00:39.20]A wing of the pentagram
+[00:43.14]Comes the juice that painted
+[00:46.80]My heart and my soul
+[00:50.90]Swept in black they are
+[00:54.80]Swept in black I am
+[00:58.63]From this soul comes eyes
+[01:02.51]That will look upon your ten
+[01:06.39]Beautiful heads
+[01:09.40]With delight
+[01:13.78]My heart is the one
+[01:17.96]That will tend to your flames
+[01:21.80]And make them mine
+[01:25.55]We share this spirit
+[01:27.44]My heart is yours
+[01:52.80]I am your disciple
+[01:54.16]And therefore my own
+[01:56.03]Your weapon I will be
+[01:57.68]With the demons that possess me
+[02:00.11]We will ride the seven sins of death
+[02:05.30]That takes me to Kathaaria
+[02:39.60]The sign of your horns
+[02:43.25]Is my dearest vision
+[02:47.16]They impale all holy
+[02:50.16]Holy and weak
+[05:39.06]You watch me face the mirror
+[05:42.47]And see the desecration
+[05:46.23]With my art I am the fist
+[05:50.25]In the face of God
+[07:00.06]You watch me face the mirror
+[07:03.47]And see the desecration
+[07:07.23]With my art I am the fist
+[07:11.25]In the face of God
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f23c229
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,157 @@
+Artistic License 2.0
+
+Copyright (c) 2000-2006, The Perl Foundation.
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed. Preamble
+
+This license establishes the terms under which a given free software Package may
+be copied, modified, distributed, and/or redistributed. The intent is that the
+Copyright Holder maintains some artistic control over the development of that
+Package while still keeping the Package available as open source and free
+software.
+
+You are always permitted to make arrangements wholly outside of this license
+directly with the Copyright Holder of a given Package. If the terms of this
+license do not permit the full use that you propose to make of the Package, you
+should contact the Copyright Holder and seek a different licensing arrangement.
+Definitions
+
+"Copyright Holder" means the individual(s) or organization(s) named in the
+copyright notice for the entire Package.
+
+"Contributor" means any party that has contributed code or other material to the
+Package, in accordance with the Copyright Holder's procedures.
+
+"You" and "your" means any person who would like to copy, distribute, or modify
+the Package.
+
+"Package" means the collection of files distributed by the Copyright Holder, and
+derivatives of that collection and/or of those files. A given Package may
+consist of either the Standard Version, or a Modified Version.
+
+"Distribute" means providing a copy of the Package or making it accessible to
+anyone else, or in the case of a company or organization, to others outside of
+your company or organization.
+
+"Distributor Fee" means any fee that you charge for Distributing this Package or
+providing support for this Package to another party. It does not mean licensing
+fees.
+
+"Standard Version" refers to the Package if it has not been modified, or has
+been modified only in ways explicitly requested by the Copyright Holder.
+
+"Modified Version" means the Package, if it has been changed, and such changes
+were not explicitly requested by the Copyright Holder.
+
+"Original License" means this Artistic License as Distributed with the Standard
+Version of the Package, in its current version or as it may be modified by The
+Perl Foundation in the future.
+
+"Source" form means the source code, documentation source, and configuration
+files for the Package.
+
+"Compiled" form means the compiled bytecode, object code, binary, or any other
+form resulting from mechanical transformation or translation of the Source form.
+Permission for Use and Modification Without Distribution
+
+(1) You are permitted to use the Standard Version and create and use Modified
+Versions for any purpose without restriction, provided that you do not
+Distribute the Modified Version. Permissions for Redistribution of the Standard
+Version
+
+(2) You may Distribute verbatim copies of the Source form of the Standard
+Version of this Package in any medium without restriction, either gratis or for
+a Distributor Fee, provided that you duplicate all of the original copyright
+notices and associated disclaimers. At your discretion, such verbatim copies may
+or may not include a Compiled form of the Package.
+
+(3) You may apply any bug fixes, portability changes, and other modifications
+made available from the Copyright Holder. The resulting Package will still be
+considered the Standard Version, and as such will be subject to the Original
+License. Distribution of Modified Versions of the Package as Source
+
+(4) You may Distribute your Modified Version as Source (either gratis or for a
+Distributor Fee, and with or without a Compiled form of the Modified Version)
+provided that you clearly document how it differs from the Standard Version,
+including, but not limited to, documenting any non-standard features,
+executables, or modules, and provided that you do at least ONE of the following:
+
+(a) make the Modified Version available to the Copyright Holder of the Standard
+Version, under the Original License, so that the Copyright Holder may include
+your modifications in the Standard Version. (b) ensure that installation of your
+Modified Version does not prevent the user installing or running the Standard
+Version. In addition, the Modified Version must bear a name that is different
+from the name of the Standard Version. (c) allow anyone who receives a copy of
+the Modified Version to make the Source form of the Modified Version available
+to others under (i) the Original License or (ii) a license that permits the
+licensee to freely copy, modify and redistribute the Modified Version using the
+same licensing terms that apply to the copy that the licensee received, and
+requires that the Source form of the Modified Version, and of any works derived
+from it, be made freely available in that license fees are prohibited but
+Distributor Fees are allowed. Distribution of Compiled Forms of the Standard
+Version or Modified Versions without the Source
+
+(5) You may Distribute Compiled forms of the Standard Version without the
+Source, provided that you include complete instructions on how to get the Source
+of the Standard Version. Such instructions must be valid at the time of your
+distribution. If these instructions, at any time while you are carrying out such
+distribution, become invalid, you must provide new instructions on demand or
+cease further distribution. If you provide valid instructions or cease
+distribution within thirty days after you become aware that the instructions are
+invalid, then you do not forfeit any of your rights under this license.
+
+(6) You may Distribute a Modified Version in Compiled form without the Source,
+provided that you comply with Section 4 with respect to the Source of the
+Modified Version. Aggregating or Linking the Package
+
+(7) You may aggregate the Package (either the Standard Version or Modified
+Version) with other packages and Distribute the resulting aggregation provided
+that you do not charge a licensing fee for the Package. Distributor Fees are
+permitted, and licensing fees for other components in the aggregation are
+permitted. The terms of this license apply to the use and Distribution of the
+Standard or Modified Versions as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with other works,
+to embed the Package in a larger work of your own, or to build stand-alone
+binary or bytecode versions of applications that include the Package, and
+Distribute the result without restriction, provided the result does not expose a
+direct interface to the Package. Items That are Not Considered Part of a
+Modified Version
+
+(9) Works (including, but not limited to, modules and scripts) that merely
+extend or make use of the Package, do not, by themselves, cause the Package to
+be a Modified Version. In addition, such works are not considered parts of the
+Package itself, and are not subject to the terms of this license. General
+Provisions
+
+(10) Any use, modification, and distribution of the Standard or Modified
+Versions is governed by this Artistic License. By using, modifying or
+distributing the Package, you accept this license. Do not use, modify, or
+distribute the Package, if you do not accept this license.
+
+(11) If your Modified Version has been derived from a Modified Version made by
+someone other than you, you are nevertheless required to ensure that your
+Modified Version complies with the requirements of this license.
+
+(12) This license does not grant you the right to use any trademark, service
+mark, tradename, or logo of the Copyright Holder.
+
+(13) This license includes the non-exclusive, worldwide, free-of-charge patent
+license to make, have made, use, offer to sell, sell, import and otherwise
+transfer the Package with respect to any patent claims licensable by the
+Copyright Holder that are necessarily infringed by the Package. If you institute
+patent litigation (including a cross-claim or counterclaim) against any party
+alleging that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the date that
+such litigation is filed.
+
+(14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
+CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW.
+UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY
+OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..2780efb
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,25 @@
+mpdlrc
+======
+
+Print timed lyrics from an LRC file for MPD's currently playing song
+line-by-line to `stdout`: <https://en.wikipedia.org/wiki/LRC_%28file_format%29>
+
+Expects to find lyrics named `Artist - Title.lrc` in `~/.lyrics`.
+
+This code is not great. It will be improved. It needs to be more configurable
+from environment variables or options, for one thing.
+
+This could maybe be used with `dzen` or a similar desktop notification tool to
+display lyrics in a corner as you work on other things.
+
+An LRC file I made for Darkthrone's "To Walk The Infernal Fields" from their
+1993 album "Under a Funeral Moon" is included for testing.
+
+License
+-------
+
+Copyright (c) [Tom Ryder][1]. Distributed under [Artistic License 2.0][2].
+
+[1]: https://sanctum.geek.nz/
+[2]: http://opensource.org/licenses/artistic-license-2.0
+
diff --git a/mpdlrc b/mpdlrc
new file mode 100755
index 0000000..e59e6f5
--- /dev/null
+++ b/mpdlrc
@@ -0,0 +1,149 @@
+#!/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 <tom@sanctum.geek.nz>
+# 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)';
+
+MPD: while (1) {
+
+ # Something important happened; kill any running lyric processes
+ if ($pid) {
+ kill 'INT', $pid;
+ }
+
+ # 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};
+ }
+ }
+ }
+
+ # Wait for something else to happen to the player, whether or not there's a
+ # forked process going
+ $mpd->idle('player');
+}
+
+# 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;
+}
+