rutaci 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,232 @@
1
+ # This file is part of rutaci, see the README for more information
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'optparse'
19
+ require 'ostruct'
20
+
21
+ module Rutaci
22
+ class Application
23
+ attr_reader :options
24
+
25
+ def initialize
26
+ @options = OpenStruct.new(
27
+ # default values
28
+ :command => :get,
29
+ :fields => [:track, :title, :artist, :album, :year, :genre, :comment], # FIXME: patch tagalib to provilde a list of all available fields
30
+ :destination => ".",
31
+ :files => []
32
+ )
33
+ #puts "default options: #{@options}"
34
+ end
35
+
36
+ def parse_options
37
+ # The general form of the parameters to parse is:
38
+ # "<general options> <command> <field otions> <filenames...>"
39
+ # Since GetoptLong and ParseOptions don't know handle this structure (options os a
40
+ # command in the middle) but I don't want to do all by hand, ARGV is split at the command
41
+ # position in two, the command is analysed manualy and the two parts are passed to GetoptLong
42
+ # seperately.
43
+ command_position = (ARGV.index('set') or ARGV.index('get') or ARGV.index('rename'))
44
+ if command_position
45
+ field_options = ARGV.slice! command_position..ARGV.length # splitt ARGV at the command_position
46
+ @options.fields = nil # don't use the default files when a command is given
47
+ @options.command = field_options.shift.to_sym
48
+ else
49
+ field_options = []
50
+ end
51
+
52
+ get_parser = OptionParser.new do |opts|
53
+ opts.banner = "fields to use with the get command (or set with --format/--muscibrains):"
54
+ opts.on("--title", "-t", "get the title") do
55
+ @options.fields ||= Array.new
56
+ @options.fields.push :title
57
+ end
58
+ opts.on("--artist", "-i", "get the artist") do
59
+ @options.fields ||= Array.new
60
+ @options.fields.push :artist
61
+ end
62
+ opts.on("--album", "-a", "get the album") do
63
+ @options.fields ||= Array.new
64
+ @options.fields.push :album
65
+ end
66
+ opts.on("--track", "-n", "get the tracknumer") do
67
+ @options.fields ||= Array.new
68
+ @options.fields.push :track
69
+ end
70
+ opts.on("--year", "-y", "get the year") do
71
+ @options.fields ||= Array.new
72
+ @options.fields.push :year
73
+ end
74
+ opts.on("--genre", "-g", "get the genre") do
75
+ @options.fields ||= Array.new
76
+ @options.fields.push :genre
77
+ end
78
+ opts.on("--comment", "-c", "get the comment") do
79
+ @options.fields ||= Array.new
80
+ @options.fields.push :comment
81
+ end
82
+ end # get_parser
83
+
84
+ set_parser = OptionParser.new do |opts|
85
+ opts.banner = "fields to use with the set command:"
86
+ opts.on("--title TITLE", "-t", "set the title to TITLE") do |title|
87
+ @options.fields ||= Hash.new
88
+ @options.fields[:title] = title
89
+ end
90
+ opts.on("--artist ARTIST", "-i", "set the artist to ARTIST") do |artist|
91
+ @options.fields ||= Hash.new
92
+ @options.fields[:artist] = artist
93
+ end
94
+ opts.on("--album ALBUM", "-a", "set the album to ALBUM") do |album|
95
+ @options.fields ||= Hash.new
96
+ @options.fields[:album] = album
97
+ end
98
+ opts.on("--track N", "-n", "set the tracknumer to N") do |track|
99
+ @options.fields ||= Hash.new
100
+ @options.fields[:track] = track
101
+ end
102
+ opts.on("--year YEAR", "-y", "set the year to YEAR") do |year|
103
+ @options.fields ||= Hash.new
104
+ @options.fields[:year] = year
105
+ end
106
+ opts.on("--genre GENRE", "-g", "set the genre to GENRE") do |genre|
107
+ @options.fields ||= Hash.new
108
+ @options.fields[:genre] = genre
109
+ end
110
+ opts.on("--comment COMMENT", "-c", "set the comment to COMMENT") do |comment|
111
+ @options.fields ||= Hash.new
112
+ @options.fields[:comment] = comment
113
+ end
114
+
115
+ opts.separator ""
116
+ opts.separator "Note: When using the --format option, the set parameters take no argument"
117
+ opts.separator " (like when used with get) The value is extracted via FORMAT from the"
118
+ opts.separator " the path/filename. Without parameters, every field appearing in FORMAT"
119
+ opts.separator " is used."
120
+ # opts.separator ""
121
+ # opts.separator "Note: When using the --musicbrainz option, the set parameters take no argument"
122
+ # opts.separator " (like when used with get) The value are looked up at musicbrains.org"
123
+ # opts.separator " using an acoustic fingerprint of the music file. Without parameters,"
124
+ # opts.separator " every field provided by musicbrains.org is used."
125
+ end # set_parser
126
+
127
+ general_parser = OptionParser.new do |opts|
128
+ opts.banner = "general options:"
129
+ opts.on("--dry-run", "-d", "Don't really execute the command, just show what would happen",
130
+ "Has no effect with the get command") do
131
+ @options.dry_run = true
132
+ end
133
+ opts.on("--interactive", "-i", "Give the user the chance to edit any value/filename",
134
+ "Has no effect with the get command; requires GNU readline") do
135
+ @options.interactive = true
136
+ end
137
+ opts.on("--keep-empty-fields", "-k", "Keep empty fields instead of removeing them when",
138
+ "displaying or setting an empty value.",
139
+ "Don't affects the rename command, we will never set an empty filename") do
140
+ @options.keep_empty_fields = true
141
+ end
142
+ opts.on("--format FORMAT", "-f", "Use FORMAT to parse input or format output and filenames",
143
+ "Used with a get command, it will format the output",
144
+ "Used with a set command, it's the pattern for parsing the filename",
145
+ "Used with a rename command, it will give the new filename",
146
+ "An example is '%n - %t.mp3', see the manual for details") do |format|
147
+ @options.format = format
148
+ end
149
+ # opts.on("--musicbrainz", "-m", "use musicbrainz.org to find the right taggs for you music",
150
+ # "This is just an other source for the metadata") do
151
+ # @options.musicbrainz = true
152
+ # end
153
+
154
+ opts.separator ""
155
+ opts.separator "options to use with the get command:"
156
+ opts.on("--values-only", "-o", "Print out only the values themselfs (one per line)",
157
+ "Fieldnames and the normaly displayed filename are ommited.") do
158
+ @options.values_only = true
159
+ end
160
+
161
+ opts.separator ""
162
+ opts.separator "options to use with the rename command:"
163
+ opts.on("--destination DESTINATION", "-D", "Set the destination directory to DESTINATION",
164
+ "default '#{@options.destination}'") do |destination|
165
+ @options.destination = destination
166
+ end
167
+
168
+ opts.separator ""
169
+ opts.separator "generic options:"
170
+
171
+ opts.on("--help", "-h", "-?", "Shows this message and quit") do
172
+ puts "rutaci is a cli tool for manipulating music file's metadata"
173
+ puts
174
+ puts "Useage: #{$0} [<options>] [get [<fields>]] <filenames...>"
175
+ puts " #{$0} [<options>] set <fields and values> <filenames...>"
176
+ puts " #{$0} [<options>] --format FORMAT rename <filenames...>"
177
+ puts
178
+ puts general_parser
179
+ puts
180
+ puts get_parser
181
+ puts
182
+ puts set_parser
183
+ exit
184
+ end
185
+ opts.on("--version", "Shows version and exit") do
186
+ puts VERSION_STRING
187
+ exit
188
+ end
189
+ end #general_parser
190
+
191
+ general_parser.parse! ARGV
192
+ @options.files.push *ARGV # the remaining args are filenames, when no command is given
193
+
194
+ if @options.command == :get or (@options.command == :set and (@options.format or @options.musicbrainz))
195
+ # note: when a format is given, we parse get-style,
196
+ # even with set since the values come from the filename or muscibrains (not the command line)
197
+ get_parser.parse! field_options
198
+ else
199
+ set_parser.parse! field_options if @options.command == :set
200
+ end
201
+ @options.files.push *field_options # the remaining args are filenames
202
+
203
+ if @options.files.empty?
204
+ puts "sorry, I need at least one filename to work with!"
205
+ puts "try the manpage or #{$0} --help"
206
+ exit 1
207
+ end
208
+
209
+ if @options.command == :rename and not @options.format
210
+ puts "sorry, I need a format for the rename command!"
211
+ puts "try the manpage or #{$0} --help"
212
+ exit 1
213
+ end
214
+ end
215
+
216
+ def run
217
+ parse_options
218
+ executor = case @options.command
219
+ when :get
220
+ require 'rutaci/getter'
221
+ Getter.new @options
222
+ when :set
223
+ require 'rutaci/setter'
224
+ Setter.new @options
225
+ when :rename
226
+ require 'rutaci/renamer'
227
+ Renamer.new @options
228
+ end
229
+ executor.run @options.files
230
+ end
231
+ end # class Application
232
+ end # module Rutaci
@@ -0,0 +1,59 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'rutaci/formater'
19
+
20
+ module Rutaci
21
+ # This class collects the taginfo from various sources.
22
+ class FilenameSource < Source
23
+ attr_reader :info
24
+ def initialize(filename, options)
25
+ raise ArgumentError, "options.format doesn't exist" unless options.format
26
+ @filename = File.expand_path filename # we may need the full path
27
+ @wanted_fields = options.fields # if this is not nil it should contain a positive-list of fileds
28
+ @regexp, @fieldlist = self.create_regexp options.format
29
+ @info = self.get_fields
30
+ end
31
+
32
+ def get_fields
33
+ match = @regexp.match @filename
34
+ return nil unless match
35
+ groups = match.to_a
36
+ groups.shift # get rid of the first field, since it's the whole match (we need only the groups)
37
+ info = Hash.new
38
+ @fieldlist.each_with_index do |field, index|
39
+ next if @wanted_fields and not @wanted_fields.include? field
40
+ info[field] = groups[index]
41
+ end
42
+ return info
43
+ end
44
+
45
+ def create_regexp(format)
46
+ str = String.new
47
+ fieldlist = Array.new
48
+ Formater.tokenize format do |token, is_placeholder|
49
+ if is_placeholder
50
+ str += "([^#{File::SEPARATOR}]*)" # match any char appart File::SEPARATOR into a group
51
+ fieldlist.push Formater::PLACEHOLDERS[token]
52
+ else
53
+ str += Regexp.escape token
54
+ end
55
+ end # tokenize
56
+ return Regexp.new(str + "$"), fieldlist
57
+ end
58
+ end # class FilenameSource
59
+ end # module Rutaci
@@ -0,0 +1,81 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ module Rutaci
19
+ class Formater
20
+ # translation of format string tokens to info field names
21
+ PLACEHOLDERS = {
22
+ "t" => :title,
23
+ "i" => :artist,
24
+ "a" => :album,
25
+ "n" => :track,
26
+ "y" => :year,
27
+ "g" => :genre,
28
+ "c" => :comment
29
+ }
30
+
31
+ # performs a lexical analysis for strings like "%n - %t"
32
+ # and yields every token found. A token may be a normal char or a placeholder
33
+ # the argumetns passed to the block is the current token and if it's a placeholder or not
34
+ # Note that a placeholder token is passed without the leading '%'
35
+ # A placeholder token always ends with a lower case letter and may have some leading flags
36
+ # A flag is everything which isn't a lower case letter or the '%' sign
37
+ def self.tokenize(format)
38
+ raise ArgumentError, "need a block to handle the tokens" unless block_given?
39
+ is_placeholder = false # true if the previous char was a '%'
40
+ multichar_token = "" # here the chars for multichar tokens are acculumated before the comleate token is send out
41
+ format.each_byte do |c|
42
+ if is_placeholder
43
+ if c == ?%
44
+ yield c.chr, false # '%%' is not the placeholder '%' but a normal '%'
45
+ else
46
+ # look out for multichar tokens
47
+ multichar_token += c.chr
48
+ if /[a-z]/.match multichar_token
49
+ yield multichar_token, true
50
+ multichar_token = ""
51
+ else
52
+ next
53
+ end
54
+ end
55
+ is_placeholder = false
56
+ else
57
+ if c == ?%
58
+ is_placeholder = true
59
+ else
60
+ yield c.chr, false
61
+ end
62
+ end # is_placeholder?
63
+ end # each_byte
64
+ end # def self.tokenize
65
+
66
+ def self.string_for_token(token, info)
67
+ placeholder = token[-1].chr # the placeholder is the last letter
68
+ flags = token[0..-2] # the rest are flags
69
+ value = info[PLACEHOLDERS[placeholder]]
70
+ case value
71
+ when Fixnum, Bignum
72
+ value = sprintf "%#{flags}d", value
73
+ when String
74
+ value = sprintf "%#{flags}s", value
75
+ else # for other classes no flags are defined (yet ;-)
76
+ value = value.to_s
77
+ end
78
+ return value
79
+ end
80
+ end # class Formater
81
+ end # module Rutaci
@@ -0,0 +1,79 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'rutaci/source'
19
+
20
+ module Rutaci
21
+ # gets info from a source and display it
22
+ # it is a command executor, so it has tp provide an initializer which takes the options
23
+ # and a method 'run' which takes an array of filenames
24
+ class Getter
25
+ def initialize(options)
26
+ @options = options
27
+ if @options.format
28
+ require 'rutaci/formater'
29
+ # make sure we get all fields nessesary for the expanding the format string
30
+ @options.fields = Array.new
31
+ Formater::PLACEHOLDERS.each_pair do |token, field|
32
+ @options.fields.push field if /%[^a-z]*#{token}/.match @options.format
33
+ end
34
+ end
35
+ end
36
+
37
+ # invoke this executor for an array of filenames
38
+ def run(files)
39
+ output = Array.new
40
+ files.each do |file|
41
+ output.push self.get(file) + "\n"
42
+ end
43
+ puts output.join("\n") # a blank line between the items
44
+ end
45
+
46
+ # get and return the actual info for a specific file
47
+ def get(file)
48
+ source = Source.factory file, @options
49
+ # use the format string if available
50
+ return self.format(source.info, @options.format) if @options.format
51
+ # esle create the standard format
52
+ output = Array.new
53
+ output.push "Filename: #{file}" unless @options.values_only
54
+ source.info.each_pair do |key, value|
55
+ value = nil if value == 0 # HACK: rtaglib seems to return non-existing numeric values as 0 instead of nil
56
+ value = value.to_s
57
+ next if value.empty? unless @options.keep_empty_fields
58
+ element = String.new
59
+ element += key.to_s.capitalize + ": " unless @options.values_only
60
+ element += value
61
+ output.push element
62
+ end
63
+ return output.join("\n")
64
+ end
65
+
66
+ # return the info formated, format may be something like "%n - %t"
67
+ def format(info, format)
68
+ str = String.new
69
+ Formater.tokenize format do |token, is_placeholder|
70
+ if is_placeholder
71
+ str += Formater.string_for_token token, info
72
+ else
73
+ str += token
74
+ end
75
+ end
76
+ return str
77
+ end
78
+ end # class Getter
79
+ end # module Rutaci
@@ -0,0 +1,57 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'readline'
19
+
20
+ module Rutaci
21
+ # writes info from a source into the files
22
+ # it is a command executor, so it has tp provide an initializer which takes the options
23
+ # and a method 'run' which takes an array of filenames
24
+ module Interaction
25
+ def self.print_lineedit_help
26
+ puts "Use <TAB> on an empty line will insert the default value, else completion is done"
27
+ puts "Use <Ctrl-C> to discard your changes and use the default value"
28
+ end
29
+
30
+ # use GNU readline for the interactive input
31
+ def self.lineedit(promt, default_value, completion_strings = [])
32
+ # FIXME: display the default value and don't wait for the user to press TAB
33
+ # it seems that this requires hacking the readline module
34
+ add_to_history = true
35
+ Readline.completion_proc = Proc.new do |current_line|
36
+ if current_line.empty?
37
+ # if we haven't typed anything, the completion is the default value
38
+ candidates = [default_value]
39
+ else
40
+ # completion: look which completion string starts with what we've typed
41
+ # TODO: don't search for the whole current_line, but also substrings.
42
+ # example: current_file = "some foob" and completion_strings = ["foobar"]
43
+ candidates = completion_strings.select {|str| str.index(current_line) == 0}
44
+ end
45
+ candidates
46
+ end
47
+ Readline.completion_append_character = "" # per default a space will be append
48
+ begin
49
+ value = Readline.readline promt, add_to_history
50
+ rescue Interrupt
51
+ puts # just to have the linebreak
52
+ value = default_value
53
+ end
54
+ return value
55
+ end
56
+ end # module Interaction
57
+ end # module Rutaci
@@ -0,0 +1,63 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'ftools'
19
+
20
+ require 'rutaci/getter'
21
+
22
+ module Rutaci
23
+ # renames files using a format string, uses the Getter
24
+ # it is a command executor, so it has tp provide an initializer which takes the options
25
+ # and a method 'run' which takes an array of filenames
26
+ class Renamer
27
+ def initialize(options)
28
+ @options = options
29
+ @getter = Getter.new options
30
+ if @options.interactive
31
+ require 'rutaci/interaction'
32
+ puts "in interactive mode you can edit the new filename before renaming"
33
+ Interaction::print_lineedit_help
34
+ puts
35
+ end
36
+ end
37
+
38
+ # invoke this executor for an array of filenames
39
+ def run(files)
40
+ files.each do |file|
41
+ self.rename(file)
42
+ end
43
+ end
44
+
45
+ # get and return the actual info for a specific file
46
+ def rename(file)
47
+ puts "current file: \"#{file}\""
48
+ new_name = File.join @options.destination, @getter.get(file).strip
49
+ new_name = Interaction::lineedit " new name: ", new_name if @options.interactive
50
+ if new_name.empty?
51
+ puts " can't rename to an empty filename!"
52
+ return
53
+ end
54
+ if @options.dry_run
55
+ puts " renaming to: \"#{new_name}\" (if we where not doing a dry-run)"
56
+ else
57
+ puts " renaming to: \"#{new_name}\""
58
+ File.makedirs File.dirname(new_name) # create missing directories
59
+ File.move file, new_name
60
+ end
61
+ end
62
+ end # class Renamer
63
+ end # module Rutaci
@@ -0,0 +1,71 @@
1
+ # rutaci is a ruby tagger with a command line interface
2
+ # Copyright (C) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU General Public License
6
+ # as published by the Free Software Foundation; either version 2
7
+ # of the License, or (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software
16
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
+
18
+ require 'rtaglib'
19
+
20
+ require 'rutaci/source'
21
+
22
+ module Rutaci
23
+ # writes info from a source into the files
24
+ # it is a command executor, so it has tp provide an initializer which takes the options
25
+ # and a method 'run' which takes an array of filenames
26
+ class Setter
27
+ def initialize(options)
28
+ @options = options
29
+ if @options.interactive
30
+ require 'rutaci/interaction'
31
+ puts "Using interactive mode you can specify the value for the current field."
32
+ Interaction::print_lineedit_help
33
+ puts
34
+ end
35
+ end
36
+
37
+ # invoke this executor for an array of filenames
38
+ def run(files)
39
+ files.each do |file|
40
+ if @options.dry_run
41
+ puts "dry run for #{file}:"
42
+ else
43
+ puts "processing #{file}:"
44
+ end
45
+ self.set(file)
46
+ puts unless file == files.last # seperator between the files
47
+ end
48
+ end
49
+
50
+ # gets writes the actual info into a specific file
51
+ def set(file)
52
+ source = Source.factory file, @options
53
+ tagfile = TagFile::File.new file
54
+ source.info.each_pair do |key, value|
55
+ value = Interaction::lineedit " #{key.to_s.capitalize}: ", value if @options.interactive
56
+ if value.empty? and not @options.keep_empty_fields
57
+ puts " ignoring empty value"
58
+ next
59
+ end
60
+ puts " setting #{key} to \"#{value}\""
61
+ tagfile.send key.to_s+"=", value unless @options.dry_run
62
+ end
63
+ if @options.dry_run
64
+ puts " writing the metadata (if it was not a dry run ;-)"
65
+ else
66
+ puts " writing the metadata"
67
+ tagfile.save
68
+ end
69
+ end
70
+ end # class Getter
71
+ end # module Rutaci