tagtool: using getopt; alot of cosmetix
[taglib.d.git] / tagtool.d
blob175fba0f65d04c3184c2a035aa76e62767be58e5
1 #!/usr/bin/env rdmd
3 module tagview;
4 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
5 * Understanding is not required. Only obedience.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 import std.array;
21 import std.conv;
22 import std.encoding;
23 import std.getopt;
24 import std.stdio;
25 import std.string;
27 import taglib;
28 import k8.encoding;
31 string utf2koi (const(char)[] s) {
32 auto efrom = EncodingScheme.create("utf-8");
33 auto eto = EncodingScheme.create("koi8-u");
34 ubyte[] res;
35 ubyte[8] buf;
36 const(ubyte)[] ub = cast(const(ubyte)[])s;
37 while (ub.length > 0) {
38 dchar dc = efrom.safeDecode(ub);
39 if (dc == INVALID_SEQUENCE) dc = '?';
40 eto.encode(dc, buf);
41 res ~= buf[0];
43 return cast(string)res;
47 string koi2utf (const(char)[] s) {
48 auto efrom = EncodingScheme.create("koi8-u");
49 auto eto = EncodingScheme.create("utf-8");
50 ubyte[] res;
51 ubyte[8] buf;
52 const(ubyte)[] ub = cast(const(ubyte)[])s;
53 while (ub.length > 0) {
54 dchar dc = efrom.safeDecode(ub);
55 if (dc == INVALID_SEQUENCE) dc = '?';
56 auto eclen = eto.encode(dc, buf);
57 res ~= buf[0..eclen];
59 return cast(string)res;
63 private void showTags (string fname) {
64 auto tf = TagFile(fname);
65 if (tf.artist.length) writeln("ARTIST=", utf2koi(tf.artist));
66 if (tf.album.length) writeln("ALBUM=", utf2koi(tf.album));
67 if (tf.title.length) writeln("TITLE=", utf2koi(tf.title));
68 if (tf.genre.length) writeln("GENRE=", utf2koi(tf.genre));
69 if (tf.year) writeln("YEAR=", tf.year);
70 if (tf.track) writeln("TRACKNUMBER=", tf.track);
71 if (tf.comment.length) writeln("COMMENT=", utf2koi(tf.comment));
75 void main (string[] args) {
76 bool optAdd = false;
77 bool optTags = false;
78 string fileName;
80 void usage (string opt=null) {
81 import std.c.process;
82 stdout.write("
83 usage: tagtool [--add] filename [tagfile]
84 tagtool [--add] [--tags] filename [name=value]
85 short options:
86 -a --add
87 -t --tags
88 ");
89 //throw new Exception("nothing to do");
90 exit(1);
93 uint s2i (string s) {
94 import std.ascii;
95 if (s.length == 0) return 0;
96 uint res = 0;
97 while (s.length) {
98 if (!isDigit(s[0])) return 0;
99 res = res*10+s[0]-'0';
100 s = s[1..$];
102 return res;
105 getopt(args, std.getopt.config.caseSensitive, std.getopt.config.bundling, std.getopt.config.stopOnFirstNonOption,
106 "add|a", &optAdd,
107 "tags|t", &optTags,
108 "help|h", &usage
110 if (args.length < 2) usage();
111 fileName = args[1];
112 args = args[2..$];
114 try {
115 if (args.length == 0) {
116 showTags(fileName);
117 } else {
118 string artist, album, title, genre, comment;
119 uint year, track;
120 if (optAdd) {
121 // load original tags
122 auto tf = TagFile(fileName);
123 if (tf.artist.length) artist = tf.artist;
124 if (tf.album.length) album = tf.album;
125 if (tf.title.length) title = tf.title;
126 if (tf.genre.length) genre = tf.genre;
127 if (tf.comment.length) comment = tf.comment;
128 if (tf.year) year = tf.year;
129 if (tf.track) track = tf.track;
130 debug {
131 writeln("optadd!");
132 writeln(" ARTIST=", utf2koi(artist));
133 writeln(" ALBUM=", utf2koi(album));
134 writeln(" TITLE=", utf2koi(title));
135 writeln(" GENRE=", utf2koi(genre));
136 writeln(" COMMENT=", utf2koi(comment));
137 writeln(" YEAR=", year);
138 writeln(" TRACKNUMBER=", track);
142 void processLn (string v) {
143 v = koi2utf(v.idup);
144 v = v.strip;
145 if (v.length == 0 || v[0] == ';' || v[0] == '#') return;
146 auto ep = v.indexOf('=');
147 if (ep < 1) return;
148 string name = v[0..ep].toUpper;
149 v = v[ep+1..$].strip;
150 debug stdout.writeln("<", name, ">=<", v, ">");
151 switch (name) {
152 case "ARTIST": artist = v; break;
153 case "ALBUM": album = v; break;
154 case "TITLE": title = v; break;
155 case "GENRE": genre = v; break;
156 case "COMMENT": comment = v; break;
157 case "YEAR": case "DATE": year = s2i(v); break;
158 case "TRACK": case "TRACKNUMBER": track = s2i(v); break;
159 default:
163 if (optTags) {
164 foreach (tag; args) processLn(tag);
165 } else if (args[0] != "-") {
166 foreach (fname; args) {
167 foreach (ln; File(fname, "r").byLine) processLn(cast(string)ln);
169 } else {
170 foreach (ln; stdin.byLine) processLn(cast(string)ln);
172 debug {
173 writeln("final:");
174 writeln(" ARTIST=", utf2koi(artist));
175 writeln(" ALBUM=", utf2koi(album));
176 writeln(" TITLE=", utf2koi(title));
177 writeln(" GENRE=", utf2koi(genre));
178 writeln(" COMMENT=", utf2koi(comment));
179 writeln(" YEAR=", year);
180 writeln(" TRACKNUMBER=", track);
182 auto tf = TagFile(fileName);
183 tf.artist = artist;
184 tf.album = album;
185 tf.title = title;
186 tf.genre = genre;
187 tf.comment = comment;
188 tf.year = year;
189 tf.track = track;
190 tf.save();
192 } catch(Exception e) {
193 debug writeln("EXPECTION: ", e.msg);