1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#!/usr/bin/perl
binmode(STDOUT, ":utf8");
use v5.10;
use warnings;
use Array::Utils qw(:all);
use DDP;
use File::Spec;
use strict;
use utf8;
use Encode qw(decode encode);
use File::Find;
use Getopt::Std;
use Net::MPD;
my $mpd_host = "tauron";
my $mpd = Net::MPD->connect($ENV{MPD_HOST} // $mpd_host // 'localhost');
my $music_root = "/mnt/raid/Audio/Rips";
sub main {
my %options=();
getopts("rst", \%options);
if ($options{r} // $options{s} // $options{t}) {
if (defined $options{r}) { subscribe_ratings_channel(); track_rating(); }
elsif (defined $options{s}) { subscribe_ratings_channel(); sync_ratings(); }
elsif (defined $options{t}) { tag_from_sticker(); }
} else { subscribe_ratings_channel(); track_rating(); };
}
sub subscribe_ratings_channel {
$mpd->subscribe('rating');
}
sub track_rating {
while(1) {
$mpd->idle('message');
my @blub = $mpd->read_messages;
foreach (@blub) {
my $string = $_->{message};
my @array = split("\t", $string);
my $uri = $array[0];
my $mode = $array[1];
my $rating = $array[2];
$uri = decode('UTF-8', $uri );
my @files = $mpd->search('filename', $uri);
my @song_tags = $files[0];
my $albumartist = $song_tags[0]->{AlbumArtist};
my $artist = $song_tags[0]->{Artist};
my $title = $song_tags[0]->{Title};
my $album = $song_tags[0]->{Album};
if ($uri =~ /.*.flac$/) {
if ($mode eq "RATING") {
print ":: tagging track \"${title}\" by \"${artist}\" with rating of \"${rating}\"\n";
} elsif ($mode eq "ALBUMRATING") {
print ":: tagging track \"${title}\" by \"${albumartist}\" with albumrating of \"${rating}\"\n";
}
system('metaflac', '--remove-tag=RATING', "${music_root}/${uri}");
system('metaflac', "--set-tag=${mode}=${rating}", "${music_root}/${uri}");
}
elsif ($uri =~ /.*.mp3$/) {
if ($mode eq "RATING") {
print ":: tagging track \"${title}\" by \"${artist}\" with rating of \"${rating}\"\n";
} elsif ($mode eq "ALBUMRATING") {
print ":: tagging track \"${title}\" by \"${albumartist}\" with albumrating of \"${rating}\"\n";
}
system('mid3v2', "--TXXX:${mode}:${rating}", "${music_root}/${uri}");
}
elsif ($uri =~ /.*.ogg$/) {
print "!! OGG files not supported, yet\n";
}
}
}
}
sub sync_ratings {
my @sticker_uris;
my @actual_uris;
my @available_stickers = $mpd->sticker_find('song', 'rating', '');
foreach my $rated_song (@available_stickers) {
push @sticker_uris, "$rated_song->{file}";
}
my @absolute;
find({
wanted => sub { push @absolute, $_ if -f and -r },
no_chdir => 1,
}, $music_root);
my @relative = map { File::Spec->abs2rel($_, $music_root) } @absolute;
push @actual_uris, $_ for @relative;
my @diff = array_diff(@sticker_uris, @actual_uris);
foreach my $unrated_song (@diff) {
if ( $unrated_song =~ /.*.flac$/) {
my $rating = system('metaflac', '--show-tag=RATING', "${music_root}/${unrated_song}");
print "$rating\n";
if ($rating ne "0") {
print "rating ${music_root}/${unrated_song} with $rating\n";
$mpd->sticker_value("song", "$unrated_song", "rating", "$rating");
}
}
}
}
sub tag_from_sticker {
my @available_stickers = $mpd->sticker_find('song', 'rating', '');
foreach my $rated_song (@available_stickers) {
my $uri = $rated_song->{file};
my $rating = $rated_song->{sticker};
if ($uri =~ /.*.flac$/) {
system('metaflac', '--remove-tag=RATING', "${music_root}/${uri}");
system('metaflac', "--set-tag=RATING=$rating", "${music_root}/${uri}");
}
elsif ($uri =~ /.*.mp3$/) {
system('mid3v2', "--TXXX:RATING:${rating}", "${music_root}/${uri}");
}
elsif ($uri =~ /.*.ogg$/) {
print "!! OGG files not supported, yet\n";
}
}
}
main();
|