0

Add mp3 tags (including cover), json decoding order fix

This commit is contained in:
Kaimi
2015-06-15 21:29:18 +03:00
parent b89fc5a78c
commit 162306aa33

127
src/ya.pl
View File

@@ -21,7 +21,10 @@ use constant
PLAYLIST_FULL_INFO => '/handlers/track-entries.jsx', PLAYLIST_FULL_INFO => '/handlers/track-entries.jsx',
ALBUM_INFO_MASK => '/album/%d', ALBUM_INFO_MASK => '/album/%d',
FILE_SAVE_EXT => '.mp3', FILE_SAVE_EXT => '.mp3',
ARTIST_TITLE_DELIM => ' - ' ARTIST_TITLE_DELIM => ' - ',
COVER_RESOLUTION => '400x400',
GENERIC_COLLECTION => "\x{441}\x{431}\x{43e}\x{440}\x{43d}\x{438}\x{43a}",
GENERIC_TITLE => 'Various Artists'
}; };
use constant use constant
{ {
@@ -43,7 +46,7 @@ my %req_modules =
( (
NIX => [], NIX => [],
WIN => [ qw/Win32::Console::ANSI/ ], WIN => [ qw/Win32::Console::ANSI/ ],
ALL => [ qw/JSON::PP Getopt::Long::Descriptive Term::ANSIColor LWP::UserAgent HTTP::Cookies HTML::Entities/ ] ALL => [ qw/MP3::Tag JSON::PP Getopt::Long::Descriptive Term::ANSIColor LWP::UserAgent HTTP::Cookies HTML::Entities/ ]
); );
$\ = NL; $\ = NL;
@@ -184,6 +187,15 @@ sub fetch_track
} }
info(OK, 'Saved track at '.$file_path); info(OK, 'Saved track at '.$file_path);
if(write_mp3_tags($file_path, $track_info_ref->{mp3tags}))
{
info(INFO, 'MP3 tags added for ' . $file_path);
}
else
{
info(ERROR, 'Failed to add MP3 tags for ' . $file_path);
}
} }
sub download_track sub download_track
@@ -295,7 +307,7 @@ sub get_album_tracks_info
my $json = create_json($json_data); my $json = create_json($json_data);
if(!$json) if(!$json)
{ {
info(DEBUG, 'Can\'t create json from data'); info(DEBUG, 'Can\'t create json from data: ' . $@);
return; return;
} }
@@ -319,10 +331,7 @@ sub get_album_tracks_info
return map return map
{ {
{ create_track_entry($_)
dir => $_->{storageDir},
title=> $_->{artists}->[0]->{name} . ARTIST_TITLE_DELIM . $_->{title}
}
} @volumes; } @volumes;
} }
@@ -347,7 +356,7 @@ sub get_playlist_tracks_info
my $json = create_json($json_data); my $json = create_json($json_data);
if(!$json) if(!$json)
{ {
info(DEBUG, 'Can\'t create json from data'); info(DEBUG, 'Can\'t create json from data: ' . $@);
return; return;
} }
@@ -403,10 +412,7 @@ sub get_playlist_tracks_info
push @tracks_info, push @tracks_info,
map map
{ {
{ create_track_entry($_)
dir => $_->{storageDir},
title=> $_->{artists}->[0]->{name} . ARTIST_TITLE_DELIM . $_->{title}
}
} @{ $json }; } @{ $json };
} }
} }
@@ -414,22 +420,105 @@ sub get_playlist_tracks_info
{ {
@tracks_info = map @tracks_info = map
{ {
{ create_track_entry($_)
dir => $_->{storageDir},
title=> $_->{artists}->[0]->{name} . ARTIST_TITLE_DELIM . $_->{title}
}
} @{ $json->{pageData}->{playlist}->{tracks} }; } @{ $json->{pageData}->{playlist}->{tracks} };
} }
return @tracks_info; return @tracks_info;
} }
sub create_track_entry
{
my $track_info = shift;
# Multiple covers possible?
my $album_cover = fetch_album_cover($track_info->{albums}->[0]->{artists}->[0]->{cover}->{uri});
# Better detection algo?
my $is_various =
scalar @{$track_info->{artists}} > 1
||
$track_info->{albums}->[0]->{artists}->[0]->{name} eq GENERIC_COLLECTION
;
my $song_artist = join ', ', map { $_->{name} } @{$track_info->{artists}};
# TALB - album title; TPE2 - album artist; APIC - album picture; TYER - year;
# TIT2 - song title; TPE1 - song artist
return
{
# Download path part
dir => $_->{storageDir},
# MP3 tags
mp3tags =>
{
TALB => $track_info->{albums}->[0]->{title},
TPE2 => $is_various ? GENERIC_TITLE : $track_info->{albums}->[0]->{artists}->[0]->{name},
APIC => [chr(0x0), 'image/jpg', chr(0x0), 'Cover (front)', $album_cover],
TYER => $track_info->{albums}->[0]->{year},
TIT2 => $track_info->{title},
TPE1 => $song_artist
},
# Save As file name
title=> $song_artist . ARTIST_TITLE_DELIM . $track_info->{title}
};
}
sub write_mp3_tags
{
my ($file_path, $mp3tags) = @_;
my $mp3 = MP3::Tag->new($file_path);
if(!$mp3)
{
info(DEBUG, 'Can\'t create MP3::Tag object: ' . $@);
return;
}
$mp3->new_tag('ID3v2');
while(my ($frame, $data) = each %{$mp3tags})
{
info(DEBUG, 'add_frame: ' . $frame . '=' . substr $data, 0, 16);
# Skip empty
if($data)
{
$mp3->{ID3v2}->add_frame
(
$frame,
ref $data eq ref [] ? @{$data} : $data
);
}
}
$mp3->{ID3v2}->write_tag;
$mp3->close();
return 1;
}
sub fetch_album_cover
{
my $cover_url = shift;
# Normalize url
$cover_url =~ s/%%/${\(COVER_RESOLUTION)}/;
$cover_url = 'https://' . $cover_url;
my $request = $ua->get($cover_url);
if(!$request->is_success)
{
info(DEBUG, 'Request failed');
return;
}
return $request->content;
}
sub create_json sub create_json
{ {
my $json_data = shift; my $json_data = shift;
HTML::Entities::decode_entities($json_data);
my $json; my $json;
eval eval
{ {
@@ -442,6 +531,8 @@ sub create_json
return; return;
} }
HTML::Entities::decode_entities($json_data);
return $json; return $json;
} }