tagomatic 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +30 -1
- data/VERSION +1 -1
- data/lib/tagomatic/format_compiler.rb +11 -16
- data/lib/tagomatic/known_formats.rb +45 -0
- data/lib/tagomatic/options_parser.rb +13 -9
- data/lib/tagomatic/tagger.rb +4 -46
- data/lib/tagomatic/tags.rb +39 -0
- metadata +33 -2
data/README.rdoc
CHANGED
@@ -7,12 +7,14 @@ Another mp3 tagger the world does not need.
|
|
7
7
|
But I needed it. I have a large collection of old mp3 files. From times when tagging was mostly
|
8
8
|
based on the file and folder names. When v2 tags where nowhere close..
|
9
9
|
|
10
|
+
== Overview
|
11
|
+
|
10
12
|
Modes of operation:
|
11
13
|
|
12
14
|
* The tagger will try to guess the tags from the full file path by applying a set of known formats.
|
13
15
|
* The tagger will apply specific tags given on the command-line.
|
14
16
|
* The tagger will match specific formats given on the command-line.
|
15
|
-
*
|
17
|
+
* Arbitrary combination of the before-mentioned modes.
|
16
18
|
|
17
19
|
The scanner supports recursive folder handling. Of course.
|
18
20
|
|
@@ -20,6 +22,33 @@ Right now v2 tags are the focus.
|
|
20
22
|
|
21
23
|
It is probably best to call this alpha ware.
|
22
24
|
|
25
|
+
== Usage
|
26
|
+
|
27
|
+
For my genre/artist/album/track.mp3 collection I use this invocation pattern:
|
28
|
+
|
29
|
+
tagomatic --underscores --guess --recurse --showtags --errorstops --cleantags /media/music/
|
30
|
+
|
31
|
+
Then I add folder-specific .tagomatic or .format= files whenever an error occurs.
|
32
|
+
|
33
|
+
== The .tagomatic file
|
34
|
+
|
35
|
+
You can put the (long version) of the command line options into folder-specific .tagomatic files.
|
36
|
+
These options are then valid only for this folder and sub-folders.
|
37
|
+
|
38
|
+
This is useful - for example - if you want to switch guessing off for sub-folders.
|
39
|
+
|
40
|
+
== The .format= files
|
41
|
+
|
42
|
+
You can add files named .format= to sub-folders. They will be picked up by tagomatic and added as
|
43
|
+
custom formats just as if you would have passed them on the command line using the --format option.
|
44
|
+
|
45
|
+
Because the slash is not allowed in file names you have to replace it with a vertical dash like in
|
46
|
+
this example:
|
47
|
+
|
48
|
+
.format=%g|%a|%b|%n - %t.mp3
|
49
|
+
|
50
|
+
These formats are valid only for this folder and sub-folders.
|
51
|
+
|
23
52
|
== Copyright
|
24
53
|
|
25
54
|
Copyright (c) 2009 Daniel Lukic. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
@@ -1,15 +1,10 @@
|
|
1
|
+
require 'tagomatic/tags'
|
2
|
+
|
1
3
|
module Tagomatic
|
2
4
|
|
3
5
|
class FormatCompiler
|
4
6
|
|
5
|
-
|
6
|
-
FORMAT_REGEXP_ALBUM = '([^\/]+)'
|
7
|
-
FORMAT_REGEXP_DISC = '\s*([0-9]+)\s*'
|
8
|
-
FORMAT_REGEXP_GENRE = '([^\/]+)'
|
9
|
-
FORMAT_REGEXP_IGNORE = '([^\/]+)'
|
10
|
-
FORMAT_REGEXP_TITLE = '([^\/]+)'
|
11
|
-
FORMAT_REGEXP_TRACKNUM = '\s*([0-9]+)\s*'
|
12
|
-
FORMAT_REGEXP_YEAR = '\s*([0-9]+)\s*'
|
7
|
+
include Tagomatic::Tags
|
13
8
|
|
14
9
|
def initialize(format_matcher_factory)
|
15
10
|
@format_matcher_factory = format_matcher_factory
|
@@ -24,14 +19,14 @@ module Tagomatic
|
|
24
19
|
tag = tag_and_tail[0, 1]
|
25
20
|
tail = tag_and_tail[1..-1]
|
26
21
|
tag_mapping << tag
|
27
|
-
regexp << FORMAT_REGEXP_ALBUM if tag ==
|
28
|
-
regexp << FORMAT_REGEXP_ARTIST if tag ==
|
29
|
-
regexp << FORMAT_REGEXP_DISC if tag ==
|
30
|
-
regexp << FORMAT_REGEXP_GENRE if tag ==
|
31
|
-
regexp << FORMAT_REGEXP_IGNORE if tag ==
|
32
|
-
regexp << FORMAT_REGEXP_TITLE if tag ==
|
33
|
-
regexp << FORMAT_REGEXP_TRACKNUM if tag ==
|
34
|
-
regexp << FORMAT_REGEXP_YEAR if tag ==
|
22
|
+
regexp << FORMAT_REGEXP_ALBUM if tag == FORMAT_ID_ALBUM
|
23
|
+
regexp << FORMAT_REGEXP_ARTIST if tag == FORMAT_ID_ARTIST
|
24
|
+
regexp << FORMAT_REGEXP_DISC if tag == FORMAT_ID_DISC
|
25
|
+
regexp << FORMAT_REGEXP_GENRE if tag == FORMAT_ID_GENRE
|
26
|
+
regexp << FORMAT_REGEXP_IGNORE if tag == FORMAT_ID_IGNORE
|
27
|
+
regexp << FORMAT_REGEXP_TITLE if tag == FORMAT_ID_TITLE
|
28
|
+
regexp << FORMAT_REGEXP_TRACKNUM if tag == FORMAT_ID_TRACKNUM
|
29
|
+
regexp << FORMAT_REGEXP_YEAR if tag == FORMAT_ID_YEAR
|
35
30
|
regexp << Regexp.escape(tail)
|
36
31
|
end
|
37
32
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Tagomatic
|
2
|
+
|
3
|
+
module KnownFormats
|
4
|
+
|
5
|
+
KNOWN_FORMATS = [
|
6
|
+
"%g/%a/%b/Disc%d/%n-%t.mp3",
|
7
|
+
"%g/%a/%b/Disc%d/%n%t.mp3",
|
8
|
+
"%g/%a/%b/Disc%d/%t.mp3",
|
9
|
+
"%g/%a/%b/CD%d/%n-%t.mp3",
|
10
|
+
"%g/%a/%b/CD%d/%n%t.mp3",
|
11
|
+
"%g/%a/%b/CD%d/%t.mp3",
|
12
|
+
"%g/%a/%b/cd%d/%n-%t.mp3",
|
13
|
+
"%g/%a/%b/cd%d/%n%t.mp3",
|
14
|
+
"%g/%a/%b/cd%d/%t.mp3",
|
15
|
+
|
16
|
+
"%g/%a/%b[%y]/%a-%b-%n-%t.mp3",
|
17
|
+
"%g/%a/%b[%y]/%n-%t.mp3",
|
18
|
+
"%g/%a/%b[%y]/%n%t.mp3",
|
19
|
+
|
20
|
+
"%g/%a/%b(%y)/%a-%b-%n-%t.mp3",
|
21
|
+
"%g/%a/%b(%y)/%n-%t.mp3",
|
22
|
+
"%g/%a/%b(%y)/%n%t.mp3",
|
23
|
+
|
24
|
+
"%g/%a/(%y)%b/%a-%b-%n-%t.mp3",
|
25
|
+
"%g/%a/(%y)%b/%n-%t.mp3",
|
26
|
+
"%g/%a/(%y)%b/%n%t.mp3",
|
27
|
+
|
28
|
+
"%g/%a/%y - %b/%a-%b-%n-%t.mp3",
|
29
|
+
"%g/%a/%y - %b/%n-%t.mp3",
|
30
|
+
"%g/%a/%y - %b/%n%t.mp3",
|
31
|
+
|
32
|
+
"%g/%a/%b/%a-%b-%n-%t.mp3",
|
33
|
+
"%g/%a/%b/%a-%b-%n-%t.MP3",
|
34
|
+
"%g/%a/%b/%n-%t.mp3",
|
35
|
+
"%g/%a/%b/%n-%t.MP3",
|
36
|
+
"%g/%a/%b/%n%t.mp3",
|
37
|
+
"%g/%a/%b/%n%t.MP3",
|
38
|
+
|
39
|
+
"%g/%a/%b/%t.mp3",
|
40
|
+
"%g/%a/%b/%t.MP3",
|
41
|
+
]
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -53,41 +53,45 @@ module Tagomatic
|
|
53
53
|
@options[:formats] << format
|
54
54
|
end
|
55
55
|
|
56
|
-
opts.on("-c", "--cleantags", "Clean up tags by removing artist and album from title for example.") do |cleantags|
|
56
|
+
opts.on("-c", "--[no-]cleantags", "Clean up tags by removing artist and album from title for example.") do |cleantags|
|
57
57
|
@options[:cleantags]= cleantags
|
58
58
|
end
|
59
|
-
opts.on("-k", "--cleartags", "Clear any existing v1 and v2 tags.") do |cleartags|
|
59
|
+
opts.on("-k", "--[no-]cleartags", "Clear any existing v1 and v2 tags.") do |cleartags|
|
60
60
|
@options[:cleartags]= cleartags
|
61
61
|
end
|
62
|
-
opts.on("-e", "--errorstops", "Stop execution if an error occurs.") do |errorstops|
|
62
|
+
opts.on("-e", "--[no-]errorstops", "Stop execution if an error occurs.") do |errorstops|
|
63
63
|
@options[:errorstops]= errorstops
|
64
64
|
end
|
65
|
-
opts.on("-s", "--guess", "Use format guessing. Can be combined with --format.") do |guess|
|
65
|
+
opts.on("-s", "--[no-]guess", "Use format guessing. Can be combined with --format.") do |guess|
|
66
66
|
@options[:guess] = guess
|
67
67
|
end
|
68
|
-
opts.on("-l", "--list", "List available formats for guessing.") do |list|
|
68
|
+
opts.on("-l", "--[no-]list", "List available formats for guessing.") do |list|
|
69
69
|
@options[:list] = list
|
70
70
|
end
|
71
|
-
opts.on("-r", "--recurse", "Scan for files recursively.") do |recurse|
|
71
|
+
opts.on("-r", "--[no-]recurse", "Scan for files recursively.") do |recurse|
|
72
72
|
@options[:recurse] = recurse
|
73
73
|
end
|
74
|
-
opts.on("-w", "--showtags", "Show the resulting tags.") do |showtags|
|
74
|
+
opts.on("-w", "--[no-]showtags", "Show the resulting tags.") do |showtags|
|
75
75
|
@options[:showtags] = showtags
|
76
76
|
end
|
77
|
-
opts.on("-u", "--underscores", "Replace underscores with spaces before processing a file name.") do |underscores|
|
77
|
+
opts.on("-u", "--[no-]underscores", "Replace underscores with spaces before processing a file name.") do |underscores|
|
78
78
|
@options[:underscores] = underscores
|
79
79
|
end
|
80
80
|
|
81
81
|
opts.separator ""
|
82
82
|
opts.separator "Common options:"
|
83
83
|
|
84
|
-
opts.on("-v", "--verbose", "Run verbosely.") do |verbose|
|
84
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely.") do |verbose|
|
85
85
|
@options[:verbose] = verbose
|
86
86
|
end
|
87
87
|
opts.on_tail("-h", "--help", "Show this message") do
|
88
88
|
puts opts
|
89
89
|
exit
|
90
90
|
end
|
91
|
+
opts.on_tail("--help-format", "Show help on writing --format strings") do
|
92
|
+
puts File.read(File.join(File.dirname($0), '..', 'lib/tagomatic/tags.rb'))
|
93
|
+
exit
|
94
|
+
end
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
data/lib/tagomatic/tagger.rb
CHANGED
@@ -2,57 +2,15 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
require 'monkey/id3v2'
|
4
4
|
require 'tagomatic/info_updater'
|
5
|
+
require 'tagomatic/known_formats'
|
6
|
+
require 'tagomatic/tags'
|
5
7
|
|
6
8
|
module Tagomatic
|
7
9
|
|
8
10
|
class Tagger
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
FORMAT_ID_DISC = 'd'
|
13
|
-
FORMAT_ID_GENRE = 'g'
|
14
|
-
FORMAT_ID_IGNORE = 'i'
|
15
|
-
FORMAT_ID_TITLE = 't'
|
16
|
-
FORMAT_ID_TRACKNUM = 'n'
|
17
|
-
FORMAT_ID_YEAR = 'y'
|
18
|
-
|
19
|
-
KNOWN_FORMATS = [
|
20
|
-
"%g/%a/%b/Disc%d/%n-%t.mp3",
|
21
|
-
"%g/%a/%b/Disc%d/%n%t.mp3",
|
22
|
-
"%g/%a/%b/Disc%d/%t.mp3",
|
23
|
-
"%g/%a/%b/CD%d/%n-%t.mp3",
|
24
|
-
"%g/%a/%b/CD%d/%n%t.mp3",
|
25
|
-
"%g/%a/%b/CD%d/%t.mp3",
|
26
|
-
"%g/%a/%b/cd%d/%n-%t.mp3",
|
27
|
-
"%g/%a/%b/cd%d/%n%t.mp3",
|
28
|
-
"%g/%a/%b/cd%d/%t.mp3",
|
29
|
-
|
30
|
-
"%g/%a/%b[%y]/%a-%b-%n-%t.mp3",
|
31
|
-
"%g/%a/%b[%y]/%n-%t.mp3",
|
32
|
-
"%g/%a/%b[%y]/%n%t.mp3",
|
33
|
-
|
34
|
-
"%g/%a/%b(%y)/%a-%b-%n-%t.mp3",
|
35
|
-
"%g/%a/%b(%y)/%n-%t.mp3",
|
36
|
-
"%g/%a/%b(%y)/%n%t.mp3",
|
37
|
-
|
38
|
-
"%g/%a/(%y)%b/%a-%b-%n-%t.mp3",
|
39
|
-
"%g/%a/(%y)%b/%n-%t.mp3",
|
40
|
-
"%g/%a/(%y)%b/%n%t.mp3",
|
41
|
-
|
42
|
-
"%g/%a/%y - %b/%a-%b-%n-%t.mp3",
|
43
|
-
"%g/%a/%y - %b/%n-%t.mp3",
|
44
|
-
"%g/%a/%y - %b/%n%t.mp3",
|
45
|
-
|
46
|
-
"%g/%a/%b/%a-%b-%n-%t.mp3",
|
47
|
-
"%g/%a/%b/%a-%b-%n-%t.MP3",
|
48
|
-
"%g/%a/%b/%n-%t.mp3",
|
49
|
-
"%g/%a/%b/%n-%t.MP3",
|
50
|
-
"%g/%a/%b/%n%t.mp3",
|
51
|
-
"%g/%a/%b/%n%t.MP3",
|
52
|
-
|
53
|
-
"%g/%a/%b/%t.mp3",
|
54
|
-
"%g/%a/%b/%t.MP3",
|
55
|
-
]
|
12
|
+
include Tagomatic::Tags
|
13
|
+
include Tagomatic::KnownFormats
|
56
14
|
|
57
15
|
def initialize(options, compiler, mp3info, info_updater_factory, logger)
|
58
16
|
@options = options
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Tagomatic
|
2
|
+
|
3
|
+
module Tags
|
4
|
+
|
5
|
+
# Use these like this on the command line:
|
6
|
+
# --format "%g/%a/%b (%y)/%n - %t.mp3"
|
7
|
+
#
|
8
|
+
# Or use them like this in folder-specific .format= file names:
|
9
|
+
# touch ".format=%g|%a|%b (%y)|%n - %t.mp3"
|
10
|
+
#
|
11
|
+
# Some more examples showing what you can do:
|
12
|
+
#
|
13
|
+
# * Using %i (ignore) to swallow trash after album name:
|
14
|
+
# --format "%g/%a/%b - %i - %y/%n - %t.mp3"
|
15
|
+
#
|
16
|
+
# * Specifying text to be skipped:
|
17
|
+
# --format "%g/%a/%b - encoded by noone - %y/%n - %t.mp3"
|
18
|
+
|
19
|
+
FORMAT_ID_ARTIST = 'a'
|
20
|
+
FORMAT_ID_ALBUM = 'b'
|
21
|
+
FORMAT_ID_DISC = 'd'
|
22
|
+
FORMAT_ID_GENRE = 'g'
|
23
|
+
FORMAT_ID_IGNORE = 'i'
|
24
|
+
FORMAT_ID_TITLE = 't'
|
25
|
+
FORMAT_ID_TRACKNUM = 'n'
|
26
|
+
FORMAT_ID_YEAR = 'y'
|
27
|
+
|
28
|
+
FORMAT_REGEXP_ARTIST = '([^\/]+)'
|
29
|
+
FORMAT_REGEXP_ALBUM = '([^\/]+)'
|
30
|
+
FORMAT_REGEXP_DISC = '\s*([0-9]+)\s*'
|
31
|
+
FORMAT_REGEXP_GENRE = '([^\/]+)'
|
32
|
+
FORMAT_REGEXP_IGNORE = '([^\/]+)'
|
33
|
+
FORMAT_REGEXP_TITLE = '([^\/]+)'
|
34
|
+
FORMAT_REGEXP_TRACKNUM = '\s*([0-9]+)\s*'
|
35
|
+
FORMAT_REGEXP_YEAR = '\s*([0-9]+)\s*'
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tagomatic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Lukic
|
@@ -42,12 +42,14 @@ description: |
|
|
42
42
|
But I needed it. I have a large collection of old mp3 files. From times when tagging was mostly
|
43
43
|
based on the file and folder names. When v2 tags where nowhere close..
|
44
44
|
|
45
|
+
== Overview
|
46
|
+
|
45
47
|
Modes of operation:
|
46
48
|
|
47
49
|
* The tagger will try to guess the tags from the full file path by applying a set of known formats.
|
48
50
|
* The tagger will apply specific tags given on the command-line.
|
49
51
|
* The tagger will match specific formats given on the command-line.
|
50
|
-
*
|
52
|
+
* Arbitrary combination of the before-mentioned modes.
|
51
53
|
|
52
54
|
The scanner supports recursive folder handling. Of course.
|
53
55
|
|
@@ -55,6 +57,33 @@ description: |
|
|
55
57
|
|
56
58
|
It is probably best to call this alpha ware.
|
57
59
|
|
60
|
+
== Usage
|
61
|
+
|
62
|
+
For my genre/artist/album/track.mp3 collection I use this invocation pattern:
|
63
|
+
|
64
|
+
tagomatic --underscores --guess --recurse --showtags --errorstops --cleantags /media/music/
|
65
|
+
|
66
|
+
Then I add folder-specific .tagomatic or .format= files whenever an error occurs.
|
67
|
+
|
68
|
+
== The .tagomatic file
|
69
|
+
|
70
|
+
You can put the (long version) of the command line options into folder-specific .tagomatic files.
|
71
|
+
These options are then valid only for this folder and sub-folders.
|
72
|
+
|
73
|
+
This is useful - for example - if you want to switch guessing off for sub-folders.
|
74
|
+
|
75
|
+
== The .format= files
|
76
|
+
|
77
|
+
You can add files named .format= to sub-folders. They will be picked up by tagomatic and added as
|
78
|
+
custom formats just as if you would have passed them on the command line using the --format option.
|
79
|
+
|
80
|
+
Because the slash is not allowed in file names you have to replace it with a vertical dash like in
|
81
|
+
this example:
|
82
|
+
|
83
|
+
.format=%g|%a|%b|%n - %t.mp3
|
84
|
+
|
85
|
+
These formats are valid only for this folder and sub-folders.
|
86
|
+
|
58
87
|
== Copyright
|
59
88
|
|
60
89
|
Copyright (c) 2009 Daniel Lukic. See LICENSE for details.
|
@@ -89,6 +118,7 @@ files:
|
|
89
118
|
- lib/tagomatic/format_compiler.rb
|
90
119
|
- lib/tagomatic/format_matcher.rb
|
91
120
|
- lib/tagomatic/info_updater.rb
|
121
|
+
- lib/tagomatic/known_formats.rb
|
92
122
|
- lib/tagomatic/local_options_matcher.rb
|
93
123
|
- lib/tagomatic/logger.rb
|
94
124
|
- lib/tagomatic/main.rb
|
@@ -99,6 +129,7 @@ files:
|
|
99
129
|
- lib/tagomatic/scanner.rb
|
100
130
|
- lib/tagomatic/system_configuration.rb
|
101
131
|
- lib/tagomatic/tagger.rb
|
132
|
+
- lib/tagomatic/tags.rb
|
102
133
|
- lib/tasks/test_data.rb
|
103
134
|
- test/data/mp3_template_file
|
104
135
|
- test/data/sorted/80s/Peter_Schilling/1982 Fehler im System/album.dat
|