mp3renamer 0.0.1
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.
- data/.svnignore +4 -0
- data/History.txt +4 -0
- data/Manifest.txt +0 -0
- data/README.txt +48 -0
- data/Rakefile +30 -0
- data/bin/mp3renamer.rb +174 -0
- data/lib/mp3/album.rb +114 -0
- data/lib/mp3/disc.rb +96 -0
- data/lib/mp3/renamer.rb +113 -0
- data/lib/mp3/track.rb +101 -0
- data/lib/mp3renamer.rb +49 -0
- data/lib/utils/formatter.rb +58 -0
- data/lib/utils/parser.rb +34 -0
- data/spec/mp3renamer_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +300 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/test/test_mp3renamer.rb +0 -0
- metadata +92 -0
data/.svnignore
ADDED
data/History.txt
ADDED
data/Manifest.txt
ADDED
File without changes
|
data/README.txt
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
mp3renamer
|
2
|
+
by FIXME (your name)
|
3
|
+
FIXME (url)
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
FIXME (describe your package)
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIXME (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
FIXME (code sample of usage)
|
16
|
+
|
17
|
+
== REQUIREMENTS:
|
18
|
+
|
19
|
+
* FIXME (list of requirements)
|
20
|
+
|
21
|
+
== INSTALL:
|
22
|
+
|
23
|
+
* FIXME (sudo gem install, anything else)
|
24
|
+
|
25
|
+
== LICENSE:
|
26
|
+
|
27
|
+
(The MIT License)
|
28
|
+
|
29
|
+
Copyright (c) 2008 FIXME (different license?)
|
30
|
+
|
31
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
32
|
+
a copy of this software and associated documentation files (the
|
33
|
+
'Software'), to deal in the Software without restriction, including
|
34
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
35
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
36
|
+
permit persons to whom the Software is furnished to do so, subject to
|
37
|
+
the following conditions:
|
38
|
+
|
39
|
+
The above copyright notice and this permission notice shall be
|
40
|
+
included in all copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
43
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
44
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
45
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
46
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
47
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
48
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_in_path 'lib'
|
17
|
+
require 'mp3renamer'
|
18
|
+
|
19
|
+
task :default => 'spec:run'
|
20
|
+
|
21
|
+
PROJ.name = 'mp3renamer'
|
22
|
+
PROJ.authors = 'FIXME (who is writing this software)'
|
23
|
+
PROJ.email = 'FIXME (your e-mail)'
|
24
|
+
PROJ.url = 'FIXME (project homepage)'
|
25
|
+
PROJ.version = Mp3renamer::VERSION
|
26
|
+
PROJ.rubyforge.name = 'mp3renamer'
|
27
|
+
|
28
|
+
PROJ.spec.opts << '--color'
|
29
|
+
|
30
|
+
# EOF
|
data/bin/mp3renamer.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
#!C:\ruby\bin\ruby.exe
|
2
|
+
|
3
|
+
require File.expand_path(
|
4
|
+
File.join(File.dirname(__FILE__), %w[.. lib mp3renamer]))
|
5
|
+
require 'rubygems'
|
6
|
+
require 'cooloptions'
|
7
|
+
require 'mp3info'
|
8
|
+
require 'pp'
|
9
|
+
|
10
|
+
$:.unshift(File.join(File.dirname($0), 'lib'))
|
11
|
+
$:.unshift(File.join(File.dirname($0), '..', 'lib'))
|
12
|
+
$:.unshift("./lib/")
|
13
|
+
|
14
|
+
require 'mp3/album'
|
15
|
+
require 'mp3/disc'
|
16
|
+
require 'mp3/renamer'
|
17
|
+
require 'mp3/track'
|
18
|
+
|
19
|
+
#
|
20
|
+
# constants
|
21
|
+
#
|
22
|
+
CURRENT_DIR = 'base name of the CURRENT directory'
|
23
|
+
PARENT_DIR = 'base name of the PARENT directory'
|
24
|
+
|
25
|
+
#
|
26
|
+
# globals
|
27
|
+
#
|
28
|
+
temp_dir = File::expand_path(ENV['TEMP'] || File::SEPARATOR)
|
29
|
+
puts "Temporary directory is \"#{temp_dir}\"" if $DEBUG
|
30
|
+
|
31
|
+
source_dir = Dir::pwd
|
32
|
+
puts "Source directory is \"#{source_dir}\"" if $DEBUG
|
33
|
+
|
34
|
+
target_dir = File.join(temp_dir, 'renamed_mp3_files')
|
35
|
+
puts "Target directory is \"#{target_dir}\"" if $DEBUG
|
36
|
+
|
37
|
+
album_artist = PARENT_DIR
|
38
|
+
album_title = CURRENT_DIR
|
39
|
+
album_year = Time::new.year.to_s
|
40
|
+
puts "Current Year is \"#{album_year}\"" if $DEBUG
|
41
|
+
|
42
|
+
puts ''
|
43
|
+
|
44
|
+
options = CoolOptions.parse!('[options] SOURCE-DIRECTORY') do |cooloptions|
|
45
|
+
|
46
|
+
cooloptions.desc ' '
|
47
|
+
cooloptions.desc 'This program takes an MP3 audiobook and renames the subdirs and files using a consistent naming convention.'
|
48
|
+
cooloptions.desc 'It also updates the ID3v1 and ID3v2 tags for artist, album, track number, track title, genre, and year.'
|
49
|
+
cooloptions.desc ' '
|
50
|
+
|
51
|
+
cooloptions.desc ' '
|
52
|
+
cooloptions.desc 'NOTES'
|
53
|
+
cooloptions.desc ' '
|
54
|
+
cooloptions.desc '(1) The following source directory structure is assumed for this program:'
|
55
|
+
cooloptions.desc ' '
|
56
|
+
cooloptions.desc ' <artist>'
|
57
|
+
cooloptions.desc ' |'
|
58
|
+
cooloptions.desc ' `--- <album> <==== this is the SOURCE-DIRECTORY command line parameter.'
|
59
|
+
cooloptions.desc ' |'
|
60
|
+
cooloptions.desc ' +--- <disc 1>'
|
61
|
+
cooloptions.desc ' | |'
|
62
|
+
cooloptions.desc ' | +--- <disc 1 track 1>.mp3'
|
63
|
+
cooloptions.desc ' | +--- <disc 1 track 2>.mp3'
|
64
|
+
cooloptions.desc ' | | ...'
|
65
|
+
cooloptions.desc ' | `--- <disc 1 track N1>.mp3'
|
66
|
+
cooloptions.desc ' |'
|
67
|
+
cooloptions.desc ' +--- <disc 2>'
|
68
|
+
cooloptions.desc ' | |'
|
69
|
+
cooloptions.desc ' | +--- <disc 2 track 1>.mp3'
|
70
|
+
cooloptions.desc ' | +--- <disc 2 track 2>.mp3'
|
71
|
+
cooloptions.desc ' | | ...'
|
72
|
+
cooloptions.desc ' | `--- <disc 2 track N1>.mp3'
|
73
|
+
cooloptions.desc ' |'
|
74
|
+
cooloptions.desc ' | ...'
|
75
|
+
cooloptions.desc ' |'
|
76
|
+
cooloptions.desc ' `--- <disc M>'
|
77
|
+
cooloptions.desc ' |'
|
78
|
+
cooloptions.desc ' +--- <disc M track 1>.mp3'
|
79
|
+
cooloptions.desc ' +--- <disc M track 2>.mp3'
|
80
|
+
cooloptions.desc ' | ...'
|
81
|
+
cooloptions.desc ' `--- <disc M track NM>.mp3'
|
82
|
+
cooloptions.desc ' '
|
83
|
+
cooloptions.desc ' '
|
84
|
+
cooloptions.desc '(2) The following output directory structure will be created:'
|
85
|
+
cooloptions.desc ' '
|
86
|
+
cooloptions.desc ' <output-directory> <==== this is value of the --output command line parameter.'
|
87
|
+
cooloptions.desc ' |'
|
88
|
+
cooloptions.desc ' `--- <artist>'
|
89
|
+
cooloptions.desc ' |'
|
90
|
+
cooloptions.desc ' `--- <album>'
|
91
|
+
cooloptions.desc ' |'
|
92
|
+
cooloptions.desc ' +--- <album> [D01.MM]'
|
93
|
+
cooloptions.desc ' | |'
|
94
|
+
cooloptions.desc ' | +--- D01.MM-T01.N1.mp3'
|
95
|
+
cooloptions.desc ' | +--- D01.MM-T02.N1.mp3'
|
96
|
+
cooloptions.desc ' | | ...'
|
97
|
+
cooloptions.desc ' | `--- D01.MM-TN1.N1.mp3'
|
98
|
+
cooloptions.desc ' |'
|
99
|
+
cooloptions.desc ' +--- <album> [D02.MM]'
|
100
|
+
cooloptions.desc ' | |'
|
101
|
+
cooloptions.desc ' | +--- D02.MM-T01.N2.mp3'
|
102
|
+
cooloptions.desc ' | +--- D02.MM-T02.N2.mp3'
|
103
|
+
cooloptions.desc ' | | ...'
|
104
|
+
cooloptions.desc ' | `--- D02.MM-TN2.N2.mp3'
|
105
|
+
cooloptions.desc ' |'
|
106
|
+
cooloptions.desc ' | ...'
|
107
|
+
cooloptions.desc ' |'
|
108
|
+
cooloptions.desc ' `--- <album> [DMM.MM]'
|
109
|
+
cooloptions.desc ' |'
|
110
|
+
cooloptions.desc ' +--- DMM.MM-T01.NN.mp3'
|
111
|
+
cooloptions.desc ' +--- DMM.MM-T02.NN.mp3'
|
112
|
+
cooloptions.desc ' | ...'
|
113
|
+
cooloptions.desc ' `--- DMM.MM-TNN.NN.mp3'
|
114
|
+
cooloptions.desc ' '
|
115
|
+
cooloptions.desc ' '
|
116
|
+
|
117
|
+
cooloptions.desc ' '
|
118
|
+
cooloptions.desc 'OPTIONS'
|
119
|
+
cooloptions.desc ' '
|
120
|
+
|
121
|
+
cooloptions.on 'output DIRECTORY' , 'Directory into which the renamed files will be written.', target_dir
|
122
|
+
cooloptions.desc ' '
|
123
|
+
|
124
|
+
cooloptions.on 'artist ARTIST-NAME', 'Name of the album\'s artist.', album_artist
|
125
|
+
cooloptions.desc ' '
|
126
|
+
cooloptions.on 'title ALBUM-TITLE' , 'Title of the album.', album_title
|
127
|
+
cooloptions.desc ' '
|
128
|
+
cooloptions.on 'year RELEASE-YEAR' , 'Year of the album\'s release.', album_year
|
129
|
+
cooloptions.desc ' '
|
130
|
+
|
131
|
+
cooloptions.on 'copy-files' , 'Copy files from source directory into output directory.', true
|
132
|
+
cooloptions.desc ' '
|
133
|
+
cooloptions.on 'update-id3v(1)-tags', 'Update ID3v1 tags for artist, album, track number, track title, genre, and year.', true
|
134
|
+
cooloptions.desc ' '
|
135
|
+
cooloptions.on 'update-id3v(2)-tags', 'Update ID3v2 tags for artist, album, track number, track title, genre, and year.', true
|
136
|
+
|
137
|
+
cooloptions.after do |result|
|
138
|
+
if result.year !~ /^(\d\d\d\d)$/
|
139
|
+
cooloptions.error("\nERROR: Invalid year: \"#{result.year}\"\n\n")
|
140
|
+
else
|
141
|
+
album_year = result.year
|
142
|
+
end
|
143
|
+
|
144
|
+
target_dir = result.output
|
145
|
+
album_artist = (result.artist != PARENT_DIR) ? result.artist : nil
|
146
|
+
album_title = (result.title != CURRENT_DIR) ? result.title : nil
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
if $DEBUG
|
152
|
+
puts "Source directory is \"#{source_dir}\""
|
153
|
+
puts "Target directory is \"#{target_dir}\""
|
154
|
+
puts "Album artist is \"#{album_artist}\""
|
155
|
+
puts "Album title is \"#{album_title}\""
|
156
|
+
puts "Album year is \"#{album_year}\""
|
157
|
+
end
|
158
|
+
|
159
|
+
if ARGV.size == 0
|
160
|
+
ARGV << '.'
|
161
|
+
end
|
162
|
+
|
163
|
+
ARGV.each do |src_dir|
|
164
|
+
renamer = Mp3::Renamer.new
|
165
|
+
renamer.album_artist = album_artist if defined? album_artist
|
166
|
+
renamer.album_title = album_title if defined? album_title
|
167
|
+
renamer.album_year = album_year
|
168
|
+
|
169
|
+
renamer.read_album(src_dir)
|
170
|
+
renamer.rename_tracks
|
171
|
+
renamer.write_album(target_dir)
|
172
|
+
renamer.update_id3_tags(target_dir)
|
173
|
+
end
|
174
|
+
puts ''
|
data/lib/mp3/album.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'mp3/disc'
|
2
|
+
require 'utils/parser'
|
3
|
+
|
4
|
+
class Mp3
|
5
|
+
|
6
|
+
#
|
7
|
+
# This class presents an album, consisting of one of more physical media
|
8
|
+
# (LPs, CDs, tapes), each of which is referred to as a disc.
|
9
|
+
#
|
10
|
+
# An instance of this class holds:
|
11
|
+
# * the name of the album's artist;
|
12
|
+
# * the title of the album;
|
13
|
+
# * year of release;
|
14
|
+
# * and an array of Disc instances, each of which describes
|
15
|
+
# just one of the aforementioned physical media making up the album.
|
16
|
+
#
|
17
|
+
class Album
|
18
|
+
|
19
|
+
attr_accessor :album_artist
|
20
|
+
attr_accessor :album_title
|
21
|
+
attr_accessor :album_year
|
22
|
+
attr_reader :discs
|
23
|
+
|
24
|
+
#
|
25
|
+
# The constructor takes a hash of symbols and their corresponding values. Valid symbols are:
|
26
|
+
# * <b>:artist</b> => the name(s) of the artist(s) responsible for the album;
|
27
|
+
# * <b>:title</b> => the title of the album;
|
28
|
+
# * <b>:year</b> => the year of release.
|
29
|
+
#
|
30
|
+
# If the <b>:artist</b> and/or <b>:title</b> symbols are not specified, they are derived from the grandparent and parent
|
31
|
+
# directories, respectively.
|
32
|
+
#
|
33
|
+
def initialize(*args)
|
34
|
+
@discs = []
|
35
|
+
parse_args(nil, args)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# This method is used to add a Disc instance to the [current] album instance.
|
40
|
+
# Assumptions
|
41
|
+
# * The order in which discs are appended _is_ the disc play order.
|
42
|
+
#
|
43
|
+
def add(item)
|
44
|
+
if item.class.name == Disc.name
|
45
|
+
@discs << item
|
46
|
+
end
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# This method is used to rename the album and all of its contained discs to a consistent format.
|
52
|
+
#
|
53
|
+
# Right now:
|
54
|
+
# * the <i>album level</i> album title is left unchanged;
|
55
|
+
# * the <i>disc level</i> album titles are set to "D<i>disc-number</i>.<i>number-of-discs</i>" for all of the
|
56
|
+
# discs in the album;
|
57
|
+
# * the <i>track level</i> album titles are also set to "D<i>disc-number</i>.<i>number-of-discs</i>" for all of the
|
58
|
+
# discs in the album;
|
59
|
+
# * the tracks are renamed recursively (see the Track class for details).
|
60
|
+
#
|
61
|
+
def rename
|
62
|
+
$track_number = 0
|
63
|
+
@discs.each do |disc|
|
64
|
+
printf("Renaming disc %02d : ", disc.disc_number); $stdout.flush
|
65
|
+
|
66
|
+
disc.album_artist = @album_artist
|
67
|
+
disc.album_title = @album_title
|
68
|
+
disc.album_year = @album_year
|
69
|
+
disc.rename(discs.size)
|
70
|
+
|
71
|
+
print "\n"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def write(dst_dir)
|
76
|
+
here = Dir.pwd
|
77
|
+
Dir.chdir dst_dir
|
78
|
+
@discs.each do |disc|
|
79
|
+
printf("Copying disc %02d : ", disc.disc_number); $stdout.flush
|
80
|
+
disc.write
|
81
|
+
puts ""
|
82
|
+
end
|
83
|
+
Dir.chdir here
|
84
|
+
end
|
85
|
+
|
86
|
+
def update_id3_tags(dst_dir)
|
87
|
+
here = Dir.pwd
|
88
|
+
Dir.chdir dst_dir
|
89
|
+
@discs.each do |disc|
|
90
|
+
print "Updating ID3 tags for disc #{disc.disc_number}"; $stdout.flush
|
91
|
+
disc.update_id3_tags
|
92
|
+
puts ""
|
93
|
+
end
|
94
|
+
Dir.chdir here
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
include Utils::Parser
|
100
|
+
|
101
|
+
def parse_string(name, value)
|
102
|
+
puts "album: parse_string(\"#{name}\", \"#{value}\")" if $DEBUG
|
103
|
+
|
104
|
+
if name.to_s == 'artist'; @album_artist = value
|
105
|
+
elsif name.to_s == 'title' ; @album_title = value
|
106
|
+
elsif name.to_s == 'year' ; @album_year = value
|
107
|
+
else
|
108
|
+
puts "Unknown keyword: \"#{name}\""
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end # Album
|
113
|
+
|
114
|
+
end # Mp3
|
data/lib/mp3/disc.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'mp3/track'
|
2
|
+
require 'utils/parser'
|
3
|
+
require 'utils/formatter'
|
4
|
+
|
5
|
+
class Mp3
|
6
|
+
|
7
|
+
class Disc
|
8
|
+
|
9
|
+
attr_accessor :disc_number
|
10
|
+
attr_accessor :disc_title
|
11
|
+
attr_accessor :album_artist
|
12
|
+
attr_accessor :album_title
|
13
|
+
attr_accessor :album_year
|
14
|
+
attr_reader :tracks
|
15
|
+
attr_accessor :separator
|
16
|
+
attr_accessor :prefix
|
17
|
+
attr_accessor :suffix
|
18
|
+
|
19
|
+
def initialize(*args)
|
20
|
+
@disc_title = ''
|
21
|
+
@tracks = []
|
22
|
+
@separator = '.'
|
23
|
+
@prefix = 'D'
|
24
|
+
@suffix = ''
|
25
|
+
parse_args(nil, args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add(item)
|
29
|
+
if item.class.name == Track.name
|
30
|
+
@tracks << item
|
31
|
+
end
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def rename(number_of_discs)
|
36
|
+
|
37
|
+
@disc_title = format(@prefix, @separator, @suffix, @disc_number, number_of_discs)
|
38
|
+
|
39
|
+
tracks.each do |track|
|
40
|
+
track.album_artist = @album_artist
|
41
|
+
track.album_title = @album_title
|
42
|
+
track.album_year = @album_year
|
43
|
+
track.rename(@disc_title, tracks.size)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def update_id3_tags
|
49
|
+
disc_subdir = "#{@album_title} [#{@disc_title}]"
|
50
|
+
|
51
|
+
here = Dir.pwd
|
52
|
+
Dir.chdir disc_subdir
|
53
|
+
|
54
|
+
@tracks.each do |track|
|
55
|
+
track.update_id3_tags
|
56
|
+
end
|
57
|
+
|
58
|
+
Dir.chdir here
|
59
|
+
end
|
60
|
+
|
61
|
+
def write
|
62
|
+
disc_subdir = "#{@album_title} [#{@disc_title}]"
|
63
|
+
if $DEBUG
|
64
|
+
print "\n\talbum title = #{@album_title}"
|
65
|
+
print "\n\tdisc title = #{@disc_title}"
|
66
|
+
print "\n\tdisc subdir = #{disc_subdir}"
|
67
|
+
end
|
68
|
+
File.makedirs(disc_subdir)
|
69
|
+
|
70
|
+
here = Dir.pwd
|
71
|
+
Dir.chdir disc_subdir
|
72
|
+
|
73
|
+
@tracks.each do |track|
|
74
|
+
track.write
|
75
|
+
end
|
76
|
+
|
77
|
+
Dir.chdir here
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
include Utils::Formatter
|
83
|
+
include Utils::Parser
|
84
|
+
|
85
|
+
def parse_string(name, value)
|
86
|
+
puts "album: parse_string(\"#{name}\", \"#{value}\")" if $DEBUG
|
87
|
+
|
88
|
+
if name.to_s == 'number'; @disc_number = value
|
89
|
+
else
|
90
|
+
puts "Unknown keyword: \"#{name}\""
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end # Disc
|
95
|
+
|
96
|
+
end # Mp3
|
data/lib/mp3/renamer.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'find'
|
3
|
+
require 'ftools'
|
4
|
+
|
5
|
+
require 'mp3/disc'
|
6
|
+
require 'utils/parser'
|
7
|
+
|
8
|
+
class Mp3
|
9
|
+
|
10
|
+
class Renamer
|
11
|
+
|
12
|
+
attr_accessor :album_artist
|
13
|
+
attr_accessor :album_title
|
14
|
+
attr_accessor :album_year
|
15
|
+
attr_accessor :album
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
@album_artist = nil
|
19
|
+
@album_title = nil
|
20
|
+
@album_year = nil
|
21
|
+
end # initialize
|
22
|
+
|
23
|
+
def read_album(src_dir)
|
24
|
+
here = Dir.pwd
|
25
|
+
|
26
|
+
Dir.chdir src_dir
|
27
|
+
|
28
|
+
puts "you are here: \"#{Dir.pwd}\"" if $DEBUG
|
29
|
+
|
30
|
+
@album_artist ||= File.basename(File.expand_path('..'))
|
31
|
+
@album_title ||= File.basename(File.expand_path('.'))
|
32
|
+
@album_year ||= '2008'
|
33
|
+
|
34
|
+
@album = Mp3::Album.new(:artist => @album_artist, :title => @album_title, :year => @album_year)
|
35
|
+
|
36
|
+
disc_number = 0
|
37
|
+
Dir['*'].sort.each do |e|
|
38
|
+
next if not File.directory?(e)
|
39
|
+
puts "\t#{e}" if $DEBUG
|
40
|
+
disc_number += 1
|
41
|
+
disc = Mp3::Disc::new(:number => disc_number)
|
42
|
+
here2 = Dir.pwd
|
43
|
+
Dir.chdir e
|
44
|
+
track_number = 0
|
45
|
+
Dir['*'].sort.each do |t|
|
46
|
+
if t =~ /\.((mp3)|(mp4)|(aac))$/
|
47
|
+
track_number += 1
|
48
|
+
track = Mp3::Track::new(:number => track_number, :file => t, :path => File.expand_path(t))
|
49
|
+
end
|
50
|
+
#puts "\t\t#{t}"
|
51
|
+
disc.add(track)
|
52
|
+
end
|
53
|
+
Dir.chdir here2
|
54
|
+
@album.add(disc)
|
55
|
+
end
|
56
|
+
Dir.chdir here
|
57
|
+
|
58
|
+
puts "Album artist : #{@album.album_artist}"
|
59
|
+
puts "Album title : #{@album.album_title}"
|
60
|
+
puts "Album year : #{@album.album_year}"
|
61
|
+
puts "Number of disc(s) : #{@album.discs.size}"
|
62
|
+
|
63
|
+
#pp(album) if $DEBUG
|
64
|
+
end # read
|
65
|
+
|
66
|
+
def rename_tracks
|
67
|
+
@album.rename
|
68
|
+
end # read
|
69
|
+
|
70
|
+
def update_id3_tags(dst_dir)
|
71
|
+
dst_dir = File.join(dst_dir, @album.album_artist, @album.album_title)
|
72
|
+
@album.update_id3_tags(dst_dir)
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_album(dst_dir)
|
76
|
+
#
|
77
|
+
# (1) create the output directory (if necessary)
|
78
|
+
# (2) create the individual disc subdirs
|
79
|
+
# (3) copy the track files per disc subdir
|
80
|
+
#
|
81
|
+
dst_dir = File.join(dst_dir, @album.album_artist, @album.album_title)
|
82
|
+
if File.exists?(dst_dir)
|
83
|
+
FileUtils.remove_dir(dst_dir, true)
|
84
|
+
puts "Deleted output dir: #{dst_dir}"
|
85
|
+
end
|
86
|
+
puts "Created output dir: #{dst_dir}"
|
87
|
+
File.makedirs(dst_dir)
|
88
|
+
|
89
|
+
here = Dir.pwd
|
90
|
+
Dir.chdir dst_dir
|
91
|
+
@album.write(dst_dir)
|
92
|
+
Dir.chdir here
|
93
|
+
end # read
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
include Utils::Parser
|
98
|
+
|
99
|
+
def parse_string(name, value)
|
100
|
+
puts "Rename: parse_string(\"#{name}\", \"#{value}\")" if $DEBUG
|
101
|
+
|
102
|
+
puts "Unknown keyword: \"#{name}\""
|
103
|
+
end # parse_string
|
104
|
+
|
105
|
+
def purge_dir_subtree(root)
|
106
|
+
Find.find(root) do |item|
|
107
|
+
puts "found: #{item}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end # Renamer
|
112
|
+
|
113
|
+
end # Mp3
|
data/lib/mp3/track.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'mp3info'
|
2
|
+
|
3
|
+
require 'utils/parser'
|
4
|
+
require 'utils/formatter'
|
5
|
+
|
6
|
+
class Mp3
|
7
|
+
|
8
|
+
class Track
|
9
|
+
|
10
|
+
attr_accessor :track_number
|
11
|
+
attr_accessor :track_title
|
12
|
+
attr_accessor :album_artist
|
13
|
+
attr_accessor :album_title
|
14
|
+
attr_accessor :album_year
|
15
|
+
attr_accessor :file
|
16
|
+
attr_accessor :path
|
17
|
+
attr_accessor :separator
|
18
|
+
attr_accessor :prefix
|
19
|
+
attr_accessor :suffix
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
@track_title = ''
|
23
|
+
@separator = '.'
|
24
|
+
@prefix = 'T'
|
25
|
+
@suffix = ''
|
26
|
+
parse_args(nil, args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def rename(disc_title, number_of_tracks)
|
30
|
+
print '.'; $stdout.flush
|
31
|
+
|
32
|
+
@track_title = disc_title + '-' + format(@prefix, @separator, @suffix, @track_number, number_of_tracks)
|
33
|
+
|
34
|
+
#print @track_title + "/"; $stdout.flush
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def update_id3_tags
|
39
|
+
print '.'; $stdout.flush
|
40
|
+
track_filename = "#{@track_title}.mp3"
|
41
|
+
$track_number += 1
|
42
|
+
if $DEBUG
|
43
|
+
print "\n\ttrack source file = #{@path}"
|
44
|
+
print "\n\ttrack filename = #{track_filename}"
|
45
|
+
print "\n\t@track number = #{@track_number}"
|
46
|
+
print "\n\t$track number = #{$track_number}"
|
47
|
+
end
|
48
|
+
Mp3Info.open(track_filename) do |mp3|
|
49
|
+
#
|
50
|
+
# ID3v1 tags
|
51
|
+
#
|
52
|
+
mp3.tag.tracknum = $track_number # @track_number.to_i
|
53
|
+
mp3.tag.title = @track_title
|
54
|
+
mp3.tag.artist = @album_artist
|
55
|
+
mp3.tag.album = @album_title
|
56
|
+
mp3.tag.year = @album_year
|
57
|
+
mp3.tag.genre_s = 'speech'
|
58
|
+
mp3.tag.comments = "Renamed on #{Time.now}"
|
59
|
+
|
60
|
+
#
|
61
|
+
# ID3v2 tags
|
62
|
+
#
|
63
|
+
mp3.tag2.TRK = $track_number # @track_number.to_i
|
64
|
+
mp3.tag2.TT2 = @track_title
|
65
|
+
mp3.tag2.TP2 = @album_artist
|
66
|
+
mp3.tag2.TAL = @album_title
|
67
|
+
mp3.tag2.TYE = @album_year
|
68
|
+
mp3.tag2.TCO = mp3.tag.genre_s
|
69
|
+
mp3.tag2.COM = mp3.tag.comments
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def write
|
74
|
+
print '.'; $stdout.flush
|
75
|
+
track_filename = "#{@track_title}.mp3"
|
76
|
+
if $DEBUG
|
77
|
+
print "\n\ttrack source file = #{@path}"
|
78
|
+
print "\n\ttrack filename = #{track_filename}"
|
79
|
+
end
|
80
|
+
File.copy(@path, track_filename, false)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
include Utils::Formatter
|
86
|
+
include Utils::Parser
|
87
|
+
|
88
|
+
def parse_string(track_title, value)
|
89
|
+
puts "album: parse_string(\"#{track_title}\", \"#{value}\")" if $DEBUG
|
90
|
+
|
91
|
+
if track_title.to_s == 'number'; @track_number = value
|
92
|
+
elsif track_title.to_s == 'file' ; @file = value
|
93
|
+
elsif track_title.to_s == 'path' ; @path = value
|
94
|
+
else
|
95
|
+
puts "Unknown keyword: \"#{track_title}\""
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end # Track
|
100
|
+
|
101
|
+
end # Mp3
|