rutaci 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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