tagomatic 0.1.2 → 0.1.3
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/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
|