]> diplodocus.org Git - flac-archive/blob - fa-encode
10210b90759a5bcd8818bd658a3409cd1b876490
[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 two_digits
35 ]);
36
37 sub filename {
38 my %a = @_;
39 my @discnumber = @{$a{discnumber} // []};
40 my $tracknumber = $a{tracknumber} // die('tracknumber required');
41 my $title = $a{title} // die('title required');
42 join('-',
43 (map { two_digits($_) } @discnumber),
44 two_digits($tracknumber),
45 mangle_for_file_name($title) . '.flac',
46 )
47 }
48
49 sub main {
50 my $input_directory = shift || pod2usage();
51 my $fn = "$input_directory/tags";
52 open(my $fh, '<', $fn) || die("open($fn): $!");
53 my ($album, $tracks) = read_tags($fh);
54 if (!defined($album->{ALBUM}) || scalar(@{$album->{ALBUM}}) != 1) {
55 die('exactly one ALBUM tag required')
56 }
57 my $album_tag = $album->{ALBUM}->[0];
58 # TODO -d support
59 if (!defined($album->{ARTIST}) || scalar(@{$album->{ARTIST}}) != 1) {
60 die('exactly one ARTIST tag required')
61 }
62 my $artist = $album->{ARTIST}->[0];
63
64 my $date;
65 if (defined($album->{DATE})) {
66 if (scalar(@{$album->{DATE}}) != 1) {
67 die('one or zero DATE tags required')
68 }
69 $date = $album->{DATE}->[0];
70 }
71 my @discnumber = ();
72 if (defined($album->{DISCNUMBER})) {
73 if (scalar(@{$album->{DISCNUMBER}}) != 1) {
74 die('one or zero DISCNUMBER tags required')
75 }
76 @discnumber = ($album->{DISCNUMBER}->[0]);
77 }
78
79 my $dir = join('/', '..', mangle_for_file_name($artist), mangle_for_file_name($album_tag));
80
81 say('set -ex');
82 say('cd ', quote($input_directory));
83 say('mkdir -p ', quote($dir));
84 my $tracknum = 0;
85 for my $track (@$tracks) {
86 $tracknum++;
87 if (!defined($track->{TITLE}) || scalar(@{$track->{TITLE}}) < 1) {
88 die("at least one TITLE required for track $tracknum")
89 }
90 $track->{ALBUM} = $album->{ALBUM};
91 $track->{TRACKNUMBER} = [$tracknum];
92 if (!defined($track->{ARTIST}) && defined($album->{ARTIST})) {
93 $track->{ARTIST} = $album->{ARTIST};
94 }
95 if (defined($date)) {
96 $track->{DATE} = [$date];
97 }
98 if (@discnumber) {
99 $track->{DISCNUMBER} = \@discnumber;
100 }
101 my $title = join(' ', @{$track->{TITLE}});
102 my $fn = join('/',
103 $dir,
104 filename(
105 discnumber => \@discnumber,
106 tracknumber => $tracknum,
107 title => $title,
108 ),
109 );
110 -e $fn && die("cowardly refusing to clobber $fn");
111 my @pictures = ('--picture', quote('3|image/jpeg|||cover.front.jpeg')); # TODO optional
112 my $tracknum_s = two_digits($tracknum);
113 say(join(' ',
114 'flac -o',
115 quote($fn),
116 '--delete-input-file',
117 '-V',
118 '--no-padding',
119 '--best',
120 @pictures,
121 (map {
122 my $name = $_;
123 map {
124 ('-T', quote($name . '=' . $_))
125 } @{$track->{$_}}
126 } sort(keys(%$track))),
127 "track$tracknum_s.cdda.wav"
128 ));
129 }
130 say('rm tags cover.front.jpeg');
131
132 return 0;
133 }
134
135 if (!caller) {
136 exit(main(@ARGV))
137 }
138
139 1;