aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2017-11-02 10:48:54 +1300
committerTom Ryder <tom@sanctum.geek.nz>2017-11-02 10:48:54 +1300
commite058d3507a180a83a621f1f9b4762aac0a016664 (patch)
treeb1926988dd50a5da7fa286fee6fa2efcabd7c4ac
parentMerge branch 'hotfix/v0.06' (diff)
parentUpdate tests to reflect new method names (diff)
downloadMusic-Lyrics-LRC-e058d3507a180a83a621f1f9b4762aac0a016664.tar.gz
Music-Lyrics-LRC-e058d3507a180a83a621f1f9b4762aac0a016664.zip
Merge branch 'release/v0.07'v0.07
* release/v0.07: Update tests to reflect new method names Regenerate README.markdown for 0.07 Update Changes for 0.07 Bump version number to 0.07 Add verbose flag to warn on malformed lines Parse any number of fractional seconds
-rw-r--r--Changes9
-rw-r--r--Makefile.PL2
-rw-r--r--README.markdown27
-rw-r--r--lib/Music/Lyrics/LRC.pm99
-rw-r--r--t/basic.t15
5 files changed, 89 insertions, 63 deletions
diff --git a/Changes b/Changes
index 5f02fdb..eff0981 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,14 @@
Revision history for Music-Lyrics-LRC
+0.07 2017-11-02
+
+ - Parse any resolution of fractional seconds in input, including no fractional
+ seconds at all
+ - Remove msec_to_ts() and ts_to_msec() functions, replaced with internals not
+ documented
+ - Add a verbose flag to the constructor to control the emission of warnings
+ for unparsed lines from files
+
0.06 2017-11-02
- Correct syntax of output file: the format uses a period for the fractional
diff --git a/Makefile.PL b/Makefile.PL
index 2707497..fa6b1f2 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -25,7 +25,7 @@ WriteMakefile(
'meta-spec' => { version => 2 },
provides => {
'Music::Lyrics::LRC' => {
- version => '0.06',
+ version => '0.07',
file => 'lib/Music/Lyrics/LRC.pm',
},
},
diff --git a/README.markdown b/README.markdown
index 91432c9..fcaecd7 100644
--- a/README.markdown
+++ b/README.markdown
@@ -4,7 +4,7 @@ Music::Lyrics::LRC - Manipulate LRC karaoke timed lyrics files
# VERSION
-Version 0.05
+Version 0.07
# DESCRIPTION
@@ -35,9 +35,16 @@ For details on the LRC file format, please see Wikipedia:
# SUBROUTINES/METHODS
-## `new()`
+## `new(%opts)`
-Constructor; no arguments.
+Constructor method. Accepts a hash with one attribute `verbose`. This
+specifies whether the module will `warn` explicitly when it cannot parse an
+input line from a file. It defaults to 0.
+
+ my $lrc = MRC::Lyrics::LRC->new();
+ ...
+ my $lrc_verbose = MRC::Lyrics::LRC->new(verbose => 1);
+ ...
## `lyrics()`
@@ -89,16 +96,6 @@ Load lyrics from the given readable filehandle.
Save lyrics to the given writeable filehandle.
-## `ts_to_msec(\%ts)`
-
-Convert the internal LRC timestamp hash structure to milliseconds. You are
-probably not interested in this.
-
-## `msec_to_ts($msec)`
-
-Convert milliseconds to the internal LRC timestamp hash structure. You are
-probably not interested in this, either.
-
# DIAGNOSTICS
- `Bad lyric time`
@@ -169,6 +166,10 @@ may change in future revisions.
The format accepted here is very liberal, and needs to be tested with lots of
different LRC files from the wild.
+Fractional seconds of any length can be parsed, and preserved in the
+millisecond count return by `lyrics()`, but any resolution beyond 2 decimal
+places is lost on `save()`.
+
The test suite is skeletal, and needs a lot of fleshing out.
# AUTHOR
diff --git a/lib/Music/Lyrics/LRC.pm b/lib/Music/Lyrics/LRC.pm
index 10204d0..f665437 100644
--- a/lib/Music/Lyrics/LRC.pm
+++ b/lib/Music/Lyrics/LRC.pm
@@ -13,7 +13,7 @@ use English '-no_match_vars';
use 5.006;
# Declare package version
-our $VERSION = '0.06';
+our $VERSION = '0.07';
# Patterns to match elements of the LRC file; these are somewhat tolerant
our %RE = (
@@ -45,9 +45,13 @@ our %RE = (
\[ # Opening left bracket
(\d+) # Minutes, capture
: # Colon
- (\d{2}) # Seconds, capture
- [.] # Period
- (\d{2}) # Hundredths of a second, capture
+ ( # Seconds group, capture
+ \d{2} # Whole seconds
+ (?: # Group for fractional seconds
+ [.] # Period
+ \d+ # At least one digit
+ )? # End optional fractional seconds group
+ ) # End seconds group
\] # Closing right bracket
[\t ]* # Any tabs or spaces
(.*\S) # Lyric line, capture
@@ -67,11 +71,10 @@ my %parsers = (
# A lyric line
lyric => sub {
- my ( $self, %ts, $text );
- ( $self, @ts{qw(min sec csec)}, $text ) = @_;
+ my ( $self, $min, $sec, $text ) = @_;
# Calculate the number of milliseconds
- my $msec = $self->ts_to_msec( \%ts );
+ my $msec = $self->_min_sec_to_msec( $min, $sec );
# Push a lyric hashref onto our list
$self->add_lyric( $msec, $text );
@@ -80,13 +83,21 @@ my %parsers = (
# Oldschool constructor
sub new {
- my ($class) = @_;
+ my ( $class, %opts ) = @_;
- # Start with empty tags and lyrics
+ # Declare a hash to build the object around
my %self;
+
+ # Start with empty tags and lyrics
$self{tags} = {};
$self{lyrics} = [];
+ # Read in the "verbose" flag if defined, default to zero
+ $self{verbose} =
+ exists $opts{verbose}
+ ? !!$opts{verbose}
+ : 0;
+
# Perlician, bless thyself
return bless \%self, $class;
}
@@ -174,8 +185,8 @@ sub load {
next LINE;
}
- # This line doesn't match anything we understand, complain but persist
- warn "Unknown format for line $NR\n";
+ # No line format match, warn if verbose
+ warn "Unknown format for line $NR\n" if $self->{verbose};
}
# Check we got to the end of the file
@@ -208,11 +219,10 @@ sub save {
# Convert milliseconds to timestamp hash
my $msec = $lyric->{time};
- my %ts = %{ $self->msec_to_ts($msec) };
+ my ( $min, $sec ) = $self->_msec_to_min_sec($msec);
# Write the line to the file, counting the lines
- $lines += printf {$fh} "[%02u:%02u.%02u]%s\n",
- @ts{qw(min sec csec)}, $lyric->{text}
+ $lines += printf {$fh} "[%02u:%05.2f]%s\n", $min, $sec, $lyric->{text}
or die "Failed lyric write: $ERRNO\n";
}
@@ -220,32 +230,28 @@ sub save {
return $lines;
}
-# Factors for timestamp<->millisecond conversions
-our %MSF = (
- min => 60_000,
- sec => 1_000,
- csec => 10,
+# Named constants for the conversion functions
+# This stands for "millisecond factors"
+my %MSF = (
+ sec => 1_000,
+ min => 60_000,
);
-# Convert an LRC timestamp hashref to milliseconds
-sub ts_to_msec {
- my ( $self, $ts ) = @_;
+# Convert a minutes-seconds pair to milliseconds
+sub _min_sec_to_msec {
+ my ( $self, $min, $sec ) = @_;
my $msec = 0;
- for my $k ( keys %{$ts} ) {
- $msec += $ts->{$k} * $MSF{$k};
- }
+ $msec += int $min * $MSF{min};
+ $msec += $sec * $MSF{sec};
return $msec;
}
-# Convert milliseconds to an LRC timestamp hashref
-sub msec_to_ts {
+# Convert milliseconds to a minutes-seconds pair
+sub _msec_to_min_sec {
my ( $self, $msec ) = @_;
- my %ts;
- for my $k (qw(min sec csec)) {
- $ts{$k} = int $msec / $MSF{$k};
- $msec %= $MSF{$k};
- }
- return \%ts;
+ my $min = int $msec / $MSF{min};
+ my $sec = ( int $msec ) % $MSF{min} / $MSF{sec};
+ return ( $min, $sec );
}
1;
@@ -264,7 +270,7 @@ Music::Lyrics::LRC - Manipulate LRC karaoke timed lyrics files
=head1 VERSION
-Version 0.06
+Version 0.07
=head1 DESCRIPTION
@@ -295,9 +301,16 @@ L<https://en.wikipedia.org/wiki/LRC_(file_format)>
=head1 SUBROUTINES/METHODS
-=head2 C<new()>
+=head2 C<new(%opts)>
+
+Constructor method. Accepts a hash with one attribute C<verbose>. This
+specifies whether the module will C<warn> explicitly when it cannot parse an
+input line from a file. It defaults to 0.
-Constructor; no arguments.
+ my $lrc = MRC::Lyrics::LRC->new();
+ ...
+ my $lrc_verbose = MRC::Lyrics::LRC->new(verbose => 1);
+ ...
=head2 C<lyrics()>
@@ -349,16 +362,6 @@ Load lyrics from the given readable filehandle.
Save lyrics to the given writeable filehandle.
-=head2 C<ts_to_msec(\%ts)>
-
-Convert the internal LRC timestamp hash structure to milliseconds. You are
-probably not interested in this.
-
-=head2 C<msec_to_ts($msec)>
-
-Convert milliseconds to the internal LRC timestamp hash structure. You are
-probably not interested in this, either.
-
=head1 DIAGNOSTICS
=over 4
@@ -445,6 +448,10 @@ may change in future revisions.
The format accepted here is very liberal, and needs to be tested with lots of
different LRC files from the wild.
+Fractional seconds of any length can be parsed, and preserved in the
+millisecond count return by C<lyrics()>, but any resolution beyond 2 decimal
+places is lost on C<save()>.
+
The test suite is skeletal, and needs a lot of fleshing out.
=head1 AUTHOR
diff --git a/t/basic.t b/t/basic.t
index 33ad0c0..a0f91f8 100644
--- a/t/basic.t
+++ b/t/basic.t
@@ -8,7 +8,7 @@ use Test::More tests => 9;
use Music::Lyrics::LRC;
-our $VERSION = '0.06';
+our $VERSION = '0.07';
my $lrc = Music::Lyrics::LRC->new();
ok( defined $lrc, 'constructed' );
@@ -17,8 +17,17 @@ my $pkg = 'Music::Lyrics::LRC';
isa_ok( $lrc, $pkg );
can_ok(
- $lrc,
- qw(lyrics tags add_lyric set_tag unset_tag load save ts_to_msec msec_to_ts),
+ $lrc, qw(
+ lyrics
+ tags
+ add_lyric
+ set_tag
+ unset_tag
+ load
+ save
+ _min_sec_to_msec
+ _msec_to_min_sec
+ ),
);
ok( $lrc->add_lyric( 0, 'lalala' ), 'add_lyric_0' );