-
Notifications
You must be signed in to change notification settings - Fork 0
/
flactag
executable file
·98 lines (90 loc) · 2.99 KB
/
flactag
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
#!/usr/bin/env perl
# modify FLAC tags using metaflac
use Getopt::Std;
$0 =~ s#.*/##;
# this array drives everything
%options = ('a', 'ARTIST',
'b', 'ALBUM',
'c', 'ALBUMARTIST',
'd', 'DISCNUMBER',
'e', 'DISCTOTAL',
'f', 'DISCSUBTITLE',
'g', 'GENRE',
'k', 'COMPOSER',
'l', 'TRACKTOTAL',
'n', 'TRACKNUMBER',
'p', 'PICTURE',
't', 'TITLE',
'y', 'DATE',
'z', 'MUSICBRAINZ'
);
# build USAGE
foreach $option (sort keys %options) {
$usage .= " [-$option " . lc($options{$option}) . "]";
}
$USAGE = "USAGE: $0$usage files...\n";
$USAGE .= "\t- argument of 'nil' removes a tag, example: $0 -c nil\n";
$USAGE .= "\t- argument of PCRE search/replace will replace a value, example: $0 -b 's/foo/bar/'\n";
die "$USAGE" if !@ARGV || grep(/^--help$/, @ARGV);
# parse options and arguments
$optarg = join(':', keys(%options)) . ':'; # example: a:m:g:t:d:
getopt($optarg, \%getopt); # pass reference to array
# show existing tags & exit if no arguments provided
grep(s/(\W)/\\\1/g, @ARGV); # escape non-word chars in filenames for shell
if (0 == %getopt) {
foreach $file (@ARGV) {
system("metaflac --list --block-type=VORBIS_COMMENT $file");
system("metaflac --list --block-type=PICTURE $file | head -12");
}
exit;
}
# assemble the musicbrainz tags I can zap
@brainztags = qw(disc album artist albumartist track);
foreach my $string (@brainztags) {
$string = uc("MUSICBRAINZ_" . $string . "ID");
}
# main loop
foreach $option (keys %getopt) {
$tagname = $options{$option};
$value = $getopt{$option};
if ($value =~ m/^s\W/) {
# it's a regex, read the existing tag
foreach $filename (@ARGV) {
# TODO: what if tag does not exist
$existing_tag = `metaflac --show-tag=$tagname $filename` || die "could not process $filename";
chomp $existing_tag;
$existing_tag =~ s/^$tagname=//i; # a field consists of NAME=VALUE
$_ = $existing_tag;
eval $value;
$new_tag = $_;
#print "DEBUG: new $tagname is $new_tag\n";
$metaflac_for_this{$filename} .= " --remove-first-tag=$tagname";
$metaflac_for_this{$filename} .= " --set-tag=\"$tagname=$new_tag\"" unless 'nil' eq $value;
}
} else {
# not a regex, no need to read existing tag
if ($tagname eq 'PICTURE' && $value eq 'nil') {
# special case: remove picture, must be run separately
$metaflac_for_pics .= " --remove --block-type=PICTURE,PADDING --dont-use-padding";
} elsif ($tagname eq 'MUSICBRAINZ' && $value eq 'nil') {
# zap musicbrainz tags
foreach my $tagname (@brainztags) {
$metaflac_for_all .= " --remove-first-tag=$tagname";
}
} else {
# set a tag to a value
$metaflac_for_all .= " --remove-first-tag=$tagname";
$metaflac_for_all .= " --set-tag=\"$tagname=$value\"" unless 'nil' eq $value;
}
}
}
# modify each file
foreach $filename (@ARGV) {
$command = "metaflac $metaflac_for_this{$filename} $metaflac_for_all $filename";
#print "DEBUG: $command\n";
system($command);
if ($metaflac_for_pics) {
$command = "metaflac $metaflac_for_pics $filename";
system($command);
}
}