package App::Pimpd::Playlist::Favorite;
use strict;
no warnings 'experimental::smartmatch';
#use encoding 'utf8';
use open qw(:utf8 :std);
BEGIN {
use Exporter;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
add_to_favlist
already_loved
search_favlist
remove_favorite
);
}
use Carp 'confess';
use App::Pimpd;
use App::Pimpd::Validate;
use Term::ExtendedColor qw(fg bg);
use Tie::File;
sub already_loved {
my($file, $playlist) = @_;
my $fh;
# Ok, we have not specified an arbitary playlist name, let's see if this
# song have been loved yet!
if(!defined($playlist)) {
if(! -e $config{loved_database}) {
open(my $fh, '>', $config{loved_database});
close $fh;
}
open($fh, '<', $config{loved_database})
or confess("Cant open '$config{loved_database}': $!");
}
# See if the song is loved in the arbitary playlist
else {
if(isa_valid_playlist($playlist)) {
open($fh, '<', "$config{playlist_directory}/$playlist.m3u")
or confess("Can not open $config{playlist_directory}/$playlist: $!");
}
else {
return;
}
}
chomp(my @songs = <$fh>);
close($fh);
return ($file ~~ @songs) ? 1 : 0;
}
sub remove_favorite {
my $query = shift;
return if !defined($query);
tie(my @songs, 'Tie::File', $config{loved_database})
or confess("Cant TIE '$config{loved_database}': $!");
my $i = 0;
for my $s(@songs) {
if($s =~ m/$query/i) {
my $old = $songs[$i];
if(splice(@songs,$i, 1)) {
printf("%s removed from favlist\n", $old);
}
else {
die("Cant remove $songs[$i]: $!\n");
}
}
$i++;
}
untie(@songs) or confess("Cant close $config{loved_database}: $!");
return;
}
sub search_favlist {
my $query = shift;
open(my $fh, '<', $config{loved_database})
or confess("Cant open '$config{loved_database}': $!");
chomp(my @songs = <$fh>);
close($fh);
if(!defined($query)) {
print "$_\n" for sort(@songs);
return;
}
my @results;
for(@songs) {
if(invalid_regex($query)) {
if($_ =~ m/\Q$query/im) {
push(@results, $_);
}
}
else {
if($_ =~ m/$query/im) {
push(@results, $_);
}
}
}
return (wantarray()) ? @results : scalar(@results);
}
sub add_to_favlist {
my $favlist_m3u = shift; # arbitary playlist name
my $artist = $mpd->current->artist // 'undef';
my $album = $mpd->current->album // 'undef';
my $title = $mpd->current->title // 'undef';
my $genre = $mpd->current->genre // 'undef';
my $file = $mpd->current->file;
#my $file = $basedir . '/' . $mpd->current->file;
# Do not complain if an arbitary playlist name is specified.
if(!defined($favlist_m3u)) {
if(already_loved($file)) {
printf("%s by %s is already loved!\n",
fg($c[11], $title), fg($c[2], $artist),
);
return;
}
}
else {
if(already_loved($file, $favlist_m3u)) {
printf("%s by %s is already loved in %s\n",
fg($c[11], $title), fg($c[2], $artist), fg('bold', $favlist_m3u),
);
return;
}
}
$genre =~ s/\s+/_/gm; # evil whitespace
my(undef, undef, undef, undef, $month, $year) = localtime(time);
$month += 1;
$year += 1900;
if($favlist_m3u) {
$favlist_m3u = "$config{playlist_directory}/" . $favlist_m3u . '.m3u';
}
else {
# 2010-12-rock.m3u
$favlist_m3u = $config{playlist_directory} . "/"
. sprintf("%d-%02d-%s.m3u", $year, $month, lc($genre));
}
# Write the db locally.
open(my $fh, '>>', $config{loved_database})
or confess("Cant open '$config{loved_database}': $!");
print $fh "$file\n";
close($fh);
if(remote_host()) {
# Sometimes this yells 'Illegal seek at [ ... ].
# No idea why. It works anyway. Lets fail silently here until
# we find a proper solution.
system('ssh',
('-p', $config{ssh_port},
"$config{ssh_user}\@$config{ssh_host}", "echo '$file' >> $favlist_m3u",
),
) == 0 and do {
printf("'%s' >> %s:%s\n",
fg($c[3], $title),
$config{ssh_host},
fg($c[4], $favlist_m3u),
);
return 0;
};
return 1;
} # Nope, not remote
open(my $fh, '>>', $favlist_m3u)
or die("Could not open '$favlist_m3u' in append mode: $!");
print $fh "$file\n";
close($fh);
print fg($c[8], fg('bold', $title)), ' => ', fg($c[6], $favlist_m3u), "\n";
return;
}
1;
__END__
=pod
=head1 NAME
App::Pimpd::Playlist::Favorite - Package exporting functions for the favlist
functionality
=head1 SYNOPSIS
use App::Pimpd;
use App::Pimpd::Playlist::Favorite;
if($mpd->current->title eq 'This song is awesome!') {
add_to_favlist();
}
=head1 DESCRIPTION
App::Pimpd::Playlist::Favorite exports functions dealing with the favlist
functionality.
=head1 EXPORTS
=over
=item add_to_favlist()
Parameters: $playlist_name | NONE
Saves the currently playing song to a special playlist, 'favlist'.
If called without arguments, the playlist naming template is
C<%year-%month-%genre>, else the argument is used.
=back
=head1 SEE ALSO
App::Pimpd::Playlist
=head1 AUTHOR
Magnus Woldrich
CPAN ID: WOLDRICH
m@japh.se
http://japh.se
=head1 COPYRIGHT
Copyright (C) 2010, 2011 Magnus Woldrich. All right reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut