]> diplodocus.org Git - flac-archive/blob - fa-encode
Restore PART/VERSION and add filename tests.
[flac-archive] / fa-encode
1 #!/usr/local/bin/perl
2
3 =head1 NAME
4
5 B<fa-encode> - encode WAV files to FLAC
6
7 =head1 SYNOPSIS
8
9 B<fa-encode> [B<-d> I<artist-directory>] B<input-directory>
10
11 I<artist-directory> defaults to the album B<ARTIST> in the tags file; one of
12 these is required.
13
14 TODO: implement B<-d>
15
16 =cut
17
18 package epg::flac::archive::encode;
19
20 use v5.12;
21 use warnings;
22
23 use FindBin;
24 use Pod::Usage;
25
26 use lib $FindBin::Bin;
27
28 require 'tags.pl';
29 epg::flac::archive::tags->import(
30 qw[
31 read_tags
32 mangle_for_file_name
33 quote
34 track_tags_from_disc
35 two_digits
36 ]);
37
38 sub filename {
39 my ($tracknumber, $tags) = @_;
40 my $title = $tags->{TITLE} // die('title required');
41 my @discnumber = @{$tags->{DISCNUMBER} // []};
42 my @partnumber = @{$tags->{PARTNUMBER} // []};
43 my @version = @{$tags->{VERSION} // []};
44 join('-',
45 (map { two_digits($_) } @discnumber),
46 two_digits($tracknumber),
47 mangle_for_file_name(join('TODO multi-title?', @$title)),
48 # TODO more than one VERSION?
49 (map { mangle_for_file_name($_) } @version),
50 @partnumber,
51 )
52 . '.flac',
53 }
54
55 sub main {
56 my $input_directory = shift || pod2usage();
57 my $fn = "$input_directory/tags";
58 open(my $fh, '<', $fn) || die("open($fn): $!");
59 my ($album, $tracks) = read_tags($fh);
60 if (!defined($album->{ALBUM}) || scalar(@{$album->{ALBUM}}) != 1) {
61 die('exactly one ALBUM tag required')
62 }
63 my $album_tag = $album->{ALBUM}->[0];
64 # TODO -d support
65 if (!defined($album->{ARTIST}) || scalar(@{$album->{ARTIST}}) != 1) {
66 die('exactly one ARTIST tag required')
67 }
68 my $artist = $album->{ARTIST}->[0];
69
70 my $date;
71 if (defined($album->{DATE})) {
72 if (scalar(@{$album->{DATE}}) != 1) {
73 die('one or zero DATE tags required')
74 }
75 $date = $album->{DATE}->[0];
76 }
77 my @discnumber = ();
78 if (defined($album->{DISCNUMBER})) {
79 if (scalar(@{$album->{DISCNUMBER}}) != 1) {
80 die('one or zero DISCNUMBER tags required')
81 }
82 @discnumber = ($album->{DISCNUMBER}->[0]);
83 }
84
85 my $dir = join('/', '..', mangle_for_file_name($artist), mangle_for_file_name($album_tag));
86
87 say('set -ex');
88 say('cd ', quote($input_directory));
89 say('mkdir -p ', quote($dir));
90 my $tracknum = 0;
91 for my $track (@$tracks) {
92 $tracknum++;
93 if (!defined($track->{TITLE}) || scalar(@{$track->{TITLE}}) < 1) {
94 die("at least one TITLE required for track $tracknum")
95 }
96 $track->{ALBUM} = $album->{ALBUM};
97 $track->{TRACKNUMBER} = [$tracknum];
98 if (!defined($track->{ARTIST}) && defined($album->{ARTIST})) {
99 $track->{ARTIST} = $album->{ARTIST};
100 }
101 if (defined($date)) {
102 $track->{DATE} = [$date];
103 }
104 if (@discnumber) {
105 $track->{DISCNUMBER} = \@discnumber;
106 }
107 my $title = join(' ', @{$track->{TITLE}});
108 my $fn = join('/',
109 $dir,
110 filename(
111 $tracknum,
112 {track_tags_from_disc($album, $tracks, $tracknum)}
113 ),
114 );
115 -e $fn && die("cowardly refusing to clobber $fn");
116 my @pictures = ('--picture', quote('3|image/jpeg|||cover.front.jpeg')); # TODO optional
117 my $tracknum_s = two_digits($tracknum);
118 say(join(' ',
119 'flac -o',
120 quote($fn),
121 '--delete-input-file',
122 '-V',
123 '--no-padding',
124 '--best',
125 @pictures,
126 (map {
127 my $name = $_;
128 map {
129 ('-T', quote($name . '=' . $_))
130 } @{$track->{$_}}
131 } sort(keys(%$track))),
132 "track$tracknum_s.cdda.wav"
133 ));
134 }
135 say('rm tags cover.front.jpeg');
136
137 return 0;
138 }
139
140 if (!caller) {
141 exit(main(@ARGV))
142 }
143
144 1;