diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2017-10-06 13:34:17 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2017-10-06 13:34:17 +1300 |
commit | 9d7feb93cef5141bfef77d74a4a02fdb0de1a9a1 (patch) | |
tree | 2f9e2717a8ec029678e592f6e9f294bcb39960f3 | |
parent | Set up README (diff) | |
download | Music-Lyrics-LRC-9d7feb93cef5141bfef77d74a4a02fdb0de1a9a1.tar.gz Music-Lyrics-LRC-9d7feb93cef5141bfef77d74a4a02fdb0de1a9a1.zip |
First version for personal cgit but not CPAN yetv0.01
-rw-r--r-- | MANIFEST | 10 | ||||
-rw-r--r-- | MANIFEST.SKIP | 9 | ||||
-rw-r--r-- | Makefile.PL | 9 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | README.markdown | 86 | ||||
-rw-r--r-- | bin/lrcplay | 45 | ||||
-rw-r--r-- | lib/Music/Lyrics/LRC.pm | 281 | ||||
-rw-r--r-- | t/00-load.t | 13 | ||||
-rw-r--r-- | xt/manifest.t (renamed from t/manifest.t) | 0 | ||||
-rw-r--r-- | xt/pod-coverage.t (renamed from t/pod-coverage.t) | 0 | ||||
-rw-r--r-- | xt/pod.t (renamed from t/pod.t) | 0 |
11 files changed, 350 insertions, 108 deletions
@@ -1,9 +1,9 @@ Changes +bin/lrcplay lib/Music/Lyrics/LRC.pm Makefile.PL -MANIFEST This list of files +MANIFEST README -t/00-load.t -t/manifest.t -t/pod-coverage.t -t/pod.t +xt/manifest.t +xt/pod-coverage.t +xt/pod.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..bf1a02b --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,9 @@ +^\.git +^Music-Lyrics-LRC-.* +^MANIFEST\.SKIP$ +^MYMETA\. +^Makefile$ +^Makefile\.old$ +^README\.markdown +^blib +^pm_to_blib$ diff --git a/Makefile.PL b/Makefile.PL index 2539029..b8ab07e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -18,9 +18,14 @@ WriteMakefile( 'Test::More' => '0', }, PREREQ_PM => { - #'ABC' => '1.6', - #'Foo::Bar::Module' => '5.0401', + 'strict' => 0, + 'warnings' => 0, + 'utf8' => 0, + 'Carp' => 0, + 'English' => 0, + 'Time::HiRes' => 0, }, + EXE_FILES => ['bin/lrcplay'], dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, clean => { FILES => 'Music-Lyrics-LRC-*' }, ); @@ -15,10 +15,7 @@ To install this module, run the following commands: SUPPORT AND DOCUMENTATION -After installing, you can find documentation for this module with the -perldoc command. - - perldoc Music::Lyrics::LRC +None yet. If you're interested, email me at <tom@sanctum.geek.nz>. LICENSE AND COPYRIGHT diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..9f35802 --- /dev/null +++ b/README.markdown @@ -0,0 +1,86 @@ +# NAME + +Music::Lyrics::LRC - Manipulate LRC karaoke lyrics files + +# VERSION + +Version 0.01 + +# SYNOPSIS + +This section to be completed. + +# DESCRIPTION + +Read, write, and do simple manipulations of the LRC lyrics files used for some +karaoke devices. + +# SUBROUTINES/METHODS + +This section to be completed. + +# DIAGNOSTICS + +This section to be completed. + +# CONFIGURATION AND ENVIRONMENT + +None to speak of. + +# DEPENDENCIES + +- Perl 5.6 or newer +- `Carp` +- `English` + +# INCOMPATIBILITIES + +Probably. + +# BUGS AND LIMITATIONS + +Yes. + +# AUTHOR + +Tom Ryder `<tom@sanctum.geek.nz>` + +# LICENSE AND COPYRIGHT + +Copyright (C) 2017 Tom Ryder + +This program is free software; you can redistribute it and/or modify it under +the terms of the Artistic License (2.0). You may obtain a copy of the full +license at: + +<http://www.perlfoundation.org/artistic\_license\_2\_0> + +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. + +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. + +This license does not grant you the right to use any trademark, service mark, +tradename, or logo of the Copyright Holder. + +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. + +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/bin/lrcplay b/bin/lrcplay new file mode 100644 index 0000000..d217098 --- /dev/null +++ b/bin/lrcplay @@ -0,0 +1,45 @@ +#!/usr/bin/env perl +package main; + +# Force me to write this properly +use strict; +use warnings; +use utf8; + +# Include required modules +use Carp; +use English '-no_match_vars'; +use Music::Lyrics::LRC; +use Time::HiRes 'sleep'; + +# Target reasonably old Perl +use 5.006; + +# Declare package version +# Is this the right thing to do with `main`? +our $VERSION = '0.01'; + +# Make a new LRC object +my $lrc = Music::Lyrics::LRC->new(); + +# Check we have a file to read +@ARGV == 1 + or croak 'Need one file argument'; + +# Read the lyrics from the named file +my $fn = shift; +open my $fh, '<', $fn + or croak "Failed to open $fn: $ERRNO"; +$lrc->parse($fh); +close $fh + or croak "Failed to close $fn: $ERRNO"; + +# Write the timed lyric lines to standard output +my $offset = 0; +for my $lyric ( @{ $lrc->lyrics } ) { + my $delta = $lyric->{time} - $offset; + sleep $delta / 1_000; + $offset += $delta; + print "$lyric->{text}\n" + or carp "Failed stdout write: $ERRNO"; +} diff --git a/lib/Music/Lyrics/LRC.pm b/lib/Music/Lyrics/LRC.pm index a2d1f6e..1de55c9 100644 --- a/lib/Music/Lyrics/LRC.pm +++ b/lib/Music/Lyrics/LRC.pm @@ -1,141 +1,254 @@ +## no critic (RequirePODUseEncodingUTF8) package Music::Lyrics::LRC; -use 5.006; +# Force me to write this properly use strict; use warnings; +use utf8; -=head1 NAME - -Music::Lyrics::LRC - The great new Music::Lyrics::LRC! - -=head1 VERSION +# Include required modules +use Carp; +use English '-no_match_vars'; -Version 0.01 - -=cut +# Target reasonably old Perl +use 5.006; +# Declare package version our $VERSION = '0.01'; +# Patterns to match elements of the LRC file; these are somewhat tolerant +our %RE = ( + + # A blank line + blank => qr{ + \A # Start of string + \s* # Any whitespace + \z # End of string + }msx, + + # A meta tag line + tag => qr{ + \A # Start of string + \s* # Any whitespace + \[ # Opening left bracket + ([[:lower:]]+) # Tag name, capture + : # Colon + (.*) # Tag value, capture + \] # Closing right bracket + \s* # Any whitespace + \z # End of string + }msx, + + # A lyric line + line => qr { + \A # Start of string + \s* # Any whitespace + \[ # Opening left bracket + (\d+) # Minutes, capture + : # Colon + (\d{2}) # Seconds, capture + [.] # Period + (\d{2}) # Hundredths of a second, capture + \] # Closing right bracket + \h* # Any horizontal whitespace + (.*\S) # Lyric line, capture + \s* # Any whitespace + \z # End of string + }msx, +); + +# Factors to get milliseconds +our %MSF = ( + min => 60_000, + sec => 1_000, + hsec => 10, +); + +# Parser functions to consume and process captures from the above patterns +my %parsers = ( + + # A meta tag line + tag => sub { + my ( $self, $tag, $value ) = @_; + $self->{tags}{$tag} = $value; + }, + + # A lyric line + line => sub { + my ( $self, %ts, $text ); + ( $self, @ts{qw(min sec hsec)}, $text ) = @_; + + # Calculate the number of milliseconds + my $msec = 0; + for ( keys %ts ) { + $msec += $ts{$_} * $MSF{$_}; + } + + # Push a lyric hashref onto our list + push @{ $self->{lyrics} }, + { + time => $msec, + text => $text, + }; + }, +); + +# Oldschool constructor +sub new { + my ($class) = @_; + + # Start with empty tags and lyrics + my %self; + $self{tags} = {}; + $self{lyrics} = []; + + # Perlician, bless thyself + return bless \%self, $class; +} -=head1 SYNOPSIS - -Quick summary of what the module does. - -Perhaps a little code snippet. +# Read-only accessor for lyrics +sub lyrics { + my $self = shift; + return $self->{lyrics}; +} - use Music::Lyrics::LRC; +# Read-only accessor for tags +sub tags { + my $self = shift; + return $self->{tags}; +} - my $foo = Music::Lyrics::LRC->new(); - ... +# Parse an LRC file from a given filehandle +sub parse { + my ( $self, $fh ) = @_; + + # Iterate through lines + LINE: while ( my $line = <$fh> ) { + + # Iterate through line types until one matches + TYPE: for my $type ( keys %RE ) { + my @vals = $line =~ $RE{$type} + or next TYPE; + exists $parsers{$type} + or next LINE; + $parsers{$type}->( $self, @vals ); + next LINE; + } + + # This line doesn't match anything we understand, complain but continue + carp "Unknown line format on line $NR"; + } + + # All done, return the number of lyrics we have now + return scalar @{ $self->lyrics }; +} -=head1 EXPORT +1; -A list of functions that can be exported. You can delete this section -if you don't export anything, such as for a purely object-oriented module. +__END__ -=head1 SUBROUTINES/METHODS +=pod -=head2 function1 +=for stopwords +LRC tradename licensable MERCHANTABILITY -=cut - -sub function1 { -} - -=head2 function2 +=head1 NAME -=cut +Music::Lyrics::LRC - Manipulate LRC karaoke lyrics files -sub function2 { -} +=head1 VERSION -=head1 AUTHOR +Version 0.01 -Tom Ryder, C<< <tom at sanctum.geek.nz> >> +=head1 SYNOPSIS -=head1 BUGS +This section to be completed. -Please report any bugs or feature requests to C<bug-music-lyrics-lrc at rt.cpan.org>, or through -the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Music-Lyrics-LRC>. I will be notified, and then you'll -automatically be notified of progress on your bug as I make changes. +=head1 DESCRIPTION +Read, write, and do simple manipulations of the LRC lyrics files used for some +karaoke devices. +=head1 SUBROUTINES/METHODS +This section to be completed. -=head1 SUPPORT +=head1 DIAGNOSTICS -You can find documentation for this module with the perldoc command. +This section to be completed. - perldoc Music::Lyrics::LRC +=head1 CONFIGURATION AND ENVIRONMENT +None to speak of. -You can also look for information at: +=head1 DEPENDENCIES =over 4 -=item * RT: CPAN's request tracker (report bugs here) +=item * -L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Music-Lyrics-LRC> +Perl 5.6 or newer -=item * AnnoCPAN: Annotated CPAN documentation +=item * -L<http://annocpan.org/dist/Music-Lyrics-LRC> +C<Carp> -=item * CPAN Ratings +=item * -L<http://cpanratings.perl.org/d/Music-Lyrics-LRC> +C<English> -=item * Search CPAN +=back -L<http://search.cpan.org/dist/Music-Lyrics-LRC/> +=head1 INCOMPATIBILITIES -=back +Probably. +=head1 BUGS AND LIMITATIONS -=head1 ACKNOWLEDGEMENTS +Yes. +=head1 AUTHOR -=head1 LICENSE AND COPYRIGHT +Tom Ryder C<< <tom@sanctum.geek.nz> >> -Copyright 2017 Tom Ryder. +=head1 LICENSE AND COPYRIGHT -This program is free software; you can redistribute it and/or modify it -under the terms of the the Artistic License (2.0). You may obtain a -copy of the full license at: +Copyright (C) 2017 Tom Ryder -L<http://www.perlfoundation.org/artistic_license_2_0> +This program is free software; you can redistribute it and/or modify it under +the terms of the Artistic License (2.0). You may obtain a copy of the full +license at: -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. +<http://www.perlfoundation.org/artistic_license_2_0> -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. +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. -This license does not grant you the right to use any trademark, service -mark, tradename, or logo of the Copyright Holder. +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. -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. +This license does not grant you the right to use any trademark, service mark, +tradename, or logo of the Copyright Holder. -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. +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. +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. =cut - -1; # End of Music::Lyrics::LRC diff --git a/t/00-load.t b/t/00-load.t deleted file mode 100644 index 65a62de..0000000 --- a/t/00-load.t +++ /dev/null @@ -1,13 +0,0 @@ -#!perl -T -use 5.006; -use strict; -use warnings; -use Test::More; - -plan tests => 1; - -BEGIN { - use_ok( 'Music::Lyrics::LRC' ) || print "Bail out!\n"; -} - -diag( "Testing Music::Lyrics::LRC $Music::Lyrics::LRC::VERSION, Perl $], $^X" ); diff --git a/t/manifest.t b/xt/manifest.t index e0b558e..e0b558e 100644 --- a/t/manifest.t +++ b/xt/manifest.t diff --git a/t/pod-coverage.t b/xt/pod-coverage.t index f5728a5..f5728a5 100644 --- a/t/pod-coverage.t +++ b/xt/pod-coverage.t |